avr: Fix documentation for Bus
[avr-sim.git] / src / Device.cpp
blob2c4b7a7dc524a69b6458ee7e77541f9733ede27f
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;
58 void Device::load(Program & program) {
59 Section sec;
60 while( program.readNextSection(sec) ) {
61 //only read flash bytes and data
62 if( sec.isFlash() ) {
63 core->loadFlash( sec.data(), sec.address(), sec.size() );
65 #ifdef DEBUG
66 std::cout << "Flash: " << sec.size() << " bytes at " << sec.address() << std::endl;
67 #endif
70 if( sec.isEeprom() ) {
71 eeprom->write( sec.address(), sec.data(), sec.size() );
73 #ifdef DEBUG
74 std::cout << "Eeprom: " << sec.size() << " bytes at " << sec.address() << std::endl;
75 #endif
80 void Device::setClockFrequency(ClockFrequency frq) {
81 this->frq = 1000000000 / frq;
82 clock.reassignBreak( this, this->frq );
85 void Device::buildCore(unsigned int ioSpaceSize, unsigned int ramSize,
86 unsigned int flashSize, unsigned int pageSize,
87 unsigned int stackMask, int pcBytes /*= 2*/,
88 ERam *eram /*= 0*/) {
89 core = new Core(bus, ioSpaceSize, ramSize, flashSize,
90 pageSize, stackMask, pcBytes, eram);
93 void Device::buildHardware(const char *hwname, HardwareSettings & hws) {
94 Hardware *hw = HardwareFactory::build(hwname, hws, bus);
96 std::string name, binding;
97 while( hws.getBinding(name, binding) ) {
98 #ifdef DEBUG
99 std::cout << "Binding \"" << name << "\" to \"" << binding << "\"" << std::endl;
100 #endif
102 if( ! hw->attachReg( name.c_str(), core->getIoreg( binding ) ) )
103 throw util::RuntimeException(
104 util::format("%s::attachReg: unknown register %s") % hwname % name );
107 if( ! hw->finishBuild() )
108 throw util::RuntimeException(
109 util::format("Failed to build hardware module %s: missing register") % hwname );
111 bus.addHardware( hw );
113 // Special handling for eeprom
114 if( strcmp(hwname, "eeprom") == 0 )
115 eeprom = static_cast<Eeprom*>( hw );
118 void Device::addIOReg(unsigned int address,
119 const std::string & name, unsigned char intial) {
120 core->addIOReg(address, name, intial);
123 void Device::addInterrupt(unsigned int vector, unsigned int address,
124 const char *name) {
125 bus.addInterrupt( vector, address, name );
128 void Device::addPin(unsigned int id, const char *name, unsigned int num) {
129 #ifdef DEBUG
130 std::cout << "Pin " << id << " => " << name << std::endl;
131 #endif
133 if( pins.size() == 0 )
134 pins.resize( num );
136 Pin *pin = new Pin();
137 pins[ id ] = pin;
139 // Multiple names?
140 if( name[0] == '[' ) {
141 static const std::string delimiters(":");
142 std::string names( name + 1, strlen(name) - 2 );
144 // skip delimiters at beginning.
145 std::string::size_type lastPos = names.find_first_not_of(delimiters, 0);
147 // find first "non-delimiter".
148 std::string::size_type pos = names.find_first_of(delimiters, lastPos);
150 while( std::string::npos != pos || std::string::npos != lastPos ) {
151 // found a name, add it to the map.
152 std::string n = names.substr(lastPos, pos - lastPos);
153 name2pin.insert( std::make_pair(n, pin) );
155 // skip delimiters. Note the "not_of"
156 lastPos = names.find_first_not_of(delimiters, pos);
158 // find next "non-delimiter"
159 pos = names.find_first_of(delimiters, lastPos);
161 } else {
162 name2pin.insert( std::make_pair(name, pin) );
166 Pin *Device::getPin(const std::string & name) const {
167 std::map<std::string, Pin *>::const_iterator it;
168 if( (it = name2pin.find( name )) != name2pin.end() )
169 return it->second;
171 throw util::RuntimeException(
172 util::format("No pin with name %s on this device") % name );
175 void Device::addAnalyzer(const char *name) {
176 core->addAnalyzer( AnalyzerFactory::newAnalyzer(core, name) );
179 void Device::addAnalyzer(Analyzer *analyzer) {
180 core->addAnalyzer( analyzer );
183 void Device::trace(const char *tracefile) {
184 core->addAnalyzer( new TraceAnalyzer(core, tracefile) );
187 void Device::reset(unsigned int type) {
188 core->reset(type);
189 bus.reset();
192 void Device::step() {
193 if( ! bus.isHoldingCPU() )
194 core->step();
196 bus.step();
198 if( ! (allowStopping && core->isStopped()) )
199 clock.setBreakDelta( frq, this );
202 DebugInterface *Device::debugInterface() {
203 return new DebugInterface(*this, *core);