2 * Copyright (c) 2003 Stephen Williams (steve@icarus.com)
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
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, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 #ident "$Id: stop.cc,v 1.16 2006/06/18 04:15:50 steve Exp $"
24 * This file provides a simple command line debugger for the vvp
25 * runtime. It is a means to interact with the user running the
32 # include "vpi_priv.h"
34 # include "schedule.h"
37 #ifdef HAVE_READLINE_READLINE_H
38 # include <readline/readline.h>
40 #ifdef HAVE_READLINE_HISTORY_H
41 # include <readline/history.h>
49 struct __vpiScope
*stop_current_scope
= 0;
52 static char* readline_stub(const char*prompt
)
56 if (prompt
&& prompt
[0]) {
57 fputs(prompt
, stdout
);
61 if (fgets(buf
, sizeof(buf
), stdin
)) {
62 char*nl
= buf
+ strlen(buf
);
63 while (nl
> buf
&& isspace(nl
[-1])) {
73 #define readline(x) readline_stub(x)
77 static bool interact_flag
= true;
79 static void cmd_call(unsigned argc
, char*argv
[])
81 struct __vpiHandle
**table
;
84 if (stop_current_scope
== 0) {
85 vpip_make_root_iterator(table
, ntable
);
88 table
= stop_current_scope
->intern
;
89 ntable
= stop_current_scope
->nintern
;
92 /* This is an array of vpiHandles, for passing to the created
94 unsigned vpi_argc
= argc
- 1;
95 vpiHandle
*vpi_argv
= (vpiHandle
*)calloc(vpi_argc
, sizeof(vpiHandle
));
96 vpiHandle
*vpi_free
= (vpiHandle
*)calloc(vpi_argc
, sizeof(vpiHandle
));
100 for (unsigned idx
= 0 ; idx
< vpi_argc
; idx
+= 1) {
101 vpiHandle handle
= 0;
102 bool add_to_free_list
= false;
104 /* Detect the special case that the argument is the
105 .(dot) string. This represents the handle for the
107 if (stop_current_scope
&& (strcmp(argv
[idx
+1], ".") == 0))
108 handle
= &stop_current_scope
->base
;
110 /* Is the argument a quoted string? */
111 if (handle
== 0 && argv
[idx
+1][0] == '"') {
112 char*tmp
= strdup(argv
[idx
+1]);
113 tmp
[strlen(tmp
)-1] = 0;
115 /* Create a temporary vpiStringConst to pass as a
116 handle. Make it temporary so that memory is
117 reclaimed after the call is completed. */
118 handle
= vpip_make_string_const(strdup(tmp
+1), false);
119 add_to_free_list
= true;
123 /* Is the argument a decimal constant? */
125 && strspn(argv
[idx
+1],"0123456789") == strlen(argv
[idx
+1])) {
126 handle
= vpip_make_dec_const(strtol(argv
[idx
+1],0,10));
127 add_to_free_list
= true;
130 /* Try to find the vpiHandle within this scope that has
131 the name in argv[idx+2]. Look in the current scope. */
133 for (unsigned tmp
= 0 ; (tmp
< ntable
)&& !handle
; tmp
+= 1) {
134 struct __vpiScope
*scope
;
137 switch (table
[tmp
]->vpi_type
->type_code
) {
144 scope
= (struct __vpiScope
*) table
[idx
];
145 if (strcmp(scope
->name
, argv
[idx
+1]) == 0)
152 name
= vpi_get_str(vpiName
,table
[tmp
]);
153 if (strcmp(argv
[idx
+1], name
) == 0)
160 printf("call error: I don't know how to"
161 " pass %s to %s\n", argv
[idx
+1], argv
[0]);
165 vpi_argv
[idx
] = handle
;
166 if (add_to_free_list
)
167 vpi_free
[idx
] = handle
;
173 /* If there are no errors so far, then make up a call to the
174 vpi task and execute that call. Free the call structure
177 vpiHandle call_handle
= vpip_build_vpi_call(argv
[0], 0, 0, 0,
179 if (call_handle
== 0)
182 vpip_execute_vpi_call(0, call_handle
);
183 vpi_free_object(call_handle
);
187 for (unsigned idx
= 0 ; idx
< vpi_argc
; idx
+= 1) {
189 vpi_free_object(vpi_free
[idx
]);
196 static void cmd_cont(unsigned, char*[])
198 interact_flag
= false;
201 static void cmd_finish(unsigned, char*[])
203 interact_flag
= false;
207 static void cmd_help(unsigned, char*[]);
209 static void cmd_list(unsigned, char*[])
211 struct __vpiHandle
**table
;
214 if (stop_current_scope
== 0) {
215 vpip_make_root_iterator(table
, ntable
);
218 table
= stop_current_scope
->intern
;
219 ntable
= stop_current_scope
->nintern
;
222 printf("%u items in this scope:\n", ntable
);
223 for (unsigned idx
= 0 ; idx
< ntable
; idx
+= 1) {
225 struct __vpiScope
*scope
;
226 struct __vpiSignal
*sig
;
228 switch (table
[idx
]->vpi_type
->type_code
) {
230 scope
= (struct __vpiScope
*) table
[idx
];
231 printf("module : %s\n", scope
->name
);
235 scope
= (struct __vpiScope
*) table
[idx
];
236 printf("task : %s\n", scope
->name
);
240 scope
= (struct __vpiScope
*) table
[idx
];
241 printf("function: %s\n", scope
->name
);
245 scope
= (struct __vpiScope
*) table
[idx
];
246 printf("block : %s\n", scope
->name
);
250 scope
= (struct __vpiScope
*) table
[idx
];
251 printf("fork : %s\n", scope
->name
);
255 printf("param : %s\n", vpi_get_str(vpiName
, table
[idx
]));
259 sig
= (struct __vpiSignal
*) table
[idx
];
260 if ((sig
->msb
== 0) && (sig
->lsb
== 0))
261 printf("reg : %s%s\n", sig
->name
,
262 sig
->signed_flag
? "signed " : "");
264 printf("reg : %s%s[%d:%d]\n", sig
->name
,
265 sig
->signed_flag
? "signed " : "",
270 sig
= (struct __vpiSignal
*) table
[idx
];
271 if ((sig
->msb
== 0) && (sig
->lsb
== 0))
272 printf("net : %s%s\n", sig
->name
,
273 sig
->signed_flag
? "signed " : "");
275 printf("net : %s%s[%d:%d]\n", sig
->name
,
276 sig
->signed_flag
? "signed " : "",
281 printf("%8d: <vpi handle>\n",
282 table
[idx
]->vpi_type
->type_code
);
289 static void cmd_load(unsigned argc
, char*argv
[])
293 for (idx
= 1 ; idx
< argc
; idx
+= 1) {
294 printf("Loading module %s...\n", argv
[idx
]);
295 vpip_load_module(argv
[idx
]);
299 static void cmd_pop(unsigned, char*[])
301 if (stop_current_scope
!= 0)
302 stop_current_scope
= stop_current_scope
->scope
;
305 static void cmd_push(unsigned argc
, char* argv
[])
308 for (unsigned idx
= 1 ; idx
< argc
; idx
+= 1) {
309 struct __vpiHandle
**table
;
312 struct __vpiScope
*child
= 0;
314 if (stop_current_scope
) {
315 table
= stop_current_scope
->intern
;
316 ntable
= stop_current_scope
->nintern
;
318 vpip_make_root_iterator(table
, ntable
);
323 for (tmp
= 0 ; tmp
< ntable
; tmp
+= 1) {
324 if (table
[tmp
]->vpi_type
->type_code
!= vpiModule
)
327 struct __vpiScope
*cp
= (struct __vpiScope
*) table
[tmp
];
329 /* This is a scope, and the name matches, then
330 report that I found the child. */
331 if (strcmp(cp
->name
, argv
[idx
]) == 0) {
338 printf("Scope %s not found.\n", argv
[idx
]);
342 stop_current_scope
= child
;
346 static void cmd_time(unsigned, char*[])
348 unsigned long ticks
= schedule_simtime();
349 printf("%lu ticks\n", ticks
);
352 static void cmd_where(unsigned, char*[])
354 struct __vpiScope
*cur
= stop_current_scope
;
357 switch (cur
->base
.vpi_type
->type_code
) {
359 printf("module %s\n",
363 printf("scope (%d) %s;\n",
364 cur
->base
.vpi_type
->type_code
,
373 static void cmd_unknown(unsigned, char*argv
[])
375 printf("Unknown command: %s\n", argv
[0]);
376 printf("Try the help command to get a summary\n"
377 "of available commands.\n");
382 void (*proc
)(unsigned argc
, char*argv
[]);
386 "Synonym for push."},
388 "Resume (continue) the simulation"},
389 { "finish", &cmd_finish
,
390 "Finish the simulation."},
394 "List items in the current scope."},
396 "Load a VPI module, a la vvp -m."},
398 "Shorthand for \"list\"."},
400 "Pop one scope from the scope stack."},
402 "Descend into the named scope."},
404 "Print the current simulation time."},
405 { "where", &cmd_where
,
406 "Show current scope, and scope hierarchy stack."},
407 { 0, &cmd_unknown
, 0}
410 static void cmd_help(unsigned argc
, char*argv
[])
412 printf("Commands can be from the following table of base commands,\n"
413 "or can be invocations of system tasks/functions.\n\n");
414 for (unsigned idx
= 0 ; cmd_table
[idx
].name
!= 0 ; idx
+= 1) {
415 printf("%-8s - %s\n", cmd_table
[idx
].name
, cmd_table
[idx
].summary
);
418 printf("\nIf the command name starts with a '$' character, it\n"
419 "is taken to be the name of a system task, and a call is\n"
420 "built up and executed.\n");
424 static void invoke_command(char*txt
)
427 char**argv
= new char*[strlen(txt
)/2];
429 /* Chop the line into words. */
430 for (char*cp
= txt
+strspn(txt
, " ")
431 ; *cp
; cp
+= strspn(cp
, " ")) {
435 char*tmp
= strchr(cp
+1, '"');
437 printf("Missing close-quote: %s\n", cp
);
445 cp
+= strcspn(cp
, " ");
454 /* Look up the command, using argv[0] as the key. */
457 if (argv
[0][0] == '$') {
458 cmd_call(argc
, argv
);
462 for (idx
= 0 ; cmd_table
[idx
].name
; idx
+= 1)
463 if (strcmp(cmd_table
[idx
].name
, argv
[0]) == 0)
466 cmd_table
[idx
].proc (argc
, argv
);
474 void stop_handler(int rc
)
476 vpi_mcd_printf(1,"** VVP Stop(%d) **\n", rc
);
477 vpi_mcd_printf(1,"** Current simulation time is %" TIME_FMT
"u ticks.\n",
480 interact_flag
= true;
481 while (interact_flag
) {
482 char*input
= readline("> ");
487 /* Advance to the first input character. */
489 while (*first
&& isspace(*first
))
493 #ifdef HAVE_READLINE_HISTORY_H
496 invoke_command(first
);
502 vpi_mcd_printf(1,"** Continue **\n");
508 * Revision 1.16 2006/06/18 04:15:50 steve
509 * Add support for system functions in continuous assignments.
511 * Revision 1.15 2005/11/25 18:35:38 steve
512 * stop/continue messages go through MCD for logging.
514 * Revision 1.14 2005/09/20 18:34:02 steve
515 * Clean up compiler warnings.
517 * Revision 1.13 2005/01/29 06:29:17 steve
518 * Support interactive mode even without readline.
520 * Revision 1.12 2004/10/04 01:10:59 steve
521 * Clean up spurious trailing white space.
523 * Revision 1.11 2004/02/21 00:44:34 steve
524 * Add load command to interactive stop.
525 * Support decimal constants passed interactive to system tasks.
527 * Revision 1.10 2003/11/07 05:58:02 steve
528 * Fix conditional compilation of readline history.