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