Timer8 now has a variable amount of output compare units.
[avr-sim.git] / src / Device.cpp
blob1457b8a206e3f64122bbdb296d164d71b9413d20
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 #ifdef DEBUG
34 # include <iostream>
35 #endif
37 namespace avr {
38 Device::Device(SimulationClock & clock, const char *devicename, bool allowStopping)
39 : SimulationObject(clock), core(0), allowStopping(allowStopping) {
41 if( devicename != 0 )
42 avr::DeviceSettings::load( this, devicename );
44 core->init();
45 reset(POR_RESET);
47 frq = 1000000000 / defaultFrequency;
48 clock.setBreakDelta( frq, this );
51 Device::~Device() {
52 if( core != 0 )
53 delete core;
56 void Device::load(Program & program) {
57 Section sec;
58 while( program.readNextSection(sec) ) {
59 //only read flash bytes and data
60 if( sec.isFlash() ) {
61 core->loadFlash( sec.data(), sec.address(), sec.size() );
63 #ifdef DEBUG
64 std::cout << "Flash: " << sec.size() << " bytes at " << sec.address() << std::endl;
65 #endif
68 if( sec.isEeprom() ) {
69 eeprom->write( sec.address(), sec.data(), sec.size() );
71 #ifdef DEBUG
72 std::cout << "Eeprom: " << sec.size() << " bytes at " << sec.address() << std::endl;
73 #endif
78 void Device::setClockFrequency(ClockFrequency frq) {
79 this->frq = 1000000000 / frq;
80 clock.reassignBreak( this, this->frq );
83 void Device::buildCore(unsigned int ioSpaceSize, unsigned int ramSize,
84 unsigned int flashSize, unsigned int pageSize,
85 unsigned int stackMask, int pcBytes /*= 2*/,
86 ERam *eram /*= 0*/) {
87 core = new Core(bus, ioSpaceSize, ramSize, flashSize,
88 pageSize, stackMask, pcBytes, eram);
91 void Device::buildHardware(const char *hwname, HardwareSettings & hws) {
92 Hardware *hw = HardwareFactory::build(hwname, hws, bus);
94 std::string name, binding;
95 while( hws.getBinding(name, binding) ) {
96 #ifdef DEBUG
97 std::cout << "Binding \"" << name << "\" to \"" << binding << "\"" << std::endl;
98 #endif
100 if( ! hw->attachReg( name.c_str(), core->getIoreg( binding ) ) )
101 throw util::RuntimeException(
102 util::format("%s::attachReg: unknown register %s") % hwname % name );
105 if( ! hw->finishBuild() )
106 throw util::RuntimeException(
107 util::format("Failed to build hardware module %s: missing register") % hwname );
109 bus.addHardware( hw );
111 // Special handling for eeprom
112 if( strcmp(hwname, "eeprom") == 0 )
113 eeprom = static_cast<Eeprom*>( hw );
116 void Device::addIOReg(unsigned int address,
117 const std::string & name, unsigned char intial) {
118 core->addIOReg(address, name, intial);
121 void Device::addInterrupt(unsigned int vector, unsigned int address,
122 const char *name) {
123 bus.addInterrupt( vector, address, name );
126 void Device::addPin(unsigned int id, const char *name, unsigned int num) {
127 #ifdef DEBUG
128 std::cout << "Pin " << id << " => " << name << std::endl;
129 #endif
131 if( pins.size() == 0 )
132 pins.resize( num );
134 Pin *pin = new Pin();
135 pins[ id ] = pin;
137 // Multiple names?
138 if( name[0] == '[' ) {
139 static const std::string delimiters(":");
140 std::string names( name + 1, strlen(name) - 2 );
142 // skip delimiters at beginning.
143 std::string::size_type lastPos = names.find_first_not_of(delimiters, 0);
145 // find first "non-delimiter".
146 std::string::size_type pos = names.find_first_of(delimiters, lastPos);
148 while( std::string::npos != pos || std::string::npos != lastPos ) {
149 // found a name, add it to the map.
150 std::string n = names.substr(lastPos, pos - lastPos);
151 name2pin.insert( std::make_pair(n, pin) );
153 // skip delimiters. Note the "not_of"
154 lastPos = names.find_first_not_of(delimiters, pos);
156 // find next "non-delimiter"
157 pos = names.find_first_of(delimiters, lastPos);
159 } else {
160 name2pin.insert( std::make_pair(name, pin) );
164 Pin *Device::getPin(const std::string & name) const {
165 std::map<std::string, Pin *>::const_iterator it;
166 if( (it = name2pin.find( name )) != name2pin.end() )
167 return it->second;
169 throw util::RuntimeException(
170 util::format("No pin with name %s on this device") % name );
173 void Device::addAnalyzer(ScriptEngine *vm, const char *name) {
174 AnalyzerFactory factory;
175 core->addAnalyzer( factory.newAnalyzer(core, vm, name) );
178 void Device::trace(const char *tracefile) {
179 core->addAnalyzer( new TraceAnalyzer(core, tracefile) );
182 void Device::reset(unsigned int type) {
183 core->reset(type);
184 bus.reset();
187 void Device::step() {
188 if( ! bus.isHoldingCPU() )
189 core->step();
191 bus.step();
193 if( ! (allowStopping && core->isStopped()) )
194 clock.setBreakDelta( frq, this );
197 DebugInterface *Device::debugInterface() {
198 return new DebugInterface(*this, *core);