2
Copyright( C) 1998 T. Scott Dattalo
4
This file is part of the libgpsim library of gpsim
6
This library is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Lesser General Public
8
License as published by the Free Software Foundation; either
9
version 2.1 of the License, or( at your option) any later version.
11
This library is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
Lesser General Public License for more details.
16
You should have received a copy of the GNU Lesser General Public
17
License along with this library; if not, see
18
<http://www.gnu.org/licenses/lgpl-2.1.html>.
36
#include "pic-processor.h"
37
#include "pic-registers.h"
40
//========================================================================
44
// This file contains all( most?) of the code that simulates those features
45
// common to all pic microcontrollers.
47
//========================================================================
49
pic_processor::pic_processor(const char *_name )
51
wdt(this, 18.0e-3),indf(0),fsr(0), stack(0), status(0),
52
Wreg(0), pcl(0), pclath(0),
55
m_MCLR(0), m_MCLR_Save(0), m_MCLRMonitor(0),
56
PPLx4(false), clksource(0), clkcontrol(0)
58
m_phase1 = new PhaseExec1( this );
59
m_phase2 = new PhaseExec2( this );
60
m_phaseInter = new PhaseInter( this );
61
m_phaseIdle = new PhaseIdle( this );
62
m_phaseCurr = m_phase1;
68
Integer::setDefaultBitmask(0xff);
70
// Test code for logging to disk:
71
for( int i=0; i<4; i++ ) osc_pin_Number[i] = 254;
74
pic_processor::~pic_processor()
79
delete_SfrReg(pclath);
80
delete_SfrReg(status);
90
delete m_configMemory;
92
if( m_MCLR) m_MCLR->setMonitor(0);
93
if( m_MCLR_Save) m_MCLR_Save->setMonitor(0);
94
if( m_MCLRMonitor) delete m_MCLRMonitor;
96
if( clksource) delete clksource;
97
if( clkcontrol) delete clkcontrol;
100
//-------------------------------------------------------------------
104
// The purpose of this member function is to 'create' a pic processor.
105
// Since this is a base class member function, only those things that
106
// are common to all pics are created.
108
void pic_processor::create( )
110
init_program_memory( program_memory_size() );
111
init_register_memory( register_memory_size() );
115
Wreg = new WREG( this, "W" );
116
pcl = new PCL( this, "pcl" );
117
pclath = new PCLATH( this, "pclath" );
118
status = new StatusReg( this );
119
indf = new INDF( this, "indf" );
121
register_bank = ®isters[0]; // Define the active register bank
123
create_config_memory();
126
//-------------------------------------------------------------------
130
// The purpose of this routine is to add one special function register
131
// to the file registers. If the sfr has a physical address( like the
132
// status or tmr0 registers) then a pointer to that register will be
133
// placed in the file register map.
135
// FIXME It doesn't make any sense to initialize the por_value here!
136
// FIXME The preferred way is to initialize all member data in their
137
// FIXME parent's constructor.
139
void pic_processor::add_SfrReg( Register *reg, uint addr,
140
RegisterValue por_value,
141
const char *new_name,
145
if(addr < register_memory_size())
149
if( registers[addr]->isa() == Register::INVALID_REGISTER)
151
delete registers[addr];
152
registers[addr] = reg;
155
else registers[addr] = reg;
160
if(new_name) reg->new_name(new_name);
162
reg->value = por_value;
163
reg->por_value = por_value; /// FIXME why are we doing this?
167
// Use this function when register is initialized on WDT reset to
168
// same value as a POR.
169
void pic_processor::add_SfrRegR(SfrReg *reg, uint addr,
170
RegisterValue por_value,
171
const char *new_name,
174
add_SfrReg( reg, addr, por_value, new_name, warn_dup );
175
reg->wdtr_value = por_value;
179
// This both deletes the register from the registers array,
180
// but also deletes the register object.
182
void pic_processor::delete_SfrReg( Register *pReg )
186
uint a = pReg->getAddress();
188
if( 0) cout << __FUNCTION__ << " addr = 0x"<<hex<<a <<" reg " << pReg->name_str<<endl;
190
if( a<nRegisters && registers[a] == pReg ) delete_file_registers(a,a);
195
// This is the inverse of add_SfrReg and does not delete the register.
197
void pic_processor::remove_SfrReg(Register *ppReg)
201
uint a = ppReg->getAddress();
202
if( a == AN_INVALID_ADDRESS ) return;
203
if( registers[a] == ppReg ) delete_file_registers(a,a,true);
207
bool pic_processor::set_config_word( uint address, uint cfg_word )
209
int i = get_config_index(address);
213
m_configMemory->getConfigWord(i)->set((int)cfg_word);
216
config_word = cfg_word;
223
uint pic_processor::get_config_word(uint address)
225
int i= get_config_index(address);
227
if( i >= 0 ) return m_configMemory->getConfigWord(i)->getVal();
232
int pic_processor::get_config_index(uint address)
236
for(int i = 0; i < m_configMemory->getnConfigWords(); i++)
238
if( m_configMemory->getConfigWord(i))
240
if( m_configMemory->getConfigWord(i)->ConfigWordAdd() == address)
250
//------------------------------------------------------------------------
251
// ConfigMemory - Base class
252
ConfigWord::ConfigWord(const char*_name, uint default_val, pic_processor *pCpu, uint addr, bool EEw)
253
: Integer(_name, default_val ), m_pCpu(pCpu), m_addr(addr),
257
void ConfigWord::get(int64_t &i)
262
//------------------------------------------------------------------------
263
ConfigMemory::ConfigMemory(pic_processor *pCpu, uint nWords)
265
, m_nConfigWords(nWords)
267
if( nWords > 0 && nWords < 100)
269
m_ConfigWords = new ConfigWord*[nWords];
271
for( uint i=0; i<nWords; i++ ) m_ConfigWords[i] = 0;
275
ConfigMemory::~ConfigMemory()
277
delete [] m_ConfigWords;
280
int ConfigMemory::addConfigWord(uint addr, ConfigWord *pConfigWord)
282
if( addr < m_nConfigWords)
284
m_ConfigWords[addr] = pConfigWord;
291
ConfigWord *ConfigMemory::getConfigWord(uint addr)
293
return addr < m_nConfigWords ? m_ConfigWords[addr] : 0;
295
//-------------------------------------------------------------------
296
class MCLRPinMonitor : public PinMonitor
299
MCLRPinMonitor(pic_processor *pCpu);
302
virtual void setDrivenState(char);
303
virtual void setDrivingState(char) {}
304
virtual void set_nodeVoltage(double) {}
305
virtual void putState(char) {}
306
virtual void setDirection() {}
309
pic_processor *m_pCpu;
310
char m_cLastResetState;
313
MCLRPinMonitor::MCLRPinMonitor(pic_processor *pCpu)
315
m_cLastResetState('I') // I is not a valid state. It's used here for 'I'nitialization
318
void MCLRPinMonitor::setDrivenState(char newState)
320
if( newState =='0' || newState =='w')
322
m_cLastResetState = '0';
323
m_pCpu->reset(MCLR_RESET);
326
if( newState =='1' || newState =='W')
328
if( m_cLastResetState == '0') m_pCpu->reset(EXIT_RESET);
330
m_cLastResetState = '1';
334
//-------------------------------------------------------------------
335
void pic_processor::createMCLRPin(int pkgPinNumber)
337
if( m_MCLR) cout << "BUG?: assigning multiple MCLR pins: " << __FILE__ << dec << " " << __LINE__ << endl;
339
assign_pin( pkgPinNumber, m_MCLR );
341
m_MCLRMonitor = new MCLRPinMonitor(this);
342
m_MCLR->setMonitor(m_MCLRMonitor);
345
//-------------------------------------------------------------------
346
// This function is called instead of createMCLRPin where the pin
347
// is already defined, but the configuration word has set the function
350
void pic_processor::assignMCLRPin(int pkgPinNumber)
354
m_MCLR_pin = pkgPinNumber;
355
m_MCLR = new IOPIN( "MCLR", OPEN_COLLECTOR ) ;
357
m_MCLR_Save = get_pin( pkgPinNumber );
358
assign_pin( pkgPinNumber,m_MCLR );
360
m_MCLRMonitor = new MCLRPinMonitor(this);
361
m_MCLR->setMonitor( m_MCLRMonitor );
363
else if( m_MCLR != get_pin( pkgPinNumber ) )
365
cout << "BUG?: assigning multiple MCLR pins: "
366
<< dec << pkgPinNumber << " " << __FILE__ << " "
370
//-------------------------------------------------------------------
371
// This function sets the pin currently set as MCLR back to its original function
372
void pic_processor::unassignMCLRPin()
376
assign_pin( m_MCLR_pin, m_MCLR_Save );
380
m_MCLR->setMonitor(0);
385
delete m_MCLRMonitor;
386
m_MCLRMonitor = NULL;
391
//--------------------------------------------------
393
class IO_SignalControl : public SignalControl
396
IO_SignalControl(char _dir){ direction = _dir; }
397
~IO_SignalControl(){}
398
virtual char getState() { return direction; }
399
virtual void release() {}
400
void setState(char _dir) { direction = _dir; }
406
// This function sets a label on a pin and if PinMod is defined
407
// removes its control from it's port register
409
void pic_processor::set_clk_pin(uint pkg_Pin_Number,
413
PicPortRegister *m_port,
414
PicTrisRegister *m_tris,
415
PicLatchRegister *m_lat)
421
uint mask = m_port->getEnableMask();
422
mask &= ~(1<< PinMod->getPinNumber());
423
m_port->setEnableMask(mask);
425
if( m_tris ) m_tris->setEnableMask(mask);
426
if( m_lat ) m_lat->setEnableMask(mask);
430
clksource = new PeripheralSignalSource(PinMod);
431
clkcontrol = new IO_SignalControl(in ? '1' : '0');
433
PinMod->setSource( clksource );
434
PinMod->setControl( clkcontrol );
435
PinMod->updatePinModule();
439
// This function reverses the effects of the previous function
440
void pic_processor::clr_clk_pin(uint pkg_Pin_Number,
442
PicPortRegister *m_port,
443
PicTrisRegister *m_tris,
444
PicLatchRegister *m_lat)
450
uint mask = m_port->getEnableMask();
451
mask |=( 1<< PinMod->getPinNumber());
452
m_port->setEnableMask(mask);
454
if( m_tris) m_tris->setEnableMask(mask);
455
if( m_lat) m_lat->setEnableMask(mask);
457
PinMod->setSource(0);
458
PinMod->setControl(0);
459
PinMod->updatePinModule();
463
void pic_processor::osc_mode(uint value)
466
uint pin_Number = get_osc_pin_Number(0);
468
if( pin_Number < 253) m_pin = get_pin( pin_Number );
470
if(( pin_Number = get_osc_pin_Number(1)) < 253
471
&&( m_pin = get_pin( pin_Number )) )
476
set_clk_pin(pin_Number, m_osc_Monitor[1], "OSC2", true);
481
set_clk_pin(pin_Number, m_osc_Monitor[1], "CLKO", false);
483
else clr_clk_pin(pin_Number, m_osc_Monitor[1]);
487
void pic_processor::Wput(uint value)
492
uint pic_processor::Wget()
497
void pic_processor::set_eeprom( EEPROM *e )
502
void pic_processor::enter_sleep() // processor is about to go to sleep, update the status register.
507
sleep_time = m_cycle;
510
save_pNextPhase = m_phaseCurr->getNextPhase();
511
save_CurrentPhase = m_phaseCurr;
512
m_phaseCurr->setNextPhase( m_phaseIdle );
513
m_phaseCurr = m_phaseIdle;
514
m_phaseCurr->setNextPhase( m_phaseIdle );
515
m_ActivityState = ePASleeping;
518
void pic_processor::exit_sleep()
520
if( m_cycle == sleep_time )// If enter and exit sleep at same clock cycle, restore execute state
522
m_phaseCurr = save_CurrentPhase;
523
m_phaseCurr->setNextPhase( save_pNextPhase );
527
m_phaseCurr = m_phase1;
528
m_phaseCurr->setNextPhase( m_phase1 );
530
m_ActivityState = ePAActive;
533
bool pic_processor::is_sleeping()
535
return m_ActivityState == ePASleeping;
538
void pic_processor::BP_set_interrupt()
540
m_phaseInter->firstHalf();
543
void pic_processor::pm_write( ) // program memory write
545
m_ActivityState = ePAPMWrite;
547
do incrementCycle(); // burn cycles until we're through writing
548
while( have_pm_write() );
551
void pic_processor::reset( RESET_TYPE r )// Reset the pic on desired reset type.
560
//m_activeCB.clear(); // Usart not working here
562
//qDebug() << "pic_processor::reset"<<m_activeCB.uniqueKeys();
567
//cout << "POR reset\n";
568
m_phaseCurr = m_phaseCurr ? m_phaseCurr : m_phase1;
569
m_ActivityState = ePAActive;
573
cout << "Reset due to Software reset instruction\n";
574
m_phaseCurr = m_phase1;
575
m_phaseCurr->setNextPhase( m_phase1 );
576
m_ActivityState = ePAActive;
580
cout << "MCLR reset\n";
581
m_phaseCurr = m_phaseIdle;
582
m_phaseCurr->setNextPhase( m_phaseIdle );
583
m_ActivityState = ePAIdle;
587
cout << "IO reset\n";
588
m_phaseCurr = m_phase1;
589
m_phaseCurr->setNextPhase( m_phase1 );
590
m_ActivityState = ePAActive;
594
cout << "Reset on Watch Dog Timer expire\n";
595
m_phaseCurr = m_phaseCurr ? m_phaseCurr : m_phase1;
596
m_phaseCurr->setNextPhase( m_phase1 );
597
m_ActivityState = ePAActive;
600
case EXIT_RESET: // MCLR reset has cleared
601
cout <<"MCLR low, resume execution\n";
602
m_phaseCurr = m_phaseCurr ? m_phaseCurr : m_phase1;
603
m_phaseCurr->setNextPhase(m_phase1);
604
m_ActivityState = ePAActive;
609
cout << "Reset on Stack overflow\n";
610
m_phaseCurr = m_phaseCurr ? m_phaseCurr : m_phaseIdle;
611
m_phaseCurr->setNextPhase(m_phaseIdle);
612
m_ActivityState = ePAActive;
616
cout << "Reset on Stack undeflow\n";
617
m_phaseCurr = m_phaseCurr ? m_phaseCurr : m_phaseIdle;
618
m_phaseCurr->setNextPhase(m_phaseIdle);
619
m_ActivityState = ePAActive;
623
printf("pic_processor::reset unknow reset type %d\n", r);
624
m_ActivityState = ePAActive;