Fixed problem in DeviceSettings::strParam, returned wrong string
[avr-sim.git] / src / Device.cpp
blobd97b9b028064774f86f5d1ae90b2ae189c4e46ca
1 /*
2 * avr-sim: An atmel AVR simulator
3 * Copyright (C) 2008 Tom Haber
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "Device.h"
20 #include "DeviceSettings.h"
21 #include "Core.h"
22 #include "HardwareFactory.h"
23 #include "Eeprom.h"
24 #include "DebugInterface.h"
25 #include "Pin.h"
27 #include "Analyzer.h"
28 #include "TraceAnalyzer.h"
29 #include "Program.h"
30 #include "Format.h"
31 #include "RuntimeException.h"
33 #include <cstring>
35 #ifdef DEBUG
36 # include <iostream>
37 #endif
39 namespace avr {
40 Device::Device(sim::SimulationClock & clock, const char *devicename, bool allowStopping)
41 : sim::SimulationObject(clock), core(0), allowStopping(allowStopping) {
43 if( devicename != 0 )
44 avr::DeviceSettings::load( this, devicename );
46 core->init();
47 reset(POR_RESET);
49 frq = 1000000000 / defaultFrequency;
50 clock.setBreakDelta( frq, this );
53 Device::~Device() {
54 if( core != 0 )
55 delete core;
57 for(size_t i = 0; i < pins.size(); ++i)
58 delete pins[i];
59 pins.clear();
62 void Device::load(Program & program) {
63 Section sec;
64 while( program.readNextSection(sec) ) {
65 //only read flash bytes and data
66 if( sec.isFlash() ) {
67 core->loadFlash( sec.data(), sec.address(), sec.size() );
69 #ifdef DEBUG
70 std::cout << "Flash: " << sec.size() << " bytes at " << sec.address() << std::endl;
71 #endif
74 if( sec.isEeprom() ) {
75 eeprom->write( sec.address(), sec.data(), sec.size() );
77 #ifdef DEBUG
78 std::cout << "Eeprom: " << sec.size() << " bytes at " << sec.address() << std::endl;
79 #endif
84 void Device::setClockFrequency(ClockFrequency frq) {
85 this->frq = 1000000000 / frq;
86 clock.reassignBreak( this, this->frq );
89 void Device::buildCore(unsigned int ioSpaceSize, unsigned int ramSize,
90 unsigned int flashSize, unsigned int pageSize,
91 unsigned int stackMask, int pcBytes /*= 2*/,
92 ERam *eram /*= 0*/) {
93 core = new Core(bus, ioSpaceSize, ramSize, flashSize,
94 pageSize, stackMask, pcBytes, eram);
97 void Device::buildHardware(const char *hwname, HardwareSettings & hws) {
98 Hardware *hw = HardwareFactory::build(hwname, hws, bus);
100 std::string name, binding;
101 while( hws.getBinding(name, binding) ) {
102 #ifdef DEBUG
103 std::cout << "Binding \"" << name << "\" to \"" << binding << "\"" << std::endl;
104 #endif
106 if( ! hw->attachReg( name.c_str(), core->getIoreg( binding ) ) )
107 throw util::RuntimeException(
108 util::format("%s::attachReg: unknown register %s") % hwname % name );
111 if( ! hw->finishBuild() )
112 throw util::RuntimeException(
113 util::format("Failed to build hardware module %s: missing register") % hwname );
115 bus.addHardware( hw );
117 // Special handling for eeprom
118 if( strcmp(hwname, "eeprom") == 0 )
119 eeprom = static_cast<Eeprom*>( hw );
122 void Device::addIOReg(unsigned int address,
123 const std::string & name, unsigned char intial) {
124 core->addIOReg(address, name, intial);
127 void Device::addInterrupt(unsigned int vector, unsigned int address,
128 const char *name) {
129 bus.addInterrupt( vector, address, name );
132 void Device::addPin(unsigned int id, const char *name, unsigned int num) {
133 #ifdef DEBUG
134 std::cout << "Pin " << id << " => " << name << std::endl;
135 #endif
137 if( pins.size() == 0 )
138 pins.resize( num );
140 Pin *pin = new Pin();
141 pins[ id - 1 ] = pin;
143 // Multiple names?
144 if( name[0] == '[' ) {
145 static const std::string delimiters(":");
146 std::string names( name + 1, strlen(name) - 2 );
148 // skip delimiters at beginning.
149 std::string::size_type lastPos = names.find_first_not_of(delimiters, 0);
151 // find first "non-delimiter".
152 std::string::size_type pos = names.find_first_of(delimiters, lastPos);
154 while( std::string::npos != pos || std::string::npos != lastPos ) {
155 // found a name, add it to the map.
156 std::string n = names.substr(lastPos, pos - lastPos);
157 name2pin.insert( std::make_pair(n, pin) );
159 // skip delimiters. Note the "not_of"
160 lastPos = names.find_first_not_of(delimiters, pos);
162 // find next "non-delimiter"
163 pos = names.find_first_of(delimiters, lastPos);
165 } else {
166 name2pin.insert( std::make_pair(name, pin) );
170 Pin *Device::getPin(const std::string & name) const {
171 std::map<std::string, Pin *>::const_iterator it;
172 if( (it = name2pin.find( name )) != name2pin.end() )
173 return it->second;
175 throw util::RuntimeException(
176 util::format("No pin with name %s on this device") % name );
179 void Device::addAnalyzer(const char *name) {
180 core->addAnalyzer( AnalyzerFactory::newAnalyzer(core, name) );
183 void Device::addAnalyzer(Analyzer *analyzer) {
184 core->addAnalyzer( analyzer );
187 void Device::trace(const char *tracefile) {
188 core->addAnalyzer( new TraceAnalyzer(core, tracefile) );
191 void Device::reset(unsigned int type) {
192 core->reset(type);
193 bus.reset();
196 void Device::step() {
197 if( ! bus.isHoldingCPU() )
198 core->step();
200 bus.step();
202 if( ! (allowStopping && core->isStopped()) )
203 clock.setBreakDelta( frq, this );
206 DebugInterface *Device::debugInterface() {
207 return new DebugInterface(*this, *core);