Bug fix: check if vm exists
[avr-sim.git] / Device.cpp
blobed7f43ada8207352683e7327f4d7e2e417252ab2
1 #include "Device.h"
2 #include "DeviceSettings.h"
3 #include "Core.h"
4 #include "HardwareFactory.h"
5 #include "Eeprom.h"
6 #include "DebugInterface.h"
8 #include "Program.h"
9 #include "Format.h"
10 #include "RuntimeException.h"
12 #ifdef DEBUG
13 # include <iostream>
14 #endif
16 namespace avr {
17 Device::Device(SimulationClock & clock, const char *devicename)
18 : SimulationObject(clock), core(0) {
20 intVectors.resize( Bus::intVectorsSize );
22 if( devicename != 0 )
23 avr::DeviceSettings::load( this, devicename );
25 core->init();
26 reset(POR_RESET);
28 frq = 1000000000 / defaultFrequency;
29 clock.setBreakDelta( frq, this );
32 Device::~Device() {
33 if( core != 0 )
34 delete core;
37 void Device::load(const Program & program) {
38 Section sec;
39 while( program.readNextSection(sec) ) {
40 //only read flash bytes and data
41 if( sec.isFlash() ) {
42 core->loadFlash( sec.data(), sec.address(), sec.size() );
44 #ifdef DEBUG
45 std::cout << "Flash: " << sec.size() << " bytes at " << sec.address() << std::endl;
46 #endif
49 if( sec.isEeprom() ) {
50 eeprom->write( sec.address(), sec.data(), sec.size() );
52 #ifdef DEBUG
53 std::cout << "Eeprom: " << sec.size() << " bytes at " << sec.address() << std::endl;
54 #endif
59 void Device::setClockFrequency(ClockFrequency frq) {
60 this->frq = 1000000000 / frq;
61 clock.reassignBreak( this, this->frq );
64 void Device::buildCore(unsigned int ioSpaceSize, unsigned int ramSize,
65 unsigned int flashSize, unsigned int stackMask,
66 int pcBytes /*= 2*/, ERam *eram /*= 0*/) {
67 core = new Core(bus, ioSpaceSize, ramSize,
68 flashSize, stackMask, pcBytes, eram);
71 void Device::buildHardware(const char *hwname, HardwareSettings & hws) {
72 Hardware *hw = HardwareFactory::build(hwname, hws, bus);
74 std::string name, binding;
75 while( hws.getBinding(name, binding) ) {
76 #ifdef DEBUG
77 std::cout << "Binding \"" << name << "\" to \"" << binding << "\"" << std::endl;
78 #endif
80 if( ! hw->attachReg( name.c_str(), core->getIoreg( binding ) ) )
81 throw util::RuntimeException(
82 util::format("%s::attachReg: unknown register %s") % hwname % name );
85 bus.addHardware( hw );
87 // Special handling for eeprom
88 if( strcmp(hwname, "eeprom") )
89 eeprom = static_cast<Eeprom*>( hw );
92 void Device::addIOReg(unsigned int address,
93 const std::string & name, unsigned char intial) {
94 core->addIOReg(address, name, intial);
97 void Device::addInterrupt(unsigned int vector, unsigned int address,
98 const char *name) {
99 intVectors[vector - 1] = IntVect( address, name );
102 void Device::addAnalyzers(ScriptEngine *vm,
103 const std::list<const char *> & analyzers) {
107 void Device::reset(unsigned int type) {
108 core->reset(type);
109 bus.reset();
112 void Device::step() {
113 bool instrFinished = false;
114 if( ! bus.isHoldingCPU() )
115 instrFinished = core->step();
117 bus.step();
120 * TODO Is this the correct place to do this?
121 * - What if the hardware is holding the CPU?
123 unsigned int vect;
124 if( instrFinished && bus.pendingInterrupt(vect) ) {
125 unsigned int addr = intVectors[ vect ].address;
126 if( core->interrupt( vect, addr ) )
127 bus.clearInterrupt(vect);
130 clock.setBreakDelta( frq, this );
133 DebugInterface *Device::debugInterface() {
134 return new DebugInterface(*this, *core);