1 /* 2 Copyright (C) 1998 T. Scott Dattalo 3 Copyright (C) 2013 Roy R. Rankin 4 5 6 This file is part of the libgpsim library of gpsim 7 8 This library is free software; you can redistribute it and/or 9 modify it under the terms of the GNU Lesser General Public 10 License as published by the Free Software Foundation; either 11 version 2.1 of the License, or (at your option) any later version. 12 13 This library is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 Lesser General Public License for more details. 17 18 You should have received a copy of the GNU Lesser General Public 19 License along with this library; if not, see 20 <http://www.gnu.org/licenses/lgpl-2.1.html>. 21 */ 22 23 24 #ifndef SRC_14_BIT_REGISTERS_H_ 25 #define SRC_14_BIT_REGISTERS_H_ 26 27 #include <string> 28 29 #include "gpsim_classes.h" 30 #include "registers.h" 31 #include "stimuli.h" 32 #include "trace.h" 33 #include "trigger.h" 34 35 #include "rcon.h" 36 #include "pir.h" 37 38 #include "tmr0.h" 39 40 class INTCON; 41 class pic_processor; 42 43 //--------------------------------------------------------- 44 // BORCON register 45 // 46 47 class BORCON : public sfr_register 48 { 49 public: 50 BORCON(Processor *, const char *pName, const char *pDesc = nullptr); 51 52 void put(unsigned int new_value); 53 void put_value(unsigned int new_value); 54 }; 55 56 57 //--------------------------------------------------------- 58 // BSR register 59 // 60 61 class BSR : public sfr_register 62 { 63 public: 64 BSR(Processor *, const char *pName, const char *pDesc = nullptr); 65 66 unsigned int register_page_bits = 0; 67 68 void put(unsigned int new_value); 69 void put_value(unsigned int new_value); 70 }; 71 72 73 //--------------------------------------------------------- 74 // FSR register 75 // 76 77 class FSR : public sfr_register 78 { 79 public: 80 FSR(Processor *, const char *pName, const char *pDesc = nullptr); 81 virtual void put(unsigned int new_value); 82 virtual void put_value(unsigned int new_value); 83 virtual unsigned int get(); 84 virtual unsigned int get_value(); 85 }; 86 87 88 //--------------------------------------------------------- 89 // FSR_12 register - FSR for the 12-bit core processors. 90 // 91 // 92 class FSR_12 : public FSR 93 { 94 public: 95 unsigned int valid_bits; 96 unsigned int register_page_bits; /* Only used by the 12-bit core to define 97 the valid paging bits in the FSR. */ 98 FSR_12(Processor *, const char *pName, 99 unsigned int _register_page_bits, unsigned int _valid_bits); 100 101 virtual void put(unsigned int new_value) override; 102 virtual void put_value(unsigned int new_value) override; 103 virtual unsigned int get() override; 104 virtual unsigned int get_value() override; 105 }; 106 107 108 //--------------------------------------------------------- 109 // Status register 110 // 111 class RCON; 112 113 class Status_register : public sfr_register 114 { 115 public: 116 117 #define STATUS_Z_BIT 2 118 #define STATUS_C_BIT 0 119 #define STATUS_DC_BIT 1 120 #define STATUS_PD_BIT 3 121 #define STATUS_TO_BIT 4 122 #define STATUS_OV_BIT 3 //18cxxx 123 #define STATUS_N_BIT 4 //18cxxx 124 #define STATUS_FSR0_BIT 4 //17c7xx 125 #define STATUS_FSR1_BIT 6 //17c7xx 126 #define STATUS_Z (1<<STATUS_Z_BIT) 127 #define STATUS_C (1<<STATUS_C_BIT) 128 #define STATUS_DC (1<<STATUS_DC_BIT) 129 #define STATUS_PD (1<<STATUS_PD_BIT) 130 #define STATUS_TO (1<<STATUS_TO_BIT) 131 #define STATUS_OV (1<<STATUS_OV_BIT) 132 #define STATUS_N (1<<STATUS_N_BIT) 133 #define STATUS_FSR0_MODE (3<<STATUS_FSR0_BIT) //17c7xx 134 #define STATUS_FSR1_MODE (3<<STATUS_FSR1_BIT) //17c7xx 135 #define BREAK_Z_ACCESS 2 136 #define BREAK_Z_WRITE 1 137 138 #define RP_MASK 0x20 139 unsigned int break_point = 0; 140 unsigned int break_on_z = 0, break_on_c = 0; 141 unsigned int rp_mask = RP_MASK; 142 unsigned int write_mask; // Bits that instructions can modify 143 RCON *rcon = nullptr; 144 145 Status_register(Processor *, const char *pName, const char *pDesc = nullptr); 146 void reset(RESET_TYPE r); 147 set_rcon(RCON * p_rcon)148 void set_rcon(RCON *p_rcon) 149 { 150 rcon = p_rcon; 151 } 152 153 virtual void put(unsigned int new_value); 154 get()155 inline unsigned int get() 156 { 157 get_trace().raw(read_trace.get() | value.get()); 158 return value.get(); 159 } 160 161 // Special member function to control just the Z bit 162 put_Z(unsigned int new_z)163 inline void put_Z(unsigned int new_z) 164 { 165 get_trace().raw(write_trace.get() | value.get()); 166 value.put((value.get() & ~STATUS_Z) | ((new_z) ? STATUS_Z : 0)); 167 } 168 get_Z()169 inline unsigned int get_Z() 170 { 171 get_trace().raw(read_trace.get() | value.get()); 172 return (((value.get() & STATUS_Z) == 0) ? 0 : 1); 173 } 174 175 176 // Special member function to control just the C bit put_C(unsigned int new_c)177 void put_C(unsigned int new_c) 178 { 179 get_trace().raw(write_trace.get() | value.get()); 180 value.put((value.get() & ~STATUS_C) | ((new_c) ? STATUS_C : 0)); 181 } 182 get_C()183 unsigned int get_C() 184 { 185 get_trace().raw(read_trace.get() | value.get()); 186 return (((value.get() & STATUS_C) == 0) ? 0 : 1); 187 } 188 189 // Special member function to set Z, C, and DC 190 put_Z_C_DC(unsigned int new_value,unsigned int src1,unsigned int src2)191 inline void put_Z_C_DC(unsigned int new_value, unsigned int src1, unsigned int src2) 192 { 193 get_trace().raw(write_trace.get() | value.get()); 194 value.put((value.get() & ~(STATUS_Z | STATUS_C | STATUS_DC)) | 195 ((new_value & 0xff) ? 0 : STATUS_Z) | 196 ((new_value & 0x100) ? STATUS_C : 0) | 197 (((new_value ^ src1 ^ src2) & 0x10) ? STATUS_DC : 0)); 198 } 199 put_Z_C_DC_for_sub(unsigned int new_value,unsigned int src1,unsigned int src2)200 inline void put_Z_C_DC_for_sub(unsigned int new_value, unsigned int src1, unsigned int src2) 201 { 202 get_trace().raw(write_trace.get() | value.get()); 203 value.put((value.get() & ~(STATUS_Z | STATUS_C | STATUS_DC)) | 204 ((new_value & 0xff) ? 0 : STATUS_Z) | 205 ((new_value & 0x100) ? 0 : STATUS_C) | 206 (((new_value ^ src1 ^ src2) & 0x10) ? 0 : STATUS_DC)); 207 } 208 put_PD(unsigned int new_pd)209 inline void put_PD(unsigned int new_pd) 210 { 211 if (rcon) 212 { 213 rcon->put_PD(new_pd); 214 215 } 216 else 217 { 218 get_trace().raw(write_trace.get() | value.get()); 219 value.put((value.get() & ~STATUS_PD) | ((new_pd) ? STATUS_PD : 0)); 220 } 221 } 222 get_PD()223 inline unsigned int get_PD() 224 { 225 if (rcon) 226 { 227 return rcon->get_PD(); 228 229 } 230 else 231 { 232 get_trace().raw(read_trace.get() | value.get()); 233 return (((value.get() & STATUS_PD) == 0) ? 0 : 1); 234 } 235 } 236 put_TO(unsigned int new_to)237 inline void put_TO(unsigned int new_to) 238 { 239 if (rcon) 240 { 241 rcon->put_TO(new_to); 242 243 } 244 else 245 { 246 get_trace().raw(write_trace.get() | value.get()); 247 value.put((value.get() & ~STATUS_TO) | ((new_to) ? STATUS_TO : 0)); 248 } 249 } 250 get_TO()251 inline unsigned int get_TO() 252 { 253 if (rcon) 254 { 255 return rcon->get_TO(); 256 257 } 258 else 259 { 260 get_trace().raw(read_trace.get() | value.get()); 261 return (((value.get() & STATUS_TO) == 0) ? 0 : 1); 262 } 263 } 264 265 // Special member function to set Z, C, DC, OV, and N for the 18cxxx family 266 267 // Special member function to control just the N bit put_N_Z(unsigned int new_value)268 void put_N_Z(unsigned int new_value) 269 { 270 get_trace().raw(write_trace.get() | value.get()); 271 value.put((value.get() & ~(STATUS_Z | STATUS_N)) | 272 ((new_value & 0xff) ? 0 : STATUS_Z) | 273 ((new_value & 0x80) ? STATUS_N : 0)); 274 } 275 put_Z_C_N(unsigned int new_value)276 void put_Z_C_N(unsigned int new_value) 277 { 278 get_trace().raw(write_trace.get() | value.get()); 279 value.put((value.get() & ~(STATUS_Z | STATUS_C | STATUS_N)) | 280 ((new_value & 0xff) ? 0 : STATUS_Z) | 281 ((new_value & 0x100) ? STATUS_C : 0) | 282 ((new_value & 0x80) ? STATUS_N : 0)); 283 } 284 put_Z_C_DC_OV_N(unsigned int new_value,unsigned int src1,unsigned int src2)285 inline void put_Z_C_DC_OV_N(unsigned int new_value, unsigned int src1, unsigned int src2) 286 { 287 get_trace().raw(write_trace.get() | value.get()); 288 value.put((value.get() & ~(STATUS_Z | STATUS_C | STATUS_DC | STATUS_OV | STATUS_N)) | 289 ((new_value & 0xff) ? 0 : STATUS_Z) | 290 ((new_value & 0x100) ? STATUS_C : 0) | 291 (((new_value ^ src1 ^ src2) & 0x10) ? STATUS_DC : 0) | 292 (((new_value ^ src1) & 0x80) ? STATUS_OV : 0) | 293 ((new_value & 0x80) ? STATUS_N : 0)); 294 } 295 put_Z_C_DC_OV_N_for_sub(unsigned int new_value,unsigned int src1,unsigned int src2)296 inline void put_Z_C_DC_OV_N_for_sub(unsigned int new_value, unsigned int src1, unsigned int src2) 297 { 298 get_trace().raw(write_trace.get() | value.get()); 299 value.put((value.get() & ~(STATUS_Z | STATUS_C | STATUS_DC | STATUS_OV | STATUS_N)) | 300 ((new_value & 0xff) ? 0 : STATUS_Z) | 301 ((new_value & 0x100) ? 0 : STATUS_C) | 302 (((new_value ^ src1 ^ src2) & 0x10) ? 0 : STATUS_DC) | 303 ((((src1 & ~src2 & ~new_value) | (new_value & ~src1 & src2)) & 0x80) ? STATUS_OV : 0) | 304 ((new_value & 0x80) ? STATUS_N : 0)); 305 } 306 307 // Special member function to control just the FSR mode put_FSR0_mode(unsigned int new_value)308 void put_FSR0_mode(unsigned int new_value) 309 { 310 get_trace().raw(write_trace.get() | value.get()); 311 value.put((value.get() & ~(STATUS_FSR0_MODE)) | 312 (new_value & 0x03)); 313 } 314 get_FSR0_mode(unsigned int)315 unsigned int get_FSR0_mode(unsigned int /* new_value */ ) 316 { 317 get_trace().raw(write_trace.get() | value.get()); 318 return ((value.get() >> STATUS_FSR0_BIT) & 0x03); 319 } 320 put_FSR1_mode(unsigned int new_value)321 void put_FSR1_mode(unsigned int new_value) 322 { 323 get_trace().raw(write_trace.get() | value.get()); 324 value.put((value.get() & ~(STATUS_FSR1_MODE)) | 325 (new_value & 0x03)); 326 } 327 get_FSR1_mode(unsigned int)328 unsigned int get_FSR1_mode(unsigned int /* new_value */ ) 329 { 330 get_trace().raw(read_trace.get() | value.get()); 331 return ((value.get() >> STATUS_FSR1_BIT) & 0x03); 332 } 333 }; 334 335 336 //--------------------------------------------------------- 337 // Stack 338 // 339 340 class Stack 341 { 342 public: 343 unsigned int contents[32]; // the stack array 344 int pointer = 0; // the stack pointer 345 unsigned int stack_mask = 7; // 1 for 12bit, 7 for 14bit, 31 for 16bit 346 bool stack_warnings_flag = false; // Should over/under flow warnings be printed? 347 bool break_on_overflow = false; // Should over flow cause a break? 348 bool break_on_underflow = false; // Should under flow cause a break? 349 350 explicit Stack(Processor *); ~Stack()351 virtual ~Stack() {} 352 353 virtual bool push(unsigned int); 354 virtual bool stack_overflow(); 355 virtual bool stack_underflow(); 356 virtual unsigned int pop(); reset(RESET_TYPE)357 virtual void reset(RESET_TYPE ) 358 { 359 pointer = 0; 360 } // %%% FIX ME %%% reset may need to change 361 // because I'm not sure how the stack is affected by a reset. 362 virtual bool set_break_on_overflow(bool clear_or_set); 363 virtual bool set_break_on_underflow(bool clear_or_set); 364 virtual unsigned int get_tos(); 365 virtual void put_tos(unsigned int); 366 367 bool STVREN = false; 368 Processor *cpu; 369 }; 370 371 372 class STKPTR : public sfr_register 373 { 374 public: 375 enum 376 { 377 STKUNF = 1 << 6, 378 STKOVF = 1 << 7 379 }; 380 STKPTR(Processor *, const char *pName, const char *pDesc = nullptr); 381 382 Stack *stack = nullptr; 383 void put_value(unsigned int new_value); 384 void put(unsigned int new_value); 385 }; 386 387 388 class TOSL : public sfr_register 389 { 390 public: 391 TOSL(Processor *, const char *pName, const char *pDesc = nullptr); 392 393 Stack *stack = nullptr; 394 395 virtual void put(unsigned int new_value); 396 virtual void put_value(unsigned int new_value); 397 virtual unsigned int get(); 398 virtual unsigned int get_value(); 399 }; 400 401 402 class TOSH : public sfr_register 403 { 404 public: 405 TOSH(Processor *, const char *pName, const char *pDesc = nullptr); 406 407 Stack *stack = nullptr; 408 409 virtual void put(unsigned int new_value); 410 virtual void put_value(unsigned int new_value); 411 virtual unsigned int get(); 412 virtual unsigned int get_value(); 413 }; 414 415 416 // 417 // Stack for enhanced 14 bit porcessors 418 // 419 class Stack14E : public Stack 420 { 421 public: 422 STKPTR stkptr; 423 TOSL tosl; 424 TOSH tosh; 425 426 explicit Stack14E(Processor *); 427 ~Stack14E(); 428 429 virtual void reset(RESET_TYPE r) override; 430 virtual unsigned int pop() override; 431 virtual bool push(unsigned int address) override; 432 virtual bool stack_overflow() override; 433 virtual bool stack_underflow() override; 434 435 #define NO_ENTRY 0x20 436 }; 437 438 439 //--------------------------------------------------------- 440 // W register 441 class WTraceType; 442 443 class WREG : public sfr_register 444 { 445 public: 446 WREG(Processor *, const char *pName, const char *pDesc = nullptr); 447 ~WREG(); 448 449 protected: 450 WTraceType *m_tt; 451 }; 452 453 454 //--------------------------------------------------------- 455 // INDF 456 457 class INDF : public sfr_register 458 { 459 public: 460 unsigned int fsr_mask; 461 unsigned int base_address_mask1; 462 unsigned int base_address_mask2; 463 464 INDF(Processor *, const char *pName, const char *pDesc = nullptr); 465 void put(unsigned int new_value); 466 virtual void put_value(unsigned int new_value); 467 unsigned int get(); 468 unsigned int get_value(); 469 virtual void initialize(); 470 }; 471 472 473 //--------------------------------------------------------- 474 // 475 // Indirect_Addressing 476 // 477 // This class coordinates the indirect addressing on the 18cxxx 478 // parts. Each of the registers comprising the indirect addressing 479 // subsystem: FSRnL,FSRnH, INDFn, POSTINCn, POSTDECn, PREINCn, and 480 // PLUSWn are each individually defined as sfr_registers AND included 481 // in the Indirect_Addressing class. So accessing these registers 482 // is the same as accessing any register: through the core cpu's 483 // register memory. The only difference for these registers is that 484 // the 485 486 class Indirect_Addressing14; // Forward reference 487 488 //--------------------------------------------------------- 489 // FSR registers 490 491 class FSRL14 : public sfr_register 492 { 493 public: 494 FSRL14(Processor *, const char *pName, const char *pDesc, Indirect_Addressing14 *pIAM); 495 void put(unsigned int new_value); 496 void put_value(unsigned int new_value); 497 498 protected: 499 Indirect_Addressing14 *iam; 500 }; 501 502 503 class FSRH14 : public sfr_register 504 { 505 public: 506 FSRH14(Processor *, const char *pName, const char *pDesc, Indirect_Addressing14 *pIAM); 507 508 void put(unsigned int new_value); 509 void put_value(unsigned int new_value); 510 511 protected: 512 Indirect_Addressing14 *iam; 513 }; 514 515 516 class INDF14 : public sfr_register 517 { 518 public: 519 INDF14(Processor *, const char *pName, const char *pDesc, Indirect_Addressing14 *pIAM); 520 521 void put(unsigned int new_value); 522 void put_value(unsigned int new_value); 523 unsigned int get(); 524 unsigned int get_value(); 525 526 protected: 527 Indirect_Addressing14 *iam; 528 }; 529 530 531 class Indirect_Addressing14 532 { 533 public: 534 Indirect_Addressing14(pic_processor *cpu, const std::string &n); 535 536 pic_processor *cpu; 537 538 unsigned int fsr_value = 0; // 16bit concatenation of fsrl and fsrh 539 unsigned int fsr_state = 0; /* used in conjunction with the pre/post incr 540 * and decrement. This is mainly needed for 541 * those instructions that perform read-modify- 542 * write operations on the indirect registers 543 * eg. btg POSTINC1,4 . The post increment must 544 * occur after the bit is toggled and not during 545 * the read operation that's determining the 546 * current state. 547 */ 548 int fsr_delta = 0; /* If there's a pending update to the fsr register 549 * pair, then the magnitude of that update is 550 * stored here. 551 */ 552 guint64 current_cycle; /* Stores the cpu cycle when the fsr was last 553 * changed. 554 */ 555 FSRL14 fsrl; 556 FSRH14 fsrh; 557 INDF14 indf; 558 559 //void init(_16bit_processor *new_cpu); 560 void put(unsigned int new_value); 561 unsigned int get(); 562 unsigned int get_value(); 563 void put_fsr(unsigned int new_fsr); get_fsr_value()564 unsigned int get_fsr_value() 565 { 566 return (fsr_value & 0xfff); 567 }; 568 void update_fsr_value(); 569 570 /* bool is_indirect_register(unsigned int reg_address) 571 * 572 * The purpose of this routine is to determine whether or not the 573 * 'reg_address' is the address of an indirect register. This is 574 * used by the 'put' and 'get' functions of the indirect registers. 575 * Indirect registers are forbidden access to other indirect registers. 576 * (Although double indirection in a single instruction cycle would 577 * be powerful!). 578 */ 579 is_indirect_register(unsigned int reg_address)580 inline bool is_indirect_register(unsigned int reg_address) 581 { 582 unsigned int bank_address = reg_address % 0x80; 583 584 if (bank_address == 0 || bank_address == 1 || bank_address == 4 || 585 bank_address == 5 || bank_address == 6 || bank_address == 7) 586 { 587 return 1; 588 } 589 590 return 0; 591 } 592 }; 593 594 595 //--------------------------------------------------------- 596 // PCL - Program Counter Low 597 // 598 599 class PCL : public sfr_register 600 { 601 public: 602 virtual void put(unsigned int new_value); 603 virtual void put_value(unsigned int new_value); 604 virtual unsigned int get(); 605 virtual unsigned int get_value(); 606 virtual void reset(RESET_TYPE r); 607 608 PCL(Processor *, const char *pName, const char *pDesc = nullptr); 609 }; 610 611 612 //--------------------------------------------------------- 613 // PCLATH - Program Counter Latch High 614 // 615 616 class PCLATH : public sfr_register 617 { 618 public: 619 void put(unsigned int new_value); 620 void put_value(unsigned int new_value); 621 unsigned int get(); 622 623 PCLATH(Processor *, const char *pName, const char *pDesc = nullptr); 624 }; 625 626 627 //--------------------------------------------------------- 628 // PCON - Power Control/Status Register 629 // 630 class PCON : public sfr_register 631 { 632 public: 633 enum 634 { 635 BOR = 1 << 0, // clear on Brown Out Reset 636 POR = 1 << 1, // clear on Power On Reset 637 RI = 1 << 2, // clear on Reset instruction 638 RMCLR = 1 << 3, // clear if hardware MCLR occurs 639 SBOREN = 1 << 4, // Software BOR Enable bit 640 ULPWUE = 1 << 5, // Ultra Low-Power Wake-up Enable bit 641 STKUNF = 1 << 6, // Stack undeflow 642 STKOVF = 1 << 7 // Stack overflow 643 }; 644 645 unsigned int valid_bits; 646 647 void put(unsigned int new_value); 648 649 PCON(Processor *, const char *pName, const char *pDesc = nullptr, 650 unsigned int bitMask = 0x03); 651 }; 652 653 654 class OSCCON; 655 class OSCTUNE : public sfr_register 656 { 657 public: 658 void put(unsigned int new_value); set_osccon(OSCCON * new_osccon)659 virtual void set_osccon(OSCCON *new_osccon) 660 { 661 osccon = new_osccon; 662 } 663 unsigned int valid_bits = 6; 664 665 enum 666 { 667 TUN0 = 1 << 0, 668 TUN1 = 1 << 1, 669 TUN2 = 1 << 2, 670 TUN3 = 1 << 3, 671 TUN4 = 1 << 4, 672 TUN5 = 1 << 5, 673 PLLEN = 1 << 6, 674 INTSRC = 1 << 7 675 }; 676 OSCCON *osccon = nullptr; 677 OSCTUNE(Processor * pCpu,const char * pName,const char * pDesc)678 OSCTUNE(Processor *pCpu, const char *pName, const char *pDesc) 679 : sfr_register(pCpu, pName, pDesc) 680 { 681 } 682 }; 683 684 685 // This class is used to trim the frequency of the internal RC clock 686 // 111111 - Max freq 687 // 100000 - no adjustment 688 // 000000 - mix freq 689 class OSCCAL : public sfr_register 690 { 691 public: 692 void put(unsigned int new_value); 693 void set_freq(float base_freq); 694 float base_freq = 0.0; 695 OSCCAL(Processor * pCpu,const char * pName,const char * pDesc,unsigned int bitMask)696 OSCCAL(Processor *pCpu, const char *pName, const char *pDesc, unsigned int bitMask) 697 : sfr_register(pCpu, pName, pDesc) 698 { 699 mValidBits = bitMask; // Can't use initialiser for parent class members 700 } 701 }; 702 703 704 class OSCCON : public sfr_register, public TriggerObject 705 { 706 public: 707 virtual void put(unsigned int new_value); 708 virtual void callback(); 709 virtual bool set_rc_frequency(bool override = false); set_osctune(OSCTUNE * new_osctune)710 virtual void set_osctune(OSCTUNE *new_osctune) 711 { 712 osctune = new_osctune; 713 } set_config_irc(unsigned int cfg_irc)714 virtual void set_config_irc(unsigned int cfg_irc) 715 { 716 config_irc = cfg_irc; 717 } set_config_xosc(unsigned int cfg_xosc)718 virtual void set_config_xosc(unsigned int cfg_xosc) 719 { 720 config_xosc = cfg_xosc; 721 } set_config_ieso(unsigned int cfg_ieso)722 virtual void set_config_ieso(unsigned int cfg_ieso) 723 { 724 config_ieso = cfg_ieso; 725 } 726 virtual void reset(RESET_TYPE r); 727 virtual void sleep(); 728 virtual void wake(); 729 virtual void por_wake(); 730 virtual bool internal_RC(); clear_irc_stable_bits()731 virtual void clear_irc_stable_bits() 732 { 733 value.put(value.get() & ~(HTS | LTS)); 734 } 735 virtual guint64 irc_por_time(); // time to stable intrc after power on reset 736 virtual guint64 irc_lh_time(); // time to stable intrc after tran low to high range 737 unsigned int write_mask; 738 unsigned int clock_state; 739 guint64 future_cycle = 0; 740 bool config_irc = false; // FOSC bits select internal RC oscillator 741 bool config_ieso = false; //internal/external switchover bit from config word 742 bool config_xosc = false; // FOSC bits select crystal/resonator 743 bool has_iofs_bit = false; 744 bool is_sleeping = false; 745 746 OSCTUNE *osctune = nullptr; 747 748 enum MODE 749 { 750 UNDEF = 0, 751 EXCSTABLE, // external source 752 LFINTOSC, // Low Freq RC osc 753 MFINTOSC, // Med Freq rc osc 754 HFINTOSC, // High Freq RC osc 755 INTOSC, // IOFS set 756 T1OSC, // T1 OSC 757 EC, // external clock, always stable 758 OST, // startup 759 PLL = 0x10 760 }; 761 762 enum 763 { 764 SCS0 = 1 << 0, 765 SCS1 = 1 << 1, 766 LTS = 1 << 1, 767 HTS = 1 << 2, 768 IOFS = 1 << 2, 769 OSTS = 1 << 3, 770 IRCF0 = 1 << 4, 771 IRCF1 = 1 << 5, 772 IRCF2 = 1 << 6, 773 IDLEN = 1 << 7 774 }; 775 OSCCON(Processor * pCpu,const char * pName,const char * pDesc)776 OSCCON(Processor *pCpu, const char *pName, const char *pDesc) 777 : sfr_register(pCpu, pName, pDesc), write_mask(0x71), 778 clock_state(OST) 779 { 780 } 781 }; 782 783 784 /* OSCCON_1 IOFS bit takes 4 ms to stablize 785 */ 786 787 class OSCCON_1 : public OSCCON 788 { 789 public: 790 // virtual void callback(); 791 // virtual void put(unsigned int new_value); 792 virtual guint64 irc_por_time(); // time to stable intrc after power on reset 793 virtual guint64 irc_lh_time(); 794 OSCCON_1(Processor * pCpu,const char * pName,const char * pDesc)795 OSCCON_1(Processor *pCpu, const char *pName, const char *pDesc) 796 : OSCCON(pCpu, pName, pDesc) 797 { 798 } 799 }; 800 801 802 class OSCCON2 : public sfr_register 803 { 804 public: 805 void put(unsigned int new_value); set_osccon(OSCCON * new_osccon)806 void set_osccon(OSCCON *new_osccon) 807 { 808 osccon = new_osccon; 809 } OSCCON2(Processor * pCpu,const char * pName,const char * pDesc)810 OSCCON2(Processor *pCpu, const char *pName, const char *pDesc) 811 : sfr_register(pCpu, pName, pDesc), write_mask(0x1c) 812 {} 813 814 unsigned int write_mask; 815 enum 816 { 817 LFIOFS = 1 << 0, // LFINTOSC Frequency Stable bit 818 MFIOFS = 1 << 1, // MFINTOSC Frequency Stable bit 819 PRISD = 1 << 2, // Primary Oscillator Drive Circuit Shutdown bit 820 SOSCGO = 1 << 3, // Secondary Oscillator Start Control bit 821 MFIOSEL = 1 << 4, // MFINTOSC Select bit 822 SOSCRUN = 1 << 6, // SOSC Run Status bit 823 PLLRDY = 1 << 7 // PLL Run Status bit 824 }; 825 826 OSCCON *osccon = nullptr; 827 }; 828 829 830 /* RC clock 16Mhz with pll to 64Mhz 831 */ 832 class OSCCON_HS : public OSCCON 833 { 834 public: 835 virtual bool set_rc_frequency(bool override = false); 836 virtual bool internal_RC(); 837 virtual void callback(); 838 virtual void por_wake(); 839 OSCCON_HS(Processor * pCpu,const char * pName,const char * pDesc)840 OSCCON_HS(Processor *pCpu, const char *pName, const char *pDesc) : 841 OSCCON(pCpu, pName, pDesc), minValPLL(5) {} 842 843 OSCCON2 *osccon2 = nullptr; 844 845 enum 846 { 847 SCS0 = 1 << 0, 848 SCS1 = 1 << 1, 849 HFIOFS = 1 << 2, 850 OSTS = 1 << 3, 851 IRCF0 = 1 << 4, 852 IRCF1 = 1 << 5, 853 IRCF2 = 1 << 6, 854 IDLEN = 1 << 7 855 }; 856 857 unsigned char minValPLL; 858 }; 859 860 861 /* RC clock 16Mhz with no SCS0 or osccon2 862 */ 863 class OSCCON_HS2 : public OSCCON 864 { 865 public: 866 virtual void put(unsigned int new_value); 867 virtual bool set_rc_frequency(bool override = false); 868 virtual bool internal_RC(); 869 virtual void callback(); 870 virtual void por_wake(); 871 OSCCON_HS2(Processor * pCpu,const char * pName,const char * pDesc)872 OSCCON_HS2(Processor *pCpu, const char *pName, const char *pDesc) : 873 OSCCON(pCpu, pName, pDesc) 874 { 875 write_mask = 0x70; 876 } 877 878 enum 879 { 880 HFIOFS = 1 << 0, 881 LFIOFR = 1 << 1, 882 HFIOFR = 1 << 3, 883 IRCF0 = 1 << 4, 884 IRCF1 = 1 << 5, 885 IRCF2 = 1 << 6, 886 }; 887 }; 888 889 890 class OSCSTAT : public sfr_register 891 { 892 public: put(unsigned int)893 void put(unsigned int /* new_value */ ) {} 894 895 enum 896 { 897 HFIOFS = 1 << 0, 898 LFIOFR = 1 << 1, 899 MFIOFR = 1 << 2, 900 HFIOFL = 1 << 3, 901 HFIOFR = 1 << 4, 902 OSTS = 1 << 5, 903 PLLR = 1 << 6, 904 T1OSCR = 1 << 7 905 }; OSCSTAT(Processor * pCpu,const char * pName,const char * pDesc)906 OSCSTAT(Processor *pCpu, const char *pName, const char *pDesc) 907 : sfr_register(pCpu, pName, pDesc) {} 908 }; 909 910 911 /* 912 * OSC status in OSCSTAT register 913 */ 914 class OSCCON_2 : public OSCCON 915 { 916 public: 917 virtual void put(unsigned int new_value); 918 void put_value(unsigned int new_value); 919 virtual void callback(); 920 virtual bool set_rc_frequency(bool override = false); set_oscstat(OSCSTAT * _oscstat)921 virtual void set_oscstat(OSCSTAT *_oscstat) 922 { 923 oscstat = _oscstat; 924 } 925 virtual void set_callback(); 926 virtual void por_wake(); 927 OSCSTAT *oscstat = nullptr; 928 929 enum 930 { 931 SCS0 = 1 << 0, 932 SCS1 = 1 << 1, 933 IRCF0 = 1 << 3, 934 IRCF1 = 1 << 4, 935 IRCF2 = 1 << 5, 936 IRCF3 = 1 << 6, 937 SPLLEN = 1 << 7 938 }; 939 OSCCON_2(Processor * pCpu,const char * pName,const char * pDesc)940 OSCCON_2(Processor *pCpu, const char *pName, const char *pDesc) 941 : OSCCON(pCpu, pName, pDesc) 942 { 943 } 944 }; 945 946 947 class WDTCON : public sfr_register 948 { 949 public: 950 unsigned int valid_bits; 951 952 enum 953 { 954 WDTPS3 = 1 << 4, 955 WDTPS2 = 1 << 3, 956 WDTPS1 = 1 << 2, 957 WDTPS0 = 1 << 1, 958 SWDTEN = 1 << 0 959 }; 960 WDTCON(Processor * pCpu,const char * pName,const char * pDesc,unsigned int bits)961 WDTCON(Processor *pCpu, const char *pName, const char *pDesc, unsigned int bits) 962 : sfr_register(pCpu, pName, pDesc), valid_bits(bits) 963 { 964 } 965 virtual void put(unsigned int new_value); 966 virtual void reset(RESET_TYPE r); 967 }; 968 969 970 // Interrupt-On-Change GPIO Register 971 class IOC : public sfr_register 972 { 973 public: 974 IOC(Processor *pCpu, const char *pName, const char *pDesc, unsigned int _valid_bits = 0xff) sfr_register(pCpu,pName,pDesc)975 : sfr_register(pCpu, pName, pDesc) 976 { 977 mValidBits = _valid_bits; 978 } 979 put(unsigned int new_value)980 virtual void put(unsigned int new_value) 981 { 982 unsigned int masked_value = new_value & mValidBits; 983 get_trace().raw(write_trace.get() | value.get()); 984 value.put(masked_value); 985 } 986 }; 987 988 989 // Interrupt-On-Change Register 990 class IOCxF : public IOC 991 { 992 public: 993 IOCxF(Processor *pCpu, const char *pName, const char *pDesc, unsigned int _valid_bits = 0xff) IOC(pCpu,pName,pDesc,_valid_bits)994 : IOC(pCpu, pName, pDesc, _valid_bits) 995 { 996 } 997 set_intcon(INTCON * new_value)998 void set_intcon(INTCON *new_value) 999 { 1000 intcon = new_value; 1001 } 1002 void put(unsigned int new_value); 1003 1004 protected: 1005 INTCON *intcon = nullptr; 1006 }; 1007 1008 1009 class PicPortRegister; 1010 // WPU set weak pullups on pin by pin basis 1011 // 1012 class WPU : public sfr_register 1013 { 1014 public: 1015 PicPortRegister *wpu_gpio; 1016 bool wpu_pu = false; 1017 1018 void put(unsigned int new_value); 1019 void set_wpu_pu(bool pullup_enable); 1020 1021 WPU(Processor *pCpu, const char *pName, const char *pDesc, PicPortRegister* gpio, unsigned int mask = 0x37) sfr_register(pCpu,pName,pDesc)1022 : sfr_register(pCpu, pName, pDesc), wpu_gpio(gpio) 1023 { 1024 mValidBits = mask; // Can't use initialiser for parent class members 1025 } 1026 }; 1027 1028 // ODCON Open Drain Control Pin will only sink current if bit is set 1029 // 1030 class ODCON : public sfr_register 1031 { 1032 public: 1033 PicPortRegister *gpio; 1034 1035 void put(unsigned int new_value); 1036 1037 ODCON(Processor *pCpu, const char *pName, const char *pDesc, PicPortRegister* _gpio, unsigned int mask = 0x37) sfr_register(pCpu,pName,pDesc)1038 : sfr_register(pCpu, pName, pDesc), gpio(_gpio) 1039 { 1040 mValidBits = mask; // Can't use initialiser for parent class members 1041 } 1042 }; 1043 1044 1045 // INLVL Logic level of input pins, 1=schmitt, 0=ttl 1046 // 1047 class INLVL : public sfr_register 1048 { 1049 public: 1050 PicPortRegister *gpio; 1051 1052 void put(unsigned int new_value); 1053 1054 INLVL(Processor *pCpu, const char *pName, const char *pDesc, PicPortRegister* _gpio, unsigned int mask = 0x37) sfr_register(pCpu,pName,pDesc)1055 : sfr_register(pCpu, pName, pDesc), gpio(_gpio) 1056 { 1057 mValidBits = mask; // Can't use initialiser for parent class members 1058 } 1059 }; 1060 1061 1062 class CPSCON1; 1063 class T1CON_G; 1064 class CPS_stimulus; 1065 1066 // Capacitance Sensing Control Register 0 1067 class CPSCON0 : public sfr_register, public TriggerObject 1068 { 1069 public: 1070 enum 1071 { 1072 T0XCS = 1 << 0, // Timer0 External Clock Source Select bit 1073 CPSOUT = 1 << 1, // Capacitive Sensing Oscillator Status bit 1074 CPSRNG0 = 1 << 2, // Capacitive Sensing Current Range bits 1075 CPSRNG1 = 1 << 3, 1076 CPSRM = 1 << 6, // Capacitive Sensing Reference Mode bit 1077 CPSON = 1 << 7 // CPS Module Enable bit 1078 }; 1079 1080 void put(unsigned int new_value); 1081 void set_chan(unsigned int _chan); 1082 void calculate_freq(); set_pin(unsigned int _chan,PinModule * _pin)1083 void set_pin(unsigned int _chan, PinModule *_pin) 1084 { 1085 pin[_chan] = _pin; 1086 } 1087 void set_DAC_volt(double); 1088 void set_FVR_volt(double); 1089 void callback(); 1090 virtual void callback_print(); 1091 1092 CPSCON0(Processor *pCpu, const char *pName, const char *pDesc = nullptr); 1093 ~CPSCON0(); 1094 1095 TMR0 *m_tmr0 = nullptr; 1096 T1CON_G *m_t1con_g = nullptr; 1097 1098 private: 1099 unsigned int chan = 0; 1100 PinModule *pin[16]; 1101 double DAC_voltage = 0.0; 1102 double FVR_voltage = 0.0; 1103 guint64 future_cycle = 0; 1104 int period = 0; 1105 CPS_stimulus *cps_stimulus = nullptr; 1106 }; 1107 1108 1109 // Capacitance Sensing Control Register 1 1110 class CPSCON1 : public sfr_register 1111 { 1112 public: 1113 void put(unsigned int new_value); 1114 CPSCON1(Processor * pCpu,const char * pName,const char * pDesc)1115 CPSCON1(Processor *pCpu, const char *pName, const char *pDesc) 1116 : sfr_register(pCpu, pName, pDesc) 1117 { 1118 mValidBits = 0x03; 1119 } 1120 1121 CPSCON0 *m_cpscon0 = nullptr; 1122 }; 1123 1124 1125 class CPS_stimulus : public stimulus 1126 { 1127 public: 1128 CPS_stimulus(CPSCON0 *arg, const char *n = nullptr, 1129 double _Vth = 0.0, double _Zth = 1e12 1130 ); 1131 1132 CPSCON0 *m_cpscon0; 1133 1134 virtual void set_nodeVoltage(double v); 1135 }; 1136 1137 1138 class SR_MODULE; 1139 1140 // SR LATCH CONTROL 0 REGISTER 1141 class SRCON0 : public sfr_register 1142 { 1143 public: 1144 enum 1145 { 1146 SRPR = 1 << 0, // Pulse Reset Input of the SR Latch bit 1147 SRPS = 1 << 1, // Pulse Set Input of the SR Latch bit 1148 SRNQEN = 1 << 2, // Latch Not Q Output Enable bit 1149 SRQEN = 1 << 3, // Latch Q Output Enable bit 1150 SRCLK0 = 1 << 4, // Latch Clock Divider bits 1151 SRCLK1 = 1 << 5, // Latch Clock Divider bits 1152 SRCLK2 = 1 << 6, // Latch Clock Divider bits 1153 SRLEN = 1 << 7, // Latch Enable bit 1154 CLKMASK = SRCLK0 | SRCLK1 | SRCLK2, 1155 CLKSHIFT = 4 1156 }; 1157 1158 SRCON0(Processor *pCpu, const char *pName, const char *pDesc, SR_MODULE *_sr_module); 1159 void put(unsigned int new_value); 1160 1161 private: 1162 SR_MODULE *m_sr_module; 1163 }; 1164 1165 1166 // SR LATCH CONTROL 1 REGISTER 1167 // 1168 class SRCON1 : public sfr_register 1169 { 1170 public: 1171 enum 1172 { 1173 SRRC1E = 1 << 0, // Latch C1 Reset Enable bit 1174 SRRC2E = 1 << 1, // Latch C2 Reset Enable bit 1175 SRRCKE = 1 << 2, // Latch Reset Clock Enable bit 1176 SRRPE = 1 << 3, // Latch Peripheral Reset Enable bit 1177 SRSC1E = 1 << 4, // Latch C1 Set Enable bit 1178 SRSC2E = 1 << 5, // Latch C2 Set Enable bit 1179 SRSCKE = 1 << 6, // Latch Set Clock Enable bit 1180 SRSPE = 1 << 7 // Latch Peripheral Set Enable bit 1181 }; 1182 1183 SRCON1(Processor *pCpu, const char *pName, const char *pDesc, SR_MODULE *m_sr_module); 1184 void put(unsigned int new_value); set_ValidBits(unsigned int validbits)1185 void set_ValidBits(unsigned int validbits) 1186 { 1187 mValidBits = validbits; 1188 } 1189 1190 private: 1191 SR_MODULE *m_sr_module; 1192 unsigned int mValidBits = 0xdd; 1193 }; 1194 1195 1196 class SRinSink; 1197 1198 class SR_MODULE: public TriggerObject 1199 { 1200 public: 1201 explicit SR_MODULE(Processor *); 1202 ~SR_MODULE(); 1203 1204 void update(); 1205 SRCON0 srcon0; 1206 SRCON1 srcon1; 1207 pulse_reset()1208 void pulse_reset() 1209 { 1210 state_reset = true; 1211 } pulse_set()1212 void pulse_set() 1213 { 1214 state_set = true; 1215 } 1216 void clock_diff(unsigned int); 1217 void clock_enable(); 1218 void clock_disable(); 1219 void syncC1out(bool val); 1220 void syncC2out(bool val); 1221 void setPins(PinModule *, PinModule *, PinModule *); 1222 void setState(char); 1223 void Qoutput(); 1224 void NQoutput(); 1225 void releasePin(int); 1226 1227 protected: 1228 void callback(); 1229 1230 Processor *cpu; 1231 guint64 future_cycle = 0; 1232 bool state_set = false; 1233 bool state_reset = false; 1234 bool state_Q = false; 1235 unsigned int srclk = 0; 1236 bool syncc1out = false; // Synced output from comparator 1 1237 bool syncc2out = false; // Synced output from comparator 2 1238 PinModule *SRI_pin = nullptr; 1239 PinModule *SRQ_pin = nullptr; 1240 PinModule *SRNQ_pin = nullptr; 1241 bool SRI = false; // state of input pin 1242 SRinSink *m_SRinSink = nullptr; 1243 PeripheralSignalSource *m_SRQsource = nullptr; 1244 PeripheralSignalSource *m_SRNQsource = nullptr; 1245 bool m_SRQsource_active = false; 1246 bool m_SRNQsource_active = false; 1247 }; 1248 1249 1250 class LVDCON_14 : public sfr_register, public TriggerObject 1251 { 1252 public: 1253 unsigned int valid_bits = 0; 1254 1255 enum 1256 { 1257 LVDL0 = 1 << 0, 1258 LVDL1 = 1 << 1, 1259 LVDL2 = 1 << 2, 1260 LVDEN = 1 << 4, 1261 IRVST = 1 << 5, 1262 }; 1263 1264 LVDCON_14(Processor *, const char *pName, const char *pDesc = nullptr); 1265 void check_lvd(); 1266 unsigned int write_mask = 0x17; 1267 InterruptSource *IntSrc = nullptr; 1268 void callback() override; 1269 void put(unsigned int new_value); setIntSrc(InterruptSource * _IntSrc)1270 virtual void setIntSrc(InterruptSource *_IntSrc) 1271 { 1272 IntSrc = _IntSrc; 1273 } 1274 }; 1275 1276 1277 #endif 1278