1 /*
2    Copyright (C) 1998 Scott Dattalo
3    Copyright (C) 2009 Roy R. Rankin
4 
5 This file is part of the libgpsim library of gpsim
6 
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11 
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 Lesser General Public License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, see
19 <http://www.gnu.org/licenses/lgpl-2.1.html>.
20 */
21 
22 #include <assert.h>
23 #include <stdio.h>
24 #include <iostream>
25 
26 #include "pic-processor.h"
27 #include "pic-ioports.h"
28 #include "intcon.h"
29 #include "psp.h"
30 #include "trace.h"
31 #include "ui.h"
32 
33 //#define DEBUG
34 #if defined(DEBUG)
35 #define Dprintf(arg) {printf("%s:%d ",__FILE__,__LINE__); printf arg; }
36 #else
37 #define Dprintf(arg) {}
38 #endif
39 
40 //-------------------------------------------------------------------
41 //
42 //                 ioports.cc
43 //
44 // The ioport infrastructure for gpsim is provided here. The class
45 // taxonomy for the IOPORT class is:
46 //
47 //  file_register
48 //     |-> sfr_register
49 //            |-> IOPORT
50 //                  |-> PORTA
51 //                  |-> PORTB
52 //                  |-> PORTC
53 //                  |-> PORTD
54 //                  |-> PORTE
55 //                  |-> PORTF
56 //
57 // Each I/O port has an associated array of I/O pins which provide an
58 // interface to the virtual external world of the stimuli.
59 //
60 //-------------------------------------------------------------------
61 
62 class PicSignalSource : public SignalControl
63 {
64 public:
PicSignalSource(PortRegister * _reg,unsigned int bitPosition)65     PicSignalSource(PortRegister *_reg, unsigned int bitPosition)
66         : m_register(_reg), m_bitMask(1 << bitPosition)
67     {
68     }
getState()69     char getState()
70     {
71 
72         char r = m_register ? (((m_register->getDriving() & m_bitMask) != 0) ? '1' : '0') : 'Z';
73 
74         Dprintf(("PicSignalSource::getState() %s  bitmask:0x%x state:%c\n",
75                  (m_register?m_register->name().c_str():"NULL"),
76                  m_bitMask,r));
77 
78         return r;
79     }
release()80     void release()
81     {
82         delete this;
83     }
84 private:
85     PortRegister *m_register;
86     unsigned int  m_bitMask;
87 };
88 
89 
90 
91 //------------------------------------------------------------------------
92 
PicPortRegister(Processor * pCpu,const char * pName,const char * pDesc,unsigned int numIopins,unsigned int enableMask)93 PicPortRegister::PicPortRegister(Processor *pCpu, const char *pName, const char *pDesc,
94                                  /*const char *port_name,*/
95                                  unsigned int numIopins,
96                                  unsigned int enableMask)
97     : PortRegister(pCpu, pName, pDesc,numIopins, false), m_tris(0)
98 {
99     setEnableMask(enableMask);
100 }
101 
102 class PicSignalControl : public SignalControl
103 {
104 public:
PicSignalControl(PicTrisRegister * _reg,unsigned int bitPosition)105     PicSignalControl(PicTrisRegister *_reg, unsigned int bitPosition)
106         : m_register(_reg), m_bitMask(1 << bitPosition)
107     {
108     }
~PicSignalControl()109     virtual ~PicSignalControl()
110     {
111     }
112 
getState()113     virtual char getState()
114     {
115         return m_register ? m_register->get3StateBit(m_bitMask) : '?';
116     }
release()117     virtual void release()
118     {
119         delete this;
120     }
121 private:
122     PicTrisRegister *m_register;
123     unsigned int m_bitMask;
124 };
125 
setTris(PicTrisRegister * new_tris)126 void PicPortRegister::setTris(PicTrisRegister *new_tris)
127 {
128     if (!m_tris)
129         m_tris = new_tris;
130 
131     unsigned int mask = getEnableMask();
132     for (unsigned int i = 0, m = 1; i < mNumIopins; i++, m <<= 1)
133     {
134         if (mask & m)
135             operator[](i).setDefaultControl(new PicSignalControl(m_tris, i));
136     }
137 }
138 //------------------------------------------------------------------------
139 
PicTrisRegister(Processor * pCpu,const char * pName,const char * pDesc,PicPortRegister * _port,bool bIgnoreWDTResets,unsigned int enableMask)140 PicTrisRegister::PicTrisRegister(Processor *pCpu, const char *pName, const char *pDesc,
141                                  /*const char *tris_name,*/
142                                  PicPortRegister *_port,
143                                  bool bIgnoreWDTResets,
144                                  unsigned int enableMask)
145     : sfr_register(pCpu, pName, pDesc),
146       m_port(_port),
147       m_EnableMask(enableMask),
148       m_bIgnoreWDTResets(bIgnoreWDTResets)
149 {
150     if (m_port)
151         m_port->setTris(this);
152 }
153 
put(unsigned int new_value)154 void PicTrisRegister::put(unsigned int new_value)
155 {
156     trace.raw(write_trace.get() | value.data);
157     value.put((value.get() & ~m_EnableMask) | (new_value & m_EnableMask));
158 
159     if (m_port)
160         m_port->updatePort();
161 }
162 
put_value(unsigned int new_value)163 void PicTrisRegister::put_value(unsigned int new_value)
164 {
165     value.put(new_value & m_EnableMask);
166 
167     if (m_port)
168         m_port->updatePort();
169 }
170 
get()171 unsigned int PicTrisRegister::get()
172 {
173     trace.raw(read_trace.get() | value.data);
174     return value.data;
175 }
176 
setEnableMask(unsigned int enableMask)177 void PicTrisRegister::setEnableMask(unsigned int enableMask)
178 {
179     m_EnableMask = enableMask;
180 }
181 
get3StateBit(unsigned int bitMask)182 char PicTrisRegister::get3StateBit(unsigned int bitMask)
183 {
184     RegisterValue rv = getRV_notrace();
185     unsigned int enabled = bitMask & m_EnableMask;
186     if (!enabled)
187         return '1';
188 
189     return (rv.init & enabled) ? '?' : ((rv.data & enabled) ? '1': '0');
190 }
191 
reset(RESET_TYPE r)192 void PicTrisRegister::reset(RESET_TYPE r)
193 {
194     if (!(m_bIgnoreWDTResets && r == WDT_RESET))
195         putRV(por_value);
196 }
197 
198 
199 //------------------------------------------------------------------------
200 
PicPSP_TrisRegister(Processor * pCpu,const char * pName,const char * pDesc,PicPortRegister * _port,bool bIgnoreWDTResets)201 PicPSP_TrisRegister::PicPSP_TrisRegister(Processor *pCpu, const char *pName, const char *pDesc,
202         /*const char *tris_name, */
203         PicPortRegister *_port, bool bIgnoreWDTResets)
204     : PicTrisRegister(pCpu, pName, pDesc, _port, bIgnoreWDTResets)
205 {
206 }
207 // If not in PSPMODE, OBF and IBF are always clear
208 // When in PSPMODE, OBF and IBF can only be cleared by reading and writing
209 // to the PSP parallel port and are set by bus transfers.
210 //
put(unsigned int new_value)211 void PicPSP_TrisRegister::put(unsigned int new_value)
212 {
213     unsigned int mask = (PSP::OBF | PSP::IBF);
214     unsigned int fixed;
215 
216     trace.raw(write_trace.get() | value.data);
217     if (! (new_value & PSP::PSPMODE))
218         fixed = 0;
219     else
220         fixed = value.data & mask;
221 
222     value.data = (new_value & ~mask) | fixed;
223     if (m_port)
224         m_port->updatePort();
225 }
226 
227 // used by gpsim to change register value
put_value(unsigned int new_value)228 void PicPSP_TrisRegister::put_value(unsigned int new_value)
229 {
230     trace.raw(write_trace.get() | value.data);
231 
232     value.data = new_value;
233     if (m_port)
234         m_port->updatePort();
235 }
236 
get()237 unsigned int PicPSP_TrisRegister::get()
238 {
239     return value.data;
240 }
241 
242 
243 //------------------------------------------------------------------------
244 
PicPortBRegister(Processor * pCpu,const char * pName,const char * pDesc,INTCON * pIntcon,unsigned int numIopins,unsigned int enableMask,INTCON2 * pIntcon2,INTCON3 * pIntcon3)245 PicPortBRegister::PicPortBRegister(Processor *pCpu, const char *pName, const char *pDesc,
246                                    INTCON *pIntcon,
247                                    unsigned int numIopins,
248                                    unsigned int enableMask,
249                                    INTCON2 *pIntcon2,
250                                    INTCON3 *pIntcon3)
251     : PicPortRegister(pCpu, pName, pDesc, numIopins, enableMask),
252       intf_bit(9),
253       cpu(pCpu),
254       m_bRBPU(false),
255       m_bIntEdge(true),
256       m_bsRBPU(0),
257       m_pIntcon(pIntcon),
258       m_pIntcon2(pIntcon2),
259       m_pIntcon3(pIntcon3)
260 {
261     assert(m_pIntcon);
262 }
263 
~PicPortBRegister()264 PicPortBRegister::~PicPortBRegister()
265 {
266     delete m_bsRBPU;
267 }
268 
269 //------------------------------------------------------------------------
270 
put(unsigned int new_value)271 void PicPortBRegister::put(unsigned int new_value)
272 {
273     trace.raw(write_trace.get() | value.data);
274 
275 
276 //  unsigned int diff = mEnableMask & (new_value ^ value.data);
277     drivingValue = new_value & mEnableMask;
278     value.data = drivingValue;
279     // If no stimuli are connected to the Port pins, then the driving
280     // value and the driven value are the same. If there are external
281     // stimuli (or perhaps internal peripherals) overdriving or overriding
282     // this port, then the call to updatePort() will update 'drivenValue'
283     // to its proper value.
284     updatePort();
285     lastDrivenValue = rvDrivenValue;
286 
287 }
288 
get()289 unsigned int PicPortBRegister::get()
290 {
291     lastDrivenValue = rvDrivenValue;
292     return mOutputMask & rvDrivenValue.data;
293 }
294 
295 //------------------------------------------------------------------------
296 // setbit
297 // FIXME - a sink should be created for the intf and rbif functions.
298 
setbit(unsigned int bit_number,char new3State)299 void PicPortBRegister::setbit(unsigned int bit_number, char new3State)
300 {
301     Dprintf(("PicPortBRegister::setbit() bit=%u,val=%c bIntEdge=%d\n",
302              bit_number, new3State, m_bIntEdge));
303 
304     // interrupt bit 0 on specified edge
305     bool bNewValue = new3State == '1' || new3State == 'W';
306     lastDrivenValue = rvDrivenValue;
307     setINTif(bit_number, bNewValue);
308     PortRegister::setbit(bit_number, new3State);
309 
310 
311 // interrupt and exit sleep level change top 4 bits on input
312     unsigned int bitMask = (1 << bit_number) & 0xF0;
313 
314     if ((lastDrivenValue.data ^ rvDrivenValue.data) & m_tris->get_value() & bitMask)
315     {
316 
317         if ((m_pIntcon->get() & (INTCON::GIE | INTCON::RBIE)) == INTCON::RBIE)
318             cpu_pic->exit_sleep();
319         m_pIntcon->set_rbif(true);
320     }
321 }
322 
setINTif(unsigned int bit_number,bool bNewValue)323 void PicPortBRegister::setINTif(unsigned int bit_number, bool bNewValue)
324 {
325 //  lastDrivenValue = rvDrivenValue;
326     bool OldValue = (lastDrivenValue.data&(1 << bit_number)) ;
327     bool level;
328 
329     if (OldValue == bNewValue) return;
330     if (m_pIntcon3)
331     {
332         int intcon = m_pIntcon->value.get();
333         int intcon2 = m_pIntcon2->value.get();
334         int intcon3 = m_pIntcon3->value.get();
335         switch (bit_number)
336         {
337         case 0:
338             level = intcon2 & INTCON2::INTEDG0;
339             if ((OldValue != bNewValue) && (bNewValue == level))
340             {
341                 m_pIntcon->set_intf(true);
342                 if ( (intcon & INTCON::INTE))
343                 {
344                     cpu_pic->exit_sleep();
345                     ((INTCON_16 *)m_pIntcon)->general_interrupt(true);
346                 }
347             }
348             return;
349             break;
350 
351         case 1:
352             level = intcon2 & INTCON2::INTEDG1;
353             if ((OldValue != bNewValue) && (bNewValue == level))
354             {
355                 m_pIntcon3->set_int1f(true);
356                 if ((intcon3 & INTCON3::INT1IE))
357                 {
358                     cpu_pic->exit_sleep();
359                     ((INTCON_16 *)m_pIntcon)->general_interrupt(intcon3 & INTCON3::INT1IP);
360                 }
361             }
362             return;
363             break;
364 
365         case 2:
366             level = intcon2 & INTCON2::INTEDG2;
367             if ((OldValue != bNewValue) && (bNewValue == level))
368             {
369                 m_pIntcon3->set_int2f(true);
370                 if ((intcon3 & INTCON3::INT2IE))
371                 {
372                     cpu_pic->exit_sleep();
373                     ((INTCON_16 *)m_pIntcon)->general_interrupt(intcon3 & INTCON3::INT2IP);
374                 }
375             }
376             return;
377             break;
378 
379         case 3:
380             if (intf_bit != 3) return;
381             level = intcon2 & INTCON2::INTEDG3;
382             if ((OldValue != bNewValue) && (bNewValue == level))
383             {
384                 m_pIntcon3->set_int3f(true);
385                 if ((intcon3 & INTCON3::INT3IE))
386                 {
387                     cpu_pic->exit_sleep();
388                     ((INTCON_16 *)m_pIntcon)->general_interrupt(intcon2 & INTCON2::INT3IP);
389                 }
390             }
391             return;
392             break;
393         }
394     }
395     else
396     {
397         if (bit_number == intf_bit)
398         {
399             if ((OldValue != m_bIntEdge) && (bNewValue == m_bIntEdge))
400             {
401                 if ((m_pIntcon->get() & INTCON::INTE))
402                 {
403                     cpu_pic->exit_sleep();
404                 }
405                 m_pIntcon->set_intf(true);
406             }
407         }
408     }
409 }
410 class RBPUBitSink : public BitSink
411 {
412     PicPortBRegister *m_pPortB;
413 public:
RBPUBitSink(PicPortBRegister * pPortB)414     explicit RBPUBitSink(PicPortBRegister *pPortB)
415         : m_pPortB(pPortB)
416     {}
417 
setSink(bool b)418     void setSink(bool b)
419     {
420         if (m_pPortB)
421             m_pPortB->setRBPU(b);
422     }
423 };
424 
assignRBPUSink(unsigned int bitPos,sfr_register * pSFR)425 void PicPortBRegister::assignRBPUSink(unsigned int bitPos, sfr_register *pSFR)
426 {
427     if (pSFR && !m_bsRBPU)
428     {
429         m_bsRBPU = new RBPUBitSink(this);
430         if (!pSFR->assignBitSink(bitPos, m_bsRBPU))
431         {
432             delete m_bsRBPU;
433             m_bsRBPU = 0;
434         }
435     }
436 }
437 
setRBPU(bool bNewRBPU)438 void PicPortBRegister::setRBPU(bool bNewRBPU)
439 {
440     m_bRBPU = !bNewRBPU;
441 
442     Dprintf(("PicPortBRegister::setRBPU() =%d\n", (m_bRBPU ? 1 : 0)));
443 
444     unsigned int mask = getEnableMask();
445     for (unsigned int i = 0, m = 1; mask; i++, m <<= 1)
446     {
447         if (mask & m)
448         {
449             mask ^= m;
450             operator[](i).getPin().update_pullup(m_bRBPU ? '1' : '0', true);
451         }
452     }
453 }
454 
setIntEdge(bool bNewIntEdge)455 void PicPortBRegister::setIntEdge(bool bNewIntEdge)
456 {
457     m_bIntEdge = bNewIntEdge;
458 }
459 
PicPortGRegister(Processor * pCpu,const char * pName,const char * pDesc,INTCON * pIntcon,IOC * pIoc,unsigned int numIopins,unsigned int enableMask,INTCON2 * pIntcon2,INTCON3 * pIntcon3)460 PicPortGRegister::PicPortGRegister(Processor *pCpu, const char *pName,
461                                    const char *pDesc,
462                                    INTCON *pIntcon, IOC *pIoc,
463                                    unsigned int numIopins, unsigned int enableMask,
464                                    INTCON2 *pIntcon2,
465                                    INTCON3 *pIntcon3)
466     : PicPortBRegister(pCpu, pName, pDesc, pIntcon, numIopins, enableMask),
467       m_pIntcon(pIntcon), m_pIoc(pIoc)
468 {
469     m_pIntcon->set_portGReg(this);
470     m_pIntcon2=pIntcon2;
471     m_pIntcon3=pIntcon3;
472 }
473 
474 // set_rbif involves RBIF,RBIE in INTCON which are the same bits as GPIF,GPIE
setIOCif()475 void PicPortGRegister::setIOCif()
476 {
477 // interrupt and exit sleep for level change on bits where IOC set
478     int bitMask = m_pIoc->get_value();
479 
480 
481     if ( (lastDrivenValue.data ^ rvDrivenValue.data) & m_tris->get_value() & bitMask )
482     {
483         cpu_pic->exit_sleep();
484         m_pIntcon->set_rbif(true);
485     }
486 }
487 
setbit(unsigned int bit_number,char new3State)488 void PicPortGRegister::setbit(unsigned int bit_number, char new3State)
489 {
490     bool bNewValue = new3State == '1' || new3State == 'W';
491 
492     lastDrivenValue = rvDrivenValue;
493     PortRegister::setbit(bit_number, new3State);
494 
495     setINTif(bit_number, bNewValue);
496     setIOCif();
497     // interrupt and exit sleep for level change on bits where IOC set
498     int bitMask = m_pIoc->get_value() & (1 << bit_number);
499 
500     if (verbose)
501         printf("PicPortGRegister::setbit() bit=%u,val=%c IOC_bit=%x\n", bit_number, new3State, bitMask);
502 }
503 
504 
setbit(unsigned int bit_number,char new3State)505 void PicPortIOCRegister::setbit(unsigned int bit_number, char new3State)
506 {
507     bool bNewValue = new3State == '1' || new3State == 'W';
508     int lastDrivenValue = rvDrivenValue.data & (1 << bit_number);
509     setINTif(bit_number, bNewValue);
510     PortRegister::setbit(bit_number, new3State);
511     int newDrivenValue = rvDrivenValue.data & (1 << bit_number);
512 
513     if (verbose)
514     {
515         printf("PicPortIOCRegister::setbit() bit=%u,val=%c IOC_+=%x IOC_-=%x\n",
516                bit_number, new3State, m_Iocap->get_value() & (1 << bit_number),
517                m_Iocan->get_value() & (1 << bit_number));
518     }
519 
520     if (newDrivenValue > lastDrivenValue)
521     {
522         // positive edge
523         if (m_tris->get_value() & (m_Iocap->get_value() & (1 << bit_number)))
524         {
525             cpu_pic->exit_sleep();
526             m_pIntcon->set_rbif(true);
527             if (m_Iocaf)
528                 m_Iocaf->put(m_Iocaf->get_value() | (1 << bit_number));
529         }
530     }
531     else if (newDrivenValue < lastDrivenValue)
532     {
533         // negative edge
534         if (m_tris->get_value() & (m_Iocan->get_value() & (1 << bit_number)))
535         {
536             cpu_pic->exit_sleep();
537             m_pIntcon->set_rbif(true);
538             if (m_Iocaf)
539                 m_Iocaf->put(m_Iocaf->get_value() | (1 << bit_number));
540         }
541     }
542 }
543 
PicPSP_PortRegister(Processor * pCpu,const char * pName,const char * pDesc,unsigned int numIopins,unsigned int enableMask)544 PicPSP_PortRegister::PicPSP_PortRegister(Processor *pCpu, const char *pName, const char *pDesc,
545         /*const char *port_name,*/
546         unsigned int numIopins,
547         unsigned int enableMask)
548     : PortRegister(pCpu, pName, pDesc,numIopins, false), m_tris(0), m_psp(0)
549 {
550     setEnableMask(enableMask);
551 }
552 
put(unsigned int new_value)553 void PicPSP_PortRegister::put(unsigned int new_value)
554 {
555     trace.raw(write_trace.get() | value.data);
556     unsigned int diff = mEnableMask & (new_value ^ value.data);
557 
558     if (m_psp && m_psp->pspmode())
559     {
560         m_psp->psp_put(new_value);
561     }
562     else if (diff)
563     {
564         drivingValue = new_value & mEnableMask;
565         value.data = drivingValue;
566         // If no stimuli are connected to the Port pins, then the driving
567         // value and the driven value are the same. If there are external
568         // stimuli (or perhaps internal peripherals) overdriving or overriding
569         // this port, then the call to updatePort() will update 'drivenValue'
570         // to its proper value.
571         updatePort();
572     }
573 }
574 
get()575 unsigned int PicPSP_PortRegister::get()
576 {
577     if (m_psp && m_psp->pspmode())
578         return(m_psp->psp_get());
579 
580     return rvDrivenValue.data;
581 }
582 
583 
setTris(PicTrisRegister * new_tris)584 void PicPSP_PortRegister::setTris(PicTrisRegister *new_tris)
585 {
586     if (!m_tris)
587         m_tris = new_tris;
588 
589     unsigned int mask = getEnableMask();
590     for (unsigned int i = 0, m = 1; i < mNumIopins; i++, m <<= 1)
591     {
592         if (mask & m)
593             operator[](i).setDefaultControl(new PicSignalControl(m_tris, i));
594     }
595 }
596 
597 //------------------------------------------------------------------------
598 // Latch Register
599 
PicLatchRegister(Processor * pCpu,const char * pName,const char * pDesc,PortRegister * _port,unsigned int enableMask)600 PicLatchRegister::PicLatchRegister(Processor *pCpu, const char *pName, const char *pDesc,
601                                    /*const char *_name, */
602                                    PortRegister *_port,
603                                    unsigned int enableMask)
604     : sfr_register(pCpu, pName, pDesc),
605       m_port(_port), m_EnableMask(enableMask)
606 {
607 }
608 
put(unsigned int new_value)609 void PicLatchRegister::put(unsigned int new_value)
610 {
611     trace.raw(write_trace.get() | value.data);
612     value.data = new_value & m_EnableMask;
613     m_port->put_value(value.data);
614 }
615 
put_value(unsigned int new_value)616 void PicLatchRegister::put_value(unsigned int new_value)
617 {
618     value.data = new_value & m_EnableMask;
619     m_port->put_value(value.data);
620 }
621 
get()622 unsigned int PicLatchRegister::get()
623 {
624     value.data = m_port->getDriving();
625     trace.raw(read_trace.get()  | value.data);
626     trace.raw(read_trace.geti() | value.init);
627 
628     return value.data;
629 }
630 
setbit(unsigned int,char)631 void PicLatchRegister::setbit(unsigned int, char)
632 {
633     printf("PicLatchRegister::setbit() -- shouldn't be called\n");
634 }
635 
setEnableMask(unsigned int nEnableMask)636 void PicLatchRegister::setEnableMask(unsigned int nEnableMask)
637 {
638     m_EnableMask = nEnableMask;
639 }
640 
641