Quit Modelsim from command line on error - tcl

I am using a .do file which is used by GUI and by .tcl in command line (vsim -c) for simulating in Modelsim 10.3c
exec vsim -c -do DoFile.do
What I need is:
If an error happens, modelsim should be quit and return to the .tcl. Otherwise it should simulate the project.
If I put the line onerror { quit -f } in my .do file the GUI is quit at the first error. So, this is not comfortable.
I didn't manage to use onerror (warning: onerror command for use within macro) or $error (unknown variable) inside tcl

I would need further information about your DO and Tcl script but you can use try-catch on vcom (for compiling VHDL) or vlog (for compiling Verilog/SystemVerilog).
Here a short a example how to use it:
# set variable for compile error
set comperror ""
# compile files
catch "vcom -quiet -93 -work work name.vhd" comperror
catch "vcom -quiet -93 -work work name2.vhd" comperror
# ... and futher files..
if [expr {${comperror}!=""}] then {
# quit modelsim or do anything else
} else {
# do simulation or execute further commands
}
You can compile ALL files and if a error occurs you can quit it. If it's successful you can run your simulation.

I have found a work around. I create a file in the .tcl and put the following lines into the .do scripts:
if [file exists ../Command_Line_Enable.txt] {
onerror { quit -f }
}
So, if that file is not generated the GUI will not exit.

Related

Tclsh can support user only type partial tcl command, but Tcl script not support

We implemented some tcl commands, if we type only part of the command at Tcl> prompt in tcl shell interactive mode, the tcl shell can recognize the command. But if we put the same partial command in tcl script file, then source the script from tcl shell, unknown command will be reported. And the whole command in tcl sript can be recognized.
How can we make source tcl script behavior same as shell interactive mode? We expect when source tcl script, partial command can also be reconginzed.
Please see following sample.
Partial command can be recognized in shell interactive mode.
Tcl> my_prove
Info: proving started
Info: ....
Info: ....
Tcl> my_pro
Info: proving started
Info: ....
Info: ....
Partial command cannot be recognized when source run.tcl script.
a) run.tcl
setup_design
my_prove
my_pro
b) source the script run.tcl
Tcl> source run.tcl
$inside source$$> setup_desgin
Design setup...
Done
$inside source$$> my_prove
Info: proving started
Info: ....
Info: ....
$inside source$$> ::unknown my_pro
invalid command name "my_pro"
Tcl implements partial command name expansion in the unknown procedure (along with numerous other things) and only turns it on in interactive mode. It's generally strongly recommended to use full command names in your scripts; that's far more likely to be reliable.
If you want to enable it, which I don't think you should, do this (this version uses tailcall so needs at least Tcl 8.6):
rename unknown _standard_unknown
proc unknown args {
set cmd [lindex $args 0]
set matches [uplevel 1 [list info commands $cmd*]]
# If there is a unique match, use it
if {[llength $matches] == 1} {
lset args 0 [lindex $matches 0]
tailcall {*}$args
}
tailcall _standard_unknown {*}$args
}
In theory, you can also set the tcl_interactive global to any true value (e.g., 1) to enable the expansion. However, there may be other unwanted behaviours as well enabled by doing that; Tcl makes no guarantees on that front.

When source a Tcl script in Tcl shell, how can I let Tcl print every Tcl command inside the script to the shell?

Running our software will start a Tcl shell in Terminal, then we can execute a series of tcl commands in this Tcl shell by souce a tcl script file. But the tcl commands inside the tcl script file will not be printed on the Tcl shell, so, we cannot see what commands have been executed by source the tcl script.
So my question is, is there any configuration of Tcl can print out the commands in the script when the script been source.
Following is an sample tcl script
# sample.tcl, composed of 3 tcl commands:
read designfile
analyze
write output
If we interactively execute the 3 tcl commands in the Tcl shell, the result will be look as:
Tcl> read designfile
Info: reading designfile
Info: size: 128k
...
...
Tcl> analyze
Info: analyzing designfile
Info: 108 modules need to be analyzed
...
...
Tcl> write output
Info: analyzed data been written into file "output"
If we source this tcl sript in Tcl shell, the result will be:
Tcl> source sample.tcl
Info: reading designfile
Info: size: 128k
...
...
Info: analyzing designfile
Info: 108 modules need to be analyzed
...
...
Info: analyzed data been written into file "output"
We expect the the result will be as below when we source the script.
Tcl> source sample.tcl
> read designfile
Info: reading designfile
Info: size: 128k
...
...
> analyze
Info: analyzing designfile
Info: 108 modules need to be analyzed
...
...
> write output
Info: analyzed data been written into file "output"
Thanks Donal very much!
Based on his suggestion, finally I got the trace command as below to satisfy my requirment.
proc print {args} {
set cmd [lindex $args 0]
puts stdout "$> $cmd"
}
trace add execution source enterstep print
That's a job for an execution trace. These can be applied to all sorts of Tcl commands, not just procedures.
trace add execution source enterstep {apply {{cmd op} {
# Trim multiline commands down a bit; I find this helps me at least!
regsub {\n.*} $cmd ... cmd
# Print what's being run
puts "EXECUTE: $cmd"
}}}
source thefile.tcl
Note that this may print a lot more than you expect! Here's a more sophisticated version that prints only the outermost level of execution.
# Called before [source] starts running
trace add execution source enter {apply {args {
global SOURCE_LEVEL
if {![info exists SOURCE_LEVEL]} {
set SOURCE_LEVEL [info level]
}
}}}
# Called after [source] finishes running
trace add execution source leave {apply {args {
global SOURCE_LEVEL
if {$SOURCE_LEVEL == [info level]} {
unset SOURCE_LEVEL
}
}}}
# Called for every command called while [source] is running
trace add execution source enterstep {apply {{cmd op} {
global SOURCE_LEVEL
if {$SOURCE_LEVEL == [info level]} {
regsub {\n.*} $cmd "..." cmd
puts "EXECUTE: $cmd"
}
}}}

