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/>.
31 # include <sys/ioctl.h>
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"
47 #include "DeviceSettings.h"
51 #define AVR_SIM_VERSION "0.1"
61 ProgramType defaultProgramType
=
63 PROG_BFD
; // Default Bfd
65 PROG_HEX
; // Default Hex
68 static void list_supported_devices() {
69 unsigned int lineLength
= 80;
72 const char *p
= getenv("COLUMNS");
73 if( (p
!= 0) && (*p
!= '\0') ) {
75 unsigned long int tmp_ulong
= strtoul(p
, NULL
, 10);
78 lineLength
= tmp_ulong
;
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
;
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"
100 << "-b --bfd-file specified filename is a bfd file (elf,coff)\n"
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"
116 std::cout
<< "Supported devices:"<< std::endl
;
117 list_supported_devices();
118 std::cout
<< std::endl
;
121 std::cout
<< "Bfd file loading is enabled" << std::endl
;
123 #if defined(HAVE_LUA) && defined(ENABLE_SCRIPTING)
124 std::cout
<< "Lua scripting is enabled" << std::endl
;
130 static sim::SimulationClock simclock
;
133 static void signal_handler(int /*sig*/) {
137 static void enable_signal_handler(int sig
= SIGINT
) {
138 struct sigaction action
;
140 action
.sa_handler
= signal_handler
;
141 sigemptyset( &action
.sa_mask
);
143 sigaction( sig
, &action
, 0 );
147 #ifdef ENABLE_SCRIPTING
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() );
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' },
183 { "bfd-file", 0, 0, 'b' },
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' },
203 while ( (c
= getopt_long (argc
, argv
, "vd:F:f:xba:s:gp:t:l:c:Vh",
204 long_options
, 0)) != -1) {
208 info
.increaseVerbosity();
213 info(INFO
) << "Device to simulate "
214 << devicename
<< std::endl
;
218 fcpu
= strtoll(optarg
, NULL
, 10);
219 info(INFO
) << "Running with CPU frequency: "<< fcpu
225 info(INFO
) << "File to load "<< filename
<< std::endl
;
229 if( programType
!= PROG_NONE
) {
230 std::cerr
<< "Multiple file types specified!" << std::endl
;
234 programType
= PROG_HEX
;
235 info(INFO
) << "Program file type is hex" << std::endl
;
240 if( programType
!= PROG_NONE
) {
241 std::cerr
<< "Multiple file types specified!" << std::endl
;
245 programType
= PROG_BFD
;
246 info(INFO
) << "Program file type is bfd" << std::endl
;
251 analyzers
.push_back( optarg
);
252 info(INFO
) << "Adding analyzer "<< optarg
<< std::endl
;
256 scriptconfig
= optarg
;
257 info(INFO
) << "Using configfile "<< scriptconfig
<< std::endl
;
262 info(INFO
) << "Running as gdb-server"<< std::endl
;
266 gdbserver_port
= atoi(optarg
);
267 info(INFO
) << "Running gdb-server on port: "
268 << gdbserver_port
<< std::endl
;
273 info(INFO
) << "Running in Trace Mode"<< std::endl
;
278 info(INFO
) << "Listing Trace"<< std::endl
;
282 clockTicks
= strtoll(optarg
, NULL
, 10);
283 info(INFO
) << "Ending executing after "<< clockTicks
284 << " clock ticks" << std::endl
;
288 std::cout
<< "Simulavr++ "<< AVR_SIM_VERSION
<< std::endl
;
290 << "See documentation for copyright and distribution terms"
292 std::cout
<< std::endl
;
302 #ifdef ENABLE_SCRIPTING
303 ScriptEngine
*vm
= 0;
304 if( HaveScripts(analyzers
) /*|| scripted peripherals */ )
305 vm
= new ScriptEngine();
308 if( programType
== PROG_NONE
)
309 programType
= defaultProgramType
;
311 Program
*program
= 0;
312 if( programType
== PROG_HEX
)
313 program
= new HexProgram();
315 else if( programType
== PROG_BFD
)
316 program
= new BfdProgram();
319 int ret
= EXIT_SUCCESS
;
321 //SimulationClock simclock; this is global now for signal_handlers
322 Device
dev( simclock
, devicename
);
326 enable_signal_handler(SIGINT
);
329 #ifdef ENABLE_SCRIPTING
331 vm
->setProgram( *program
);
334 if( filename
!= 0 ) {
335 program
->load( filename
);
336 dev
.load( *program
);
340 dev
.trace( tracefile
);
342 if( clockTicks
!= 0 )
343 simclock
.setMaxTicks( clockTicks
);
346 dev
.setClockFrequency( fcpu
);
348 if( analyzers
.size() != 0 )
349 addAnalyzers( dev
, analyzers
);
351 if( scriptconfig
!= 0 ) {
352 #ifdef ENABLE_SCRIPTING
354 vm
->loadConfig( scriptconfig
);
356 std::cerr
<< "Warning: scriptconfig specified but no VM" << std::endl
;
358 std::cerr
<< "Warning: scriptconfig specified but scripting disabled" << std::endl
;
363 if( listtrace
!= 0 ) {
365 tracer
.list( listtrace
, std::cout
, dev
);
366 } else if( gdbserver
) {
367 GdbServer
gdb( simclock
, gdbserver_port
);
374 } catch( util::Exception
& ex
) {
375 std::cerr
<< ex
.message() << std::endl
;
376 ex
.printStackTrace( std::cerr
);
378 } catch( std::exception
& ex
) {
379 std::cerr
<< ex
.what() << std::endl
;
382 std::cerr
<< "Caught unknown exception" << std::endl
;
389 #ifdef ENABLE_SCRIPTING
394 info(INFO
) << "Simulation ran for " << simclock
.ticks()
395 << " clock ticks" << std::endl
;