Bug fix: check if vm exists
[avr-sim.git] / avr-sim.cpp
blob29f4d74af7584e4391ed02a62a00409e08779943
1 #include <iostream>
2 #include <getopt.h>
4 #ifdef LINUX
5 # include <signal.h>
6 # include <setjmp.h>
7 #endif
9 #include "SimulationClock.h"
10 #include "GdbServer.h"
12 #include "BfdProgram.h"
13 #include "ScriptEngine.h"
14 #include "Trace.h"
15 #include "Device.h"
16 #include "DeviceSettings.h"
18 using namespace avr;
20 #define AVR_SIM_VERSION "0.1"
22 static void list_supported_devices() {
23 DeviceSettings::listAll();
26 static void print_usage() {
27 std::cout << "AVR-Simulator"<< std::endl
28 << "-u run with user interface for external pin handling at port 7777\n"
29 << "-f --file <name> load elf-file <name> for simulation in simulated target\n"
30 << "-d --device <device name> simulate <device name>\n "
31 << "-a --analyzer <name> add analyzer <name> (scripts are added using script:<script>)"
32 << "-s --scriptconfig <filename> config file for scripts"
33 << "-g --gdbserver running as gdb-server\n"
34 << "-p <port> change <port> for gdb server to port\n"
35 << "-t --trace <file name> enable trace outputs into <file name>\n"
36 << "-l --listtrace <file name> list trace outputs from <file name>\n"
37 << "-F --cpufrequence set the cpu frequence to <Hz>\n"
38 << "-c --clockticks set the number of clocks ticks to execute\n"
39 << "-v --verbose output some hints to console\n"
40 << "-h --help outputs this\n"
41 << std::endl;
43 std::cout << "Supported devices:"<< std::endl;
44 list_supported_devices();
45 std::cout << std::endl;
47 exit(0);
50 static SimulationClock simclock;
52 #ifdef LINUX
53 static void signal_handler(int sig) {
54 simclock.finish();
57 static void enable_signal_handler(int sig = SIGINT) {
58 struct sigaction action;
59 action.sa_flags = 0;
60 action.sa_handler = signal_handler;
61 sigemptyset( &action.sa_mask );
63 sigaction( sig, &action, 0 );
65 #endif
67 struct IsScript {
68 bool operator ()(const char *str) {
69 const char *scriptPrefix = "script:";
70 return strncmp( str, scriptPrefix, strlen(scriptPrefix) ) == 0;
74 static bool HaveScripts(const std::list<const char *> & analyzers) {
75 return ( std::find_if(analyzers.begin(), analyzers.end(), IsScript()) != analyzers.end() );
78 int main(int argc, char *argv[]) {
79 int verbose = 0;
80 const char *devicename = "atmega8";
81 const char *filename = 0;
82 const char *listtrace = 0;
83 unsigned long long fcpu = 0;
84 bool gdbserver = false;
85 int gdbserver_port = 1234;
86 ClockOffset clockTicks = 0;
88 std::list<const char *> analyzers;
89 const char *scriptconfig = 0;
91 static struct option long_options[] = {
92 { "file", 1, 0, 'f' },
93 { "device", 1, 0, 'd' },
94 { "analyzer", 1, 0, 'a' },
95 { "scriptconfig", 1, 0, 's' },
96 { "gdb", 0, 0, 'g' },
97 { "gdbserver", 0, 0, 's' },
98 { "gdbport", 1, 0, 'p' },
99 { "trace", 1, 0, 't' },
100 { "listtrace", 1, 0, 'l' },
101 { "version", 0, 0, 'V' },
102 { "cpufrequency", 1, 0, 'F' },
103 { "verbose", 0, 0, 'v' },
104 { "help", 0, 0, 'h' },
105 { 0, 0, 0, 0 }
108 int c;
109 while ( (c = getopt_long (argc, argv, "vd:F:f:a:s:gp:t:l:c:Vh",
110 long_options, 0)) != -1) {
112 switch (c ) {
113 case 'v':
114 verbose++;
115 break;
117 case 'd':
118 devicename = optarg;
119 if( verbose > 1 )
120 std::cout << "Device to simulate "<< devicename
121 << std::endl;
122 break;
124 case 'F':
125 fcpu = strtoll(optarg, NULL, 10);
126 if (verbose > 1)
127 std::cout << "Running with CPU frequency: "<< fcpu
128 << std::endl;
129 break;
131 case 'f':
132 filename = optarg;
133 if( verbose > 1 )
134 std::cout << "File to load "<< filename << std::endl;
135 break;
137 case 'a':
138 analyzers.push_back( optarg );
139 if( verbose > 1 )
140 std::cout << "Adding analyzer "<< optarg << std::endl;
141 break;
143 case 's':
144 scriptconfig = optarg;
145 if( verbose > 1 )
146 std::cout << "Using configfile "<< scriptconfig << std::endl;
147 break;
149 case 'g':
150 gdbserver = true;
151 if( verbose > 1 )
152 std::cout << "Running as gdb-server"<< std::endl;
153 break;
155 case 'p':
156 gdbserver_port = atoi(optarg);
157 if (verbose > 1)
158 std::cout << "Running gdb-server on port: "
159 << gdbserver_port << std::endl;
160 break;
162 case 't':
163 Trace::instance().enableLogging( optarg );
164 if( verbose > 1 )
165 std::cout << "Running in Trace Mode"<< std::endl;
166 break;
168 case 'l':
169 listtrace = optarg;
170 if( verbose > 1 )
171 std::cout << "Listing Trace"<< std::endl;
172 break;
174 case 'c':
175 clockTicks = strtoll(optarg, NULL, 10);
176 if (verbose > 1)
177 std::cout << "Ending executing after "<< clockTicks
178 << " clock ticks" << std::endl;
179 break;
181 case 'V': {
182 std::cout << "Simulavr++ "<< AVR_SIM_VERSION << std::endl;
183 std::cout
184 << "See documentation for copyright and distribution terms"
185 << std::endl;
186 std::cout << std::endl;
187 exit(0);
189 break;
191 default:
192 print_usage();
196 ScriptEngine *vm = 0;
197 if( HaveScripts(analyzers) /*|| scripted peripherals */ )
198 vm = new ScriptEngine();
200 int ret = EXIT_SUCCESS;
201 try {
202 //SimulationClock simclock; this is global now for signal_handlers
203 Device dev( simclock, devicename );
205 #ifdef LINUX
206 enable_signal_handler(SIGINT);
207 #endif
209 #ifdef HAVE_BFD
210 BfdProgram program;
211 #else
212 Program program;
213 #endif
215 if( vm != 0 )
216 vm->setProgram( program );
218 if( filename != 0 ) {
219 program.load( filename );
220 dev.load( program );
223 if( clockTicks != 0 )
224 simclock.setMaxTicks( clockTicks );
226 if( clockTicks != 0 )
227 simclock.setMaxTicks( clockTicks );
229 if( fcpu != 0 )
230 dev.setClockFrequency( fcpu );
232 if( analyzers.size() != 0 )
233 dev.addAnalyzers( vm, analyzers );
235 if( scriptconfig != 0 ) {
236 if( vm == 0 )
237 std::cerr << "Warning: scriptconfig specified but no VM" << std::endl;
238 else
239 vm->loadConfig( scriptconfig );
242 if( listtrace != 0 ) {
243 Trace::instance().list( listtrace, std::cout, dev );
244 } else if( gdbserver ) {
245 GdbServer gdb( simclock, gdbserver_port );
246 gdb.add( &dev );
247 gdb.exec();
248 } else {
249 simclock.exec();
252 } catch( util::Exception & ex ) {
253 std::cerr << ex.message() << std::endl;
254 ex.printStackTrace( std::cerr );
255 ret = EXIT_FAILURE;
256 } catch( std::exception & ex ) {
257 std::cerr << ex.what() << std::endl;
258 ret = EXIT_FAILURE;
261 if( vm != 0 )
262 delete vm;
264 if( verbose >= 1 )
265 std::cout << "Simulation ran for " << simclock.ticks()
266 << " clock ticks" << std::endl;
268 return ret;