eval/exec can not be executed in TCL script

I am using TCL to control a traffic generator. When the traffic received, I want to use shark command to convert the .pcap file to a .txt file, and then I can do some other job.
But when run the exec in the program the following info print out:
while executing
"exec tshark -Vxr /var/tmp/PCRF/create_req.pcap"
("eval" body line 1)
invoked from within
"eval exec {tshark -Vxr /var/tmp/PCRF/create_req.pcap}"
(file "./tcp_test.tcl" line 7)
The following is the TCL script:
# Radius accounting request start packets
# Version 1.0
# Date 2014/4/16 16:38
puts "\n Begin to decode the capture file\n"
#source /var/tmp/PCRF/convert_pcap.tcl
eval exec {tshark -Vxr /var/tmp/PCRF/create_req.pcap}
puts "\n end of the file decode and the result is rrr\n"
Tcl's exec can throw an error for two reasons. It does so if either:
The subprocess returns a non-zero exit code.
The subprocess writes to standard error.
The first one can be annoying, but it is genuinely how programs are supposed to indicate real errors. It can be a problem if the program also uses it in other ways (e.g., to say that nothing was found, like grep does) but that. However, in this case you get the error message child process exited abnormally so it is easy to at least figure out what happened.
More problematic is when something is written to standard error; the message written there is used as the error message after newline stripping. Even just a newline will trigger a failure, and that failure overwrites any chance of getting the real out from the program (and in the case of just a newline, is highly mysterious). Here's a (possibly) reproduction of your problem:
% exec /bin/sh -c {echo >&2}
% set errorInfo
while executing
"exec /bin/sh -c {echo >&2}"
How to fix this? Well, you can try the -ignorestderr option (if supported by your version of Tcl, which you don't mention):
exec -ignorestderr tshark -Vxr /var/tmp/PCRF/create_req.pcap
Or you can try merging the standard output and standard error channels with 2>#1, so that the error messages are part of the overall output stream (and picked up as a normal result):
exec tshark -Vxr /var/tmp/PCRF/create_req.pcap 2>#1
Or you could use a merge-pipe (needed for older Tcl versions):
exec tshark -Vxr /var/tmp/PCRF/create_req.pcap |& cat
Or you can even direct the subprocess's standard error to the main standard error: the user (or exterior logger) will see the “error” output, but Tcl won't (and the exec won't fail):
exec tshark -Vxr /var/tmp/PCRF/create_req.pcap 2>#stderr
More elaborate things are possible with Tcl 8.6, which can make OS pipes with chan pipe, and you can (in all Tcl versions) run subprocesses as pipelines with open |… but these are probably overkill.
You don't need eval exec {stuff…}; plain old exec stuff… is precisely equivalent, shorter to write and a bit easier to get correct.

DBD::MySql initialisation failed: Can't locate object method "driver" via package "DBD::MySql" while using Bio-informatics tool OrthoMCL

I am trying to run the bio-informatics tool OrthoMCL on Ubuntu 12.04. This tool needs a MySQL database for data processing. My SQL database is working well and is version 5.5.34. OrthoMCL contains some Perl scripts to run into command line. When I run a that uses the folowing modules I get the folowing error:
mark#CMBIPC34:~/Bureaublad/OrthoMCL/orthomclSoftware-v2.0.9/bin$ perl orthomclLoadBlast '/home/mark/Bureaublad/my_orthomcl_dir/orthomcl.config' '/home/mark/Bureaublad/my_orthomcl_dir/compliantFasta/similarSequences.txt'
DBD::MySql initialisation failed: Can't locate object method "driver" via package "DBD::MySql" at /usr/local/lib/perl/5.14.2/DBI.pm line 821, <F> line 14.
Perhaps the capitalisation of DBD 'MySql' isn't right. at /home/mark/Bureaublad/OrthoMCL/orthomclSoftware-v2.0.9/bin/../lib/perl/OrthoMCLEngine/Main/Base.pm line 56
The modules are:
use DBI;
use FindBin;
use lib "$FindBin::Bin/../lib/perl";
use OrthoMCLEngine::Main::Base;
use strict;
When I ran this script to test installed modules
use DBI;
print "Available DBI Drivers and Data Sources:\n\n";
#drivers;
my #drivers=DBI->available_drivers('quiet');
my #sources;
foreach my $driver (#drivers) {
print "$driver\n";
#sources=eval { DBI->data_sources($driver) };
if ($#) {
print "\tError: ",substr($#,0,60),"\n";
} elsif (#sources) {
foreach (#sources) {
print "\t$_\n";
}
} else {
print "\tNo known data sources\n";
}
}
I get this result:
Available DBI Drivers and Data Sources:
DBM
DBI:DBM:f_dir=Verwijzing naar Stage-documenten
DBI:DBM:f_dir=my_orthomcl_dir
DBI:DBM:f_dir=Dropbox
DBI:DBM:f_dir=OrthoMCL
DBI:DBM:f_dir=MySQL
DBI:DBM:f_dir=.
DBI:DBM:f_dir=mcl-12-068
ExampleP
dbi:ExampleP:dir=.
File
DBI:File:f_dir=Verwijzing naar Stage-documenten
DBI:File:f_dir=my_orthomcl_dir
DBI:File:f_dir=Dropbox
DBI:File:f_dir=OrthoMCL
DBI:File:f_dir=MySQL
DBI:File:f_dir=.
DBI:File:f_dir=mcl-12-068
Gofer
No known data sources
Multiplex
No known data sources
MySql
Error: DBD::MySql initialisation failed: Can't locate object method
Proxy
No known data sources
Sponge
No known data sources
mysql
DBI:mysql:information_schema
When I try in the command line into downloaded folder DBD-mysql-4.025 I get this errors:
perl Makefile.PL
no error
make
/usr/bin/ld: cannot find -lmysqlclient
collect2: ld gaf exit-status 1 terug
make: *** [blib/arch/auto/DBD/mysql/mysql.so] Fout 1
make test
same error as make
make install
same error as make
I tried also installing by cpan[1]> install DBD::mysql and got this error:
/usr/bin/ld: cannot find -lmysqlclient
collect2: ld gaf exit-status 1 terug
make: *** [blib/arch/auto/DBD/mysql/mysql.so] Fout 1
CAPTTOFU/DBD-mysql-4.025.tar.gz
/usr/bin/make -- NOT OK
Running make test
Can't test without successful make
Running make install
Make had returned bad status, install seems impossible
Failed during this command:
CAPTTOFU/DBD-mysql-4.025.tar.gz : make NO
Where can I find -lmysqlclient, I can't find the file on the hard disk of the computer.
The problem don't occure while running this test perl script:
#!/usr/bin/perl -w
use DBI;
$dbh = DBI->connect('dbi:mysql:orthomcl','root','')
or die "Connection Error: $DBI::errstr\n";
$sql = "show tables";
$sth = $dbh->prepare($sql);
$sth->execute
or die "SQL Error: $DBI::errstr\n";
while (#row = $sth->fetchrow_array) {
print "#row\n";
}
In this case the tables of the database OrthoMCL will be displayed correcty without any error message.
I hope somebody can help me to solve this problem.
"Perhaps the capitalisation of ''MySql'' isn't right."
Does your connect statement use the proper capitalization?
$dbh = DBI->connect("dbi:mysql:...", ...);
Finally I found the solution. The problem was in the config file:
dbConnectString=dbi:MySql:orthomcl:localhost:3306
have to be
dbConnectString=dbi:mysql:orthomcl:localhost:3306

calling makefiles - handling exceptions

I realized that as I run makefiles from my main makefile, if they child makefiles fail, the parent continues and does not return with an error exit code.
I've tried to add the exception handling...but it does not work. Any ideas?
MAKE_FILES := $(wildcard test_*.mak)
compile_tests:
#echo "Compiling tests.$(MAKE_FILES)."
#for m in $(MAKE_FILES); do\
$(MAKE) -f "$$m"; || $(error Failed to compile $$m)\
done
You cannot use make functions like $(error ...) in your recipe, because all make variables and functions are expanded first, before the shell is invoked. So the error function will happen immediately when make tries to run that recipe, before it even starts.
You have to use shell constructs to fail, not make constructs; something like:
compile_tests:
#echo "Compiling tests.$(MAKE_FILES)."
#for m in $(MAKE_FILES); do \
$(MAKE) -f "$$m" && continue; \
echo Failed to compile $$m; \
exit 1
done
However, even this is not really great, because if you use -k it will still stop immediately. Better is to take advantage of what make does well, which is run lots of things:
compile_tests: $(addprefix tests.$(MAKE_FILES))
$(addprefix tests.$(MAKE_FILES)): tests.%:
$(MAKE) -f "$*"
One note, if you enable -j these will all run in parallel. Not sure if that's OK with you or not.