Fixed nasty eeprom bug
[avr-sim.git] / src / Device.cpp
blobac0f4e22b9f130725656134e5c3a2f141120a105
1 #include "Device.h"
2 #include "DeviceSettings.h"
3 #include "Core.h"
4 #include "HardwareFactory.h"
5 #include "Eeprom.h"
6 #include "DebugInterface.h"
7 #include "Pin.h"
9 #include "Analyzer.h"
10 #include "TraceAnalyzer.h"
11 #include "Program.h"
12 #include "Format.h"
13 #include "RuntimeException.h"
15 #ifdef DEBUG
16 # include <iostream>
17 #endif
19 namespace avr {
20 Device::Device(SimulationClock & clock, const char *devicename)
21 : SimulationObject(clock), core(0) {
23 if( devicename != 0 )
24 avr::DeviceSettings::load( this, devicename );
26 core->init();
27 reset(POR_RESET);
29 frq = 1000000000 / defaultFrequency;
30 clock.setBreakDelta( frq, this );
33 Device::~Device() {
34 if( core != 0 )
35 delete core;
38 void Device::load(Program & program) {
39 Section sec;
40 while( program.readNextSection(sec) ) {
41 //only read flash bytes and data
42 if( sec.isFlash() ) {
43 core->loadFlash( sec.data(), sec.address(), sec.size() );
45 #ifdef DEBUG
46 std::cout << "Flash: " << sec.size() << " bytes at " << sec.address() << std::endl;
47 #endif
50 if( sec.isEeprom() ) {
51 eeprom->write( sec.address(), sec.data(), sec.size() );
53 #ifdef DEBUG
54 std::cout << "Eeprom: " << sec.size() << " bytes at " << sec.address() << std::endl;
55 #endif
60 void Device::setClockFrequency(ClockFrequency frq) {
61 this->frq = 1000000000 / frq;
62 clock.reassignBreak( this, this->frq );
65 void Device::buildCore(unsigned int ioSpaceSize, unsigned int ramSize,
66 unsigned int flashSize, unsigned int stackMask,
67 int pcBytes /*= 2*/, ERam *eram /*= 0*/) {
68 core = new Core(bus, ioSpaceSize, ramSize,
69 flashSize, stackMask, pcBytes, eram);
72 void Device::buildHardware(const char *hwname, HardwareSettings & hws) {
73 Hardware *hw = HardwareFactory::build(hwname, hws, bus);
75 std::string name, binding;
76 while( hws.getBinding(name, binding) ) {
77 #ifdef DEBUG
78 std::cout << "Binding \"" << name << "\" to \"" << binding << "\"" << std::endl;
79 #endif
81 if( ! hw->attachReg( name.c_str(), core->getIoreg( binding ) ) )
82 throw util::RuntimeException(
83 util::format("%s::attachReg: unknown register %s") % hwname % name );
86 if( ! hw->finishBuild() )
87 throw util::RuntimeException(
88 util::format("Failed to build hardware module %s: missing register") % hwname );
90 bus.addHardware( hw );
92 // Special handling for eeprom
93 if( strcmp(hwname, "eeprom") == 0 )
94 eeprom = static_cast<Eeprom*>( hw );
97 void Device::addIOReg(unsigned int address,
98 const std::string & name, unsigned char intial) {
99 core->addIOReg(address, name, intial);
102 void Device::addInterrupt(unsigned int vector, unsigned int address,
103 const char *name) {
104 bus.addInterrupt( vector, address, name );
107 void Device::addPin(unsigned int id, const char *name, unsigned int num) {
108 #ifdef DEBUG
109 std::cout << "Pin " << id << " => " << name << std::endl;
110 #endif
112 if( pins.size() == 0 )
113 pins.resize( num );
115 Pin *pin = new Pin();
116 pins[ id ] = pin;
118 // Multiple names?
119 if( name[0] == '[' ) {
120 static const std::string delimiters(":");
121 std::string names( name + 1, strlen(name) - 2 );
123 // skip delimiters at beginning.
124 std::string::size_type lastPos = names.find_first_not_of(delimiters, 0);
126 // find first "non-delimiter".
127 std::string::size_type pos = names.find_first_of(delimiters, lastPos);
129 while( std::string::npos != pos || std::string::npos != lastPos ) {
130 // found a name, add it to the map.
131 std::string n = names.substr(lastPos, pos - lastPos);
132 name2pin.insert( std::make_pair(n, pin) );
134 // skip delimiters. Note the "not_of"
135 lastPos = names.find_first_not_of(delimiters, pos);
137 // find next "non-delimiter"
138 pos = names.find_first_of(delimiters, lastPos);
140 } else {
141 name2pin.insert( std::make_pair(name, pin) );
145 Pin *Device::getPin(const std::string & name) const {
146 std::map<std::string, Pin *>::const_iterator it;
147 if( (it = name2pin.find( name )) != name2pin.end() )
148 return it->second;
150 throw util::RuntimeException(
151 util::format("No pin with name %s on this device") % name );
154 void Device::addAnalyzer(ScriptEngine *vm, const char *name) {
155 AnalyzerFactory factory;
156 core->addAnalyzer( factory.newAnalyzer(core, vm, name) );
159 void Device::trace(const char *tracefile) {
160 core->addAnalyzer( new TraceAnalyzer(core, tracefile) );
163 void Device::reset(unsigned int type) {
164 core->reset(type);
165 bus.reset();
168 void Device::step() {
169 if( ! bus.isHoldingCPU() )
170 core->step();
172 bus.step();
173 clock.setBreakDelta( frq, this );
176 DebugInterface *Device::debugInterface() {
177 return new DebugInterface(*this, *core);