Fixed problem in DeviceSettings::strParam, returned wrong string
[avr-sim.git] / src / avr-sim.cpp
blob5a8bb5985043c434791373ef23d824ffe8bed991
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 "config.h"
21 #include <iostream>
22 #include <getopt.h>
23 #include <errno.h>
24 #include <cstring>
26 #ifdef _POSIX_SOURCE
27 # include <signal.h>
28 # include <setjmp.h>
30 # define TIOCGWINSZ
31 # include <sys/ioctl.h>
32 #endif
34 #include "VerboseInfo.h"
35 #include "SimulationClock.h"
36 #include "GdbServer.h"
38 #include "BfdProgram.h"
39 #include "HexProgram.h"
41 #ifdef ENABLE_SCRIPTING
42 #include "ScriptEngine.h"
43 #endif
45 #include "Trace.h"
46 #include "Device.h"
47 #include "DeviceSettings.h"
49 using namespace avr;
51 #define AVR_SIM_VERSION "0.1"
53 enum ProgramType {
54 #ifdef HAVE_LIBBFD
55 PROG_BFD,
56 #endif
57 PROG_HEX,
58 PROG_NONE
61 ProgramType defaultProgramType =
62 #ifdef HAVE_LIBBFD
63 PROG_BFD; // Default Bfd
64 #else
65 PROG_HEX; // Default Hex
66 #endif
68 static void list_supported_devices() {
69 unsigned int lineLength = 80;
72 const char *p = getenv("COLUMNS");
73 if( (p != 0) && (*p != '\0') ) {
74 errno = 0;
75 unsigned long int tmp_ulong = strtoul(p, NULL, 10);
77 if( errno == 0 )
78 lineLength = tmp_ulong;
82 #ifdef TIOCGWINSZ
84 struct winsize ws;
86 if( (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1)
87 && (0 < ws.ws_col) && (ws.ws_col == (size_t) ws.ws_col) )
88 lineLength = ws.ws_col;
90 #endif
92 DeviceSettings::listAll(lineLength);
95 static void print_usage() {
96 std::cout << "AVR-Simulator"<< std::endl
97 << "-u run with user interface for external pin handling at port 7777\n"
98 << "-f --file <name> load file <name> for simulation in simulated target\n"
99 #ifdef HAVE_LIBBFD
100 << "-b --bfd-file specified filename is a bfd file (elf,coff)\n"
101 #endif
102 << "-x --hex-file specified filename is a hex file\n"
103 << "-d --device <device name> simulate <device name>\n"
104 << "-a --analyzer <name> add analyzer <name> (scripts are added using script:<script>)\n"
105 << "-s --scriptconfig <filename> config file for scripts\n"
106 << "-g --gdbserver running as gdb-server\n"
107 << "-p <port> change <port> for gdb server to port\n"
108 << "-t --trace <file name> enable trace outputs into <file name>\n"
109 << "-l --listtrace <file name> list trace outputs from <file name>\n"
110 << "-F --cpufrequence set the cpu frequence to <Hz>\n"
111 << "-c --clockticks set the number of clocks ticks to execute\n"
112 << "-v --verbose output some hints to console\n"
113 << "-h --help outputs this\n"
114 << std::endl;
116 std::cout << "Supported devices:"<< std::endl;
117 list_supported_devices();
118 std::cout << std::endl;
120 #ifdef HAVE_LIBBFD
121 std::cout << "Bfd file loading is enabled" << std::endl;
122 #endif
123 #if defined(HAVE_LUA) && defined(ENABLE_SCRIPTING)
124 std::cout << "Lua scripting is enabled" << std::endl;
125 #endif
127 exit(0);
130 static sim::SimulationClock simclock;
132 #ifdef _POSIX_SOURCE
133 static void signal_handler(int /*sig*/) {
134 simclock.finish();
137 static void enable_signal_handler(int sig = SIGINT) {
138 struct sigaction action;
139 action.sa_flags = 0;
140 action.sa_handler = signal_handler;
141 sigemptyset( &action.sa_mask );
143 sigaction( sig, &action, 0 );
145 #endif
147 #ifdef ENABLE_SCRIPTING
148 struct IsScript {
149 bool operator ()(const char *str) {
150 const char *scriptPrefix = "script:";
151 return strncmp( str, scriptPrefix, strlen(scriptPrefix) ) == 0;
155 static bool HaveScripts(const std::list<const char *> & analyzers) {
156 return ( std::find_if(analyzers.begin(), analyzers.end(), IsScript()) != analyzers.end() );
158 #endif
160 static void addAnalyzers(Device & dev, const std::list<const char *> & names) {
161 std::list<const char *>::const_iterator it;
162 for(it = names.begin(); it != names.end(); ++it)
163 dev.addAnalyzer( *it );
166 int main(int argc, char *argv[]) {
167 const char *devicename = "atmega162";
168 const char *filename = 0;
169 const char *listtrace = 0;
170 const char *tracefile = 0;
171 unsigned long long fcpu = 0;
172 bool gdbserver = false;
173 int gdbserver_port = 1234;
174 sim::ClockOffset clockTicks = 0;
175 ProgramType programType = PROG_NONE;
177 std::list<const char *> analyzers;
178 const char *scriptconfig = 0;
180 static struct option long_options[] = {
181 { "file", 1, 0, 'f' },
182 #ifdef HAVE_LIBBFD
183 { "bfd-file", 0, 0, 'b' },
184 #endif
185 { "hex-file", 0, 0, 'x' },
186 { "device", 1, 0, 'd' },
187 { "analyzer", 1, 0, 'a' },
188 { "scriptconfig", 1, 0, 's' },
189 { "gdb", 0, 0, 'g' },
190 { "gdbserver", 0, 0, 'g' },
191 { "gdbport", 1, 0, 'p' },
192 { "trace", 1, 0, 't' },
193 { "listtrace", 1, 0, 'l' },
194 { "version", 0, 0, 'V' },
195 { "cpufrequency", 1, 0, 'F' },
196 { "clockticks", 1, 0, 'c' },
197 { "verbose", 0, 0, 'v' },
198 { "help", 0, 0, 'h' },
199 { 0, 0, 0, 0 }
202 int c;
203 while ( (c = getopt_long (argc, argv, "vd:F:f:xba:s:gp:t:l:c:Vh",
204 long_options, 0)) != -1) {
206 switch (c ) {
207 case 'v':
208 info.increaseVerbosity();
209 break;
211 case 'd':
212 devicename = optarg;
213 info(INFO) << "Device to simulate "
214 << devicename << std::endl;
215 break;
217 case 'F':
218 fcpu = strtoll(optarg, NULL, 10);
219 info(INFO) << "Running with CPU frequency: "<< fcpu
220 << std::endl;
221 break;
223 case 'f':
224 filename = optarg;
225 info(INFO) << "File to load "<< filename << std::endl;
226 break;
228 case 'x':
229 if( programType != PROG_NONE ) {
230 std::cerr << "Multiple file types specified!" << std::endl;
231 exit(1);
234 programType = PROG_HEX;
235 info(INFO) << "Program file type is hex" << std::endl;
236 break;
238 #ifdef HAVE_LIBBFD
239 case 'b':
240 if( programType != PROG_NONE ) {
241 std::cerr << "Multiple file types specified!" << std::endl;
242 exit(1);
245 programType = PROG_BFD;
246 info(INFO) << "Program file type is bfd" << std::endl;
247 break;
248 #endif
250 case 'a':
251 analyzers.push_back( optarg );
252 info(INFO) << "Adding analyzer "<< optarg << std::endl;
253 break;
255 case 's':
256 scriptconfig = optarg;
257 info(INFO) << "Using configfile "<< scriptconfig << std::endl;
258 break;
260 case 'g':
261 gdbserver = true;
262 info(INFO) << "Running as gdb-server"<< std::endl;
263 break;
265 case 'p':
266 gdbserver_port = atoi(optarg);
267 info(INFO) << "Running gdb-server on port: "
268 << gdbserver_port << std::endl;
269 break;
271 case 't':
272 tracefile = optarg;
273 info(INFO) << "Running in Trace Mode"<< std::endl;
274 break;
276 case 'l':
277 listtrace = optarg;
278 info(INFO) << "Listing Trace"<< std::endl;
279 break;
281 case 'c':
282 clockTicks = strtoll(optarg, NULL, 10);
283 info(INFO) << "Ending executing after "<< clockTicks
284 << " clock ticks" << std::endl;
285 break;
287 case 'V': {
288 std::cout << "Simulavr++ "<< AVR_SIM_VERSION << std::endl;
289 std::cout
290 << "See documentation for copyright and distribution terms"
291 << std::endl;
292 std::cout << std::endl;
293 exit(0);
295 break;
297 default:
298 print_usage();
302 #ifdef ENABLE_SCRIPTING
303 ScriptEngine *vm = 0;
304 if( HaveScripts(analyzers) /*|| scripted peripherals */ )
305 vm = new ScriptEngine();
306 #endif
308 if( programType == PROG_NONE )
309 programType = defaultProgramType;
311 Program *program = 0;
312 if( programType == PROG_HEX )
313 program = new HexProgram();
314 #ifdef HAVE_LIBBFD
315 else if( programType == PROG_BFD )
316 program = new BfdProgram();
317 #endif
319 int ret = EXIT_SUCCESS;
320 try {
321 //SimulationClock simclock; this is global now for signal_handlers
322 Device dev( simclock, devicename );
324 #ifdef _POSIX_SOURCE
325 if( ! gdbserver )
326 enable_signal_handler(SIGINT);
327 #endif
329 #ifdef ENABLE_SCRIPTING
330 if( vm != 0 )
331 vm->setProgram( *program );
332 #endif
334 if( filename != 0 ) {
335 program->load( filename );
336 dev.load( *program );
339 if( tracefile != 0 )
340 dev.trace( tracefile );
342 if( clockTicks != 0 )
343 simclock.setMaxTicks( clockTicks );
345 if( fcpu != 0 )
346 dev.setClockFrequency( fcpu );
348 if( analyzers.size() != 0 )
349 addAnalyzers( dev, analyzers );
351 if( scriptconfig != 0 ) {
352 #ifdef ENABLE_SCRIPTING
353 if( vm != 0 ) {
354 vm->loadConfig( scriptconfig );
355 } else
356 std::cerr << "Warning: scriptconfig specified but no VM" << std::endl;
357 #else
358 std::cerr << "Warning: scriptconfig specified but scripting disabled" << std::endl;
359 #endif
363 if( listtrace != 0 ) {
364 Trace tracer;
365 tracer.list( listtrace, std::cout, dev);
366 } else if( gdbserver ) {
367 GdbServer gdb( simclock, gdbserver_port );
368 gdb.add( &dev );
369 gdb.exec();
370 } else {
371 simclock.exec();
374 } catch( util::Exception & ex ) {
375 std::cerr << ex.message() << std::endl;
376 ex.printStackTrace( std::cerr );
377 ret = EXIT_FAILURE;
378 } catch( std::exception & ex ) {
379 std::cerr << ex.what() << std::endl;
380 ret = EXIT_FAILURE;
381 } catch( ... ) {
382 std::cerr << "Caught unknown exception" << std::endl;
383 ret = EXIT_FAILURE;
386 if( program != 0 )
387 delete program;
389 #ifdef ENABLE_SCRIPTING
390 if( vm != 0 )
391 delete vm;
392 #endif
394 info(INFO) << "Simulation ran for " << simclock.ticks()
395 << " clock ticks" << std::endl;
397 return ret;