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 { "verbose", 0, 0, 'v' },
197 { "help", 0, 0, 'h' },
202 while ( (c
= getopt_long (argc
, argv
, "vd:F:f:xba:s:gp:t:l:c:Vh",
203 long_options
, 0)) != -1) {
207 info
.increaseVerbosity();
212 info(INFO
) << "Device to simulate "
213 << devicename
<< std::endl
;
217 fcpu
= strtoll(optarg
, NULL
, 10);
218 info(INFO
) << "Running with CPU frequency: "<< fcpu
224 info(INFO
) << "File to load "<< filename
<< std::endl
;
228 if( programType
!= PROG_NONE
) {
229 std::cerr
<< "Multiple file types specified!" << std::endl
;
233 programType
= PROG_HEX
;
234 info(INFO
) << "Program file type is hex" << std::endl
;
239 if( programType
!= PROG_NONE
) {
240 std::cerr
<< "Multiple file types specified!" << std::endl
;
244 programType
= PROG_BFD
;
245 info(INFO
) << "Program file type is bfd" << std::endl
;
250 analyzers
.push_back( optarg
);
251 info(INFO
) << "Adding analyzer "<< optarg
<< std::endl
;
255 scriptconfig
= optarg
;
256 info(INFO
) << "Using configfile "<< scriptconfig
<< std::endl
;
261 info(INFO
) << "Running as gdb-server"<< std::endl
;
265 gdbserver_port
= atoi(optarg
);
266 info(INFO
) << "Running gdb-server on port: "
267 << gdbserver_port
<< std::endl
;
272 info(INFO
) << "Running in Trace Mode"<< std::endl
;
277 info(INFO
) << "Listing Trace"<< std::endl
;
281 clockTicks
= strtoll(optarg
, NULL
, 10);
282 info(INFO
) << "Ending executing after "<< clockTicks
283 << " clock ticks" << std::endl
;
287 std::cout
<< "Simulavr++ "<< AVR_SIM_VERSION
<< std::endl
;
289 << "See documentation for copyright and distribution terms"
291 std::cout
<< std::endl
;
301 #ifdef ENABLE_SCRIPTING
302 ScriptEngine
*vm
= 0;
303 if( HaveScripts(analyzers
) /*|| scripted peripherals */ )
304 vm
= new ScriptEngine();
307 if( programType
== PROG_NONE
)
308 programType
= defaultProgramType
;
310 Program
*program
= 0;
311 if( programType
== PROG_HEX
)
312 program
= new HexProgram();
314 else if( programType
== PROG_BFD
)
315 program
= new BfdProgram();
318 int ret
= EXIT_SUCCESS
;
320 //SimulationClock simclock; this is global now for signal_handlers
321 Device
dev( simclock
, devicename
);
325 enable_signal_handler(SIGINT
);
328 #ifdef ENABLE_SCRIPTING
330 vm
->setProgram( *program
);
333 if( filename
!= 0 ) {
334 program
->load( filename
);
335 dev
.load( *program
);
339 dev
.trace( tracefile
);
341 if( clockTicks
!= 0 )
342 simclock
.setMaxTicks( clockTicks
);
345 dev
.setClockFrequency( fcpu
);
347 if( analyzers
.size() != 0 )
348 addAnalyzers( dev
, analyzers
);
350 if( scriptconfig
!= 0 ) {
351 #ifdef ENABLE_SCRIPTING
353 vm
->loadConfig( scriptconfig
);
355 std::cerr
<< "Warning: scriptconfig specified but no VM" << std::endl
;
357 std::cerr
<< "Warning: scriptconfig specified but scripting disabled" << std::endl
;
362 if( listtrace
!= 0 ) {
364 tracer
.list( listtrace
, std::cout
, dev
);
365 } else if( gdbserver
) {
366 GdbServer
gdb( simclock
, gdbserver_port
);
373 } catch( util::Exception
& ex
) {
374 std::cerr
<< ex
.message() << std::endl
;
375 ex
.printStackTrace( std::cerr
);
377 } catch( std::exception
& ex
) {
378 std::cerr
<< ex
.what() << std::endl
;
381 std::cerr
<< "Caught unknown exception" << std::endl
;
388 #ifdef ENABLE_SCRIPTING
393 info(INFO
) << "Simulation ran for " << simclock
.ticks()
394 << " clock ticks" << std::endl
;