File Coverage

/.cpan/build/Simulation-Automate-1.0.1-vTiPpZ/blib/lib/Simulation/Automate.pm
Criterion Covered Total %
statement 337 638 52.8
branch 76 318 23.9
condition 22 101 21.7
subroutine 25 28 89.2
pod 2 17 11.7
total 462 1102 41.9


line stmt bran cond sub pod time code
1             package Simulation::Automate;
2              
3 2     2   6385 use vars qw( $VERSION );
  2         3  
  2         151  
4             $VERSION = "1.0.1";
5              
6             #################################################################################
7             # #
8             # Copyright (C) 2000,2002-2004 Wim Vanderbauwhede. All rights reserved. #
9             # This program is free software; you can redistribute it and/or modify it #
10             # under the same terms as Perl itself. #
11             # #
12             #################################################################################
13              
14             #headers
15             #
16             #Main module for SynSim simulation automation tool.
17             #The first part creates the module Loops.pm based on the data file;
18             #this module is then called via eval() and used by Simulation::Automate.pm
19             #Loops calls &Automate::main() at every pass through the loops.
20             #
21             #$Id$
22             #
23              
24              
25 2     2   14 use warnings;
  2         4  
  2         55  
26 2     2   11 use strict;
  2         14  
  2         63  
27 2     2   10 use Cwd;
  2         3  
  2         163  
28 2     2   11 use Carp;
  2         3  
  2         129  
29 2     2   10 use Exporter;
  2         23  
  2         56  
30 2     2   718 use lib '.';
  2         587  
  2         13  
31 2     2   7259 use Simulation::Automate::Remote;
  2         5  
  2         1662  
32              
33             @Simulation::Automate::ISA = qw(Exporter);
34             @Simulation::Automate::EXPORT = qw(
35             &synsim
36             &setup
37             &localinstall
38             );
39              
40             #===============================================================================
41             sub synsim {
42 1     1 1 5611 my $remotehost=&check_for_remote_host();
43 1 50       16 if($remotehost){
44 0         0 &run_on_remote_host($remotehost)
45             } else {
46 1         5 &run_local(); # new name for sub synsim
47             }
48             }
49             #===============================================================================
50             sub run_local {
51 1   50 1 0 23 my $datafile=shift||'synsim.data';
52              
53             ################################################################################
54             #
55             # Create module Simulation::Automate::Loops.pm
56             #
57             ################################################################################
58              
59 1         4 my @flags=my ($batch,$interactive,$nosims,$plot,$verbose,$warn)=@{&preprocess_commandline($datafile)};
  1         94  
60 1         9 my $dataset=$datafile;
61 1         19 $dataset=~s/\.data//;
62 1 50       6 print STDERR "\nCreating Loops.pm...\n" if $verbose;
63              
64 1         14 (my $dataref,my $groupedref)=&allow_multiple_sims($datafile);
65 1         8 my $simref=&generate_loop_module($dataref,$groupedref,$dataset,\@flags);
66              
67             ################################################################################
68             #
69             # Do the actual simulations
70             #
71             ################################################################################
72              
73 1 50       10 &execute_loop($datafile,$dataset,$simref,\@flags) && do {
74 1         164 unlink "Loops_$dataset.pm";
75             };
76 1 50       395 if($dataset ne 'synsim'){
77 0         0 print STDERR "\nFinished SynSim run for $dataset.data\n\n";
78             } else {
79 1         87 print STDERR "\nFinished SynSim run\n\n";
80             }
81 1         124 return 1;
82             }
83             #===============================================================================
84              
85             ################################################################################
86             ##
87             ## Subroutines
88             ##
89             ################################################################################
90              
91             sub preprocess_commandline {
92 1     1 0 9 my $datafile=$_[0];
93 1         7 my ($batch,$interactive,$nosims,$plot,$verbose,$warn,$justplot,$list_postprocessors)=(0,0,0,0,0,0,0,0);
94 1         4 my $default=1;
95 1 50       7 if(@ARGV) {
96 0         0 my $dtf=0;
97 0         0 foreach(@ARGV) {
98 0 0       0 if(/-f/){$dtf=1;next}
  0         0  
  0         0  
99 0 0       0 if($dtf==1) {
100 0         0 $_[0]=$_;$datafile=$_;$default=0;$dtf=0;
  0         0  
  0         0  
  0         0  
101             }
102 0 0       0 if(/-b/){$batch=1;next}
  0         0  
  0         0  
103 0 0       0 if(/-i/){$interactive=1;$plot=1;$verbose=1;next}
  0         0  
  0         0  
  0         0  
  0         0  
104 0 0       0 if(/-N/){$nosims=1;next}
  0         0  
  0         0  
105 0 0       0 if(/-p/){$plot=1;next}
  0         0  
  0         0  
106 0 0       0 if(/-v/){$verbose=1;next}
  0         0  
  0         0  
107 0 0       0 if(/-w/){$warn=1;next;}
  0         0  
  0         0  
108 0 0       0 if(/-P/){$justplot=1;next}
  0         0  
  0         0  
109 0 0       0 if(/-A/){$list_postprocessors=1;next}
  0         0  
  0         0  
110 0 0       0 if(/-D/) {
111 0 0       0 (not -d 'TEMPLATES') && mkdir 'TEMPLATES';
112 0 0       0 (not -d 'TEMPLATES/SIMTYPES') && mkdir 'TEMPLATES/SIMTYPES';
113 0 0       0 (not -d 'TEMPLATES/DEVTYPES') && mkdir 'TEMPLATES/DEVTYPES';
114 0 0       0 (not -d 'SOURCES') && mkdir 'SOURCES';
115 0 0       0 (not -d 'PLUGINS') && mkdir 'PLUGINS';
116 0         0 die "An empty directory structure has been created\n";
117             }
118 0 0       0 if(/-h|-\?/) {
119 0         0 my $script=$0;
120 0         0 $script=~s/.*\///;
121              
122             # -f flag now optional
123             # -f [filename]: 'file input'. Expects a file containing info about simulation and device type.
124              
125 0         0 die <<"HELP";
126              
127             The script must be executed in a subdirectory of the directory
128             containing the script.
129             This directory must contain at least a TEMPLATES/SIMTYPE subdir
130             with the simulation templates, and a data file. See documentation for more information.
131              
132             syntax: ./$script [-h -D -i -p -P -A -v -w -N datafile]
133              
134             Possible switches:
135              
136             none: defaults to -f $datafile
137             -D : Create an empty SynSim directory structure in the current directory
138             -v : 'verbose'. Sends simulator output to STDOUT, otherwise to simlog file
139             -p : plot. This creates the plot, but does not display it
140             -i : interactive. Creates a plot on the screen after every iteration. Implies -p -v
141             -P : Plot. This displays plots created with -p
142             -A : Analysis Templates. Displays a list of all available analysis templates and the man page
143             -w : 'warnings'. Show warnings for undefined variables.
144             -N : 'No simulations'. Does only postprocessing
145             -h, -? : this help
146             HELP
147             }
148             } # foreach @ARGV
149 0 0       0 if($list_postprocessors) {
150             #convenience function to list available postprocessors
151             #so get all subs from PostProcessors
152              
153 0         0 print "\n";
154 0 0       0 if(-e '../Simulation/Automate.pm') {
155             #This is good for a local SynSim, not for a global one
156 0         0 system("pod2text ../Simulation/Automate.pm | perl -n -e 'print if /^POST/../^DICT/ and !/DICT/' | less");
157              
158             } else {
159 0         0 system("man Simulation::Automate");
160              
161             }
162 2     2   12 no strict;
  2         2  
  2         10465  
163 0         0 require('../Simulation/Automate/PostProcessors.pm');
164 0         0 print "\nAvailable postprocessing routines:\n\n";
165 0         0 foreach my $key (sort keys %Simulation::Automate::PostProcessors::) {
166              
167 0 0       0 if( $key=~/^[A-Z]+[a-z]+/){
168 0         0 print "$key \n";
169             }
170             }
171 0         0 die "\n";
172             }
173             #test if the last argument might be the filename (if no -f flag)
174 0 0       0 if($default){
175 0         0 my $test=$ARGV[@ARGV-1];
176 0 0       0 if($test!~/^\-/) {
177 0         0 $datafile=$test;
178 0         0 $default=0;
179 0         0 $_[0]=$datafile;
180             }
181             }
182              
183 0 0       0 if($default) {
184 0 0       0 print STDERR "Assuming $datafile as input data filename\n" if $verbose;
185             }
186             } else {
187 1 50       10 print STDERR "No command line arguments given. Assuming $datafile as input data filename\n" if $verbose;
188             }
189              
190 1 50 33     64 if(not(-e "./TEMPLATES" && -d "./TEMPLATES" && -e "./$datafile")) {
      33        
191 0         0 die "
192             The current directory must contain at least a TEMPLATES/SIMTYPE subdir with the simulation templates, and a data file. See documentation for more information.
193              
194             If Simulation::Automate is installed locally, the current directory must be in the same directoy as the Simulation directory.
195              
196             ";
197             }
198 1 50       16 if($justplot) {
199             #convenience function to plot results
200 0         0 chomp(my $simtype=`egrep '^SIM(TYPE|NAME|ULATION|TEMPL)|^\ *TEMPLATE' $datafile`);
201 0         0 $simtype=~s/^SIM(TYPE|NAME|ULATION)|^\s*TEMPLATE\s*:\s*//;
202 0         0 $simtype=~s/\s*$//;
203 0         0 $simtype=~s/\..*$//;
204 0         0 chomp(my $anatype=`egrep '^ANA(LYSIS)*_*(TEMPL)*(ATE)*' $datafile`);
205 0         0 $anatype=~s/^ANA(LYSIS)*_*(TEMPL)*(ATE)*\s*:\s*//;
206 0         0 $anatype=~s/\s*$//;
207 0         0 $datafile=~s/\.data//;
208              
209 0         0 chdir "${simtype}-$datafile";
210 0         0 my $gv='/usr/bin/ggv';
211 0 0 0     0 if((not -e '/usr/bin/ggv') and ( -e '/usr/X11R6/bin/gv')) {
212 0         0 $gv='/usr/X11R6/bin/gv';
213             }
214 0         0 system("$gv ${simtype}-$anatype.ps");
215 0         0 die "Done\n";
216             }
217              
218              
219 1         10 return [$batch,$interactive,$nosims,$plot,$verbose,$warn];
220             } #END of preprocess_commandline
221              
222             #-------------------------------------------------------------------------------
223             #
224             # This subroutine takes a reference to %specific as generated by allow_multiple_sims($datafile) and passes it on to fill_data_hash_multi;
225             # It gets back %data, which contains the list of parameters and their value-list for every simtype
226             #
227              
228             sub generate_loop_module {
229 1     1 0 3 my $specificref=shift; #this is the reference to %specific, the hash of arrays of data for each sim
230 1         2 my $groupedref=shift;
231 1         4 my %grouped=%$groupedref;
232              
233 1         2 my $dataset=shift;
234 1         2 my $flagsref=shift;
235 1         2 my ($batch,$interactive,$nosims,$plot,$verbose,$warn)=@{$flagsref};
  1         2  
236 1         5 my $dataref=&fill_data_hash_multi($specificref);
237 1         2 my %data=%{$dataref};
  1         3  
238 1         91 open(MOD,">Loops_$dataset.pm");
239              
240 1         21 print MOD &strip(<<"ENDHEAD");
241             *package Loops_$dataset;
242             *#
243             *################################################################################
244             *# Author: WV #
245             *# Date : 21/11/2000;01/08/2002 #
246             *# #
247             *# Module to support script for SynSim simulations. #
248             *# The subroutine in this module generates the loop to do multiple simulations. #
249             *# This module is generated by Simulation::Automate.pm #
250             *# #
251             *################################################################################
252             *
253             *use sigtrap qw(die untrapped normal-signals
254             * stack-trace any error-signals);
255             *use strict;
256             *
257             *use FileHandle;
258             *use Exporter;
259             *
260             *\@Loops_${dataset}::ISA = qw(Exporter);
261             *\@Loops_${dataset}::EXPORT = qw(
262             ENDHEAD
263              
264 1         7 foreach my $sim (keys %data) {
265 1         5 print MOD &strip(
266             "* execute_${sim}_loop\n");
267             }
268 1         4 print MOD &strip('
269             * );
270             *
271             ');
272              
273 1         3 my @sims=();
274 1         6 foreach my $sim (keys %data) {
275 1         3 my $title=$data{$sim}{TITLE};
276 1         11 delete $data{$sim}{TITLE};
277              
278 1 50       63 my $nruns=(exists $data{$sim}{NRUNS})?$data{$sim}{NRUNS}:1;
279 1 50       6 if($nruns>1) {
280 0         0 $data{$sim}{__NRUNS}=join(',',(1..$nruns));
281             }
282 1         3 push @sims,$sim;
283 1         12 print MOD &strip(<<"ENDSUBHEAD");
284              
285             *use lib '..','../..';
286             *#use Simulation::Automate::Main;
287             *use Simulation::Automate;
288             *#use Simulation::Automate::PostProcessors;
289             *use Simulation::Automate::PostProcLib;
290             *
291             *sub execute_${sim}_loop {
292             *my \$dataset=shift;
293             *my \$dirname=\"${sim}-\$dataset\";
294             *my \$flagsref=shift;
295             *my \$i=0;
296             *my \$returnvalue;
297             *my \$resheader='';
298             *my \%last=();
299             *my \%sweepeddata=();
300             *my \$v=$verbose;
301             *my \$leaveloop=0;
302              
303             ENDSUBHEAD
304              
305             #if($data{$sim}{'PREPROCESSOR'}) {
306             #print MOD &strip('
307             #*my $preprocref=\&Simulation::Automate::PostProcessors::'.$data{$sim}{'PREPROCESSOR'}.';
308             #');
309             #} else {
310             #print MOD &strip('
311             #*my $preprocref;
312             #');
313             #}
314              
315             # TITLE is treated separately
316 1         6 print MOD &strip(
317             "*my \$TITLE = '$title';\n"
318             );
319              
320 1         3 foreach my $par (sort keys %{$data{$sim}}) {
  1         11  
321 2 50       10 $par!~/^\_/ && next;
322             #Here as good as anywhere else
323             #WV 010604
324             # We must deal with CONDVAR
325             # This is not good: it means some postprocessors require a change to the code!
326             #Anyway
327 0         0 my $conditional =0;
328 0 0       0 if (exists $data{$sim}{CONDVAR}) {
329             #CONDVAR must be the sweepvar
330 0         0 $conditional =1;
331             }
332              
333 0 0 0     0 if ( ( not $conditional and
      0        
      0        
      0        
334             (
335             (exists $data{$sim}{XVAR} and $par eq $data{$sim}{XVAR}) or (exists $data{$sim}{SWEEPVAR} and $par eq $data{$sim}{SWEEPVAR})
336             )
337             ) or ( $conditional and
338             ( $par eq $data{$sim}{CONDVAR})
339             )
340             ) {
341             #the sweep variable, make sure it's ; not ,
342 0         0 $data{$sim}{$par}=~s/,/;/g; # a bit rough, comments at end get it as well
343             #make sure grouped variables are treated as well
344 0 0       0 if (exists $grouped{$par}) {
345 0         0 my $leader=$grouped{$par};
346 0         0 foreach my $gpar (sort keys %grouped) {
347 0 0       0 if( $grouped{$gpar} eq $leader) {
348 0         0 $data{$sim}{$gpar}=~s/,/;/g;
349 0         0 delete $grouped{$gpar};
350             }
351             }
352             }
353             }
354             }
355             # define vars
356 1         3 foreach my $par (sort keys %{$data{$sim}}) {
  1         6  
357 2 50       12 if ($data{$sim}{$par}!~/,/) { # if just one item
358             # support for "for..to..step.."-style lists
359 2         9 $data{$sim}{$par}=&expand_list($data{$sim}{$par});
360              
361 2         6 $data{$sim}{$par}=~s/^\'//;
362 2         5 $data{$sim}{$par}=~s/\'$//;
363 2         10 print MOD &strip(
364             "*my \$${par} = '$data{$sim}{$par}';\n"
365             );
366             }
367             }
368             # assign common hash items
369 1         3 print MOD &strip(
370             "*my \%data=();\n"
371             );
372 1         5 print MOD &strip('
373             * print STDERR "# SynSim configuration variables\n" if $v;
374             * print STDERR "#","-" x 79,"\n# TITLE : '.$title.'\n" if $v;
375             * $resheader.= "# SynSim configuration variables\n";
376             * $resheader.= "#"."-" x 79;
377             * $resheader.= "\n# TITLE : '.$title.'\n";
378             ');
379 1         3 print MOD &strip(
380             "*\$data{TITLE}=\$TITLE;\n"
381             );
382 1         3 my $nsims=1;
383 1         5 my $prevkey='';
384              
385 1         2 foreach my $par (sort keys %{$data{$sim}}) {
  1         5  
386              
387 2 50 33     7 if($par=~/^_/ && $prevkey!~/^_/) {
388 0         0 print MOD &strip('
389             * print STDERR "#","-" x 79,"\n" if $v;
390             * print STDERR "# Static parameters used in the simulation:\n" if $v;
391             * print STDERR "#","-" x 79,"\n" if $v;
392             * $resheader.= "#"."-" x 79;
393             * $resheader.= "\n# Static parameters used in the simulation:\n";
394             * $resheader.= "#"."-" x 79;
395             * $resheader.= "\n";
396             ');
397             }
398              
399 2 50       8 if ($data{$sim}{$par}!~/,/) { # if just one item, or it might be a sweep
400 2 50       9 if($data{$sim}{$par}=~/(\d+)\s*\.\.\s*(\d+)/) {
    50          
401 0         0 my $b=$1;
402 0         0 my $e=$2;
403 0         0 my $patt="$b .. $e";
404 0         0 $nsims=$e-$b+1;
405 0         0 print MOD &strip(
406             "*my \@tmp$par=($patt);
407             *\$data{$par} = [\@tmp$par];
408             *print STDERR \"# $par = \$$par\\n\" if \$v;
409             *\$resheader.= \"# $par = \$$par\\n\";
410             ");
411              
412             } elsif($data{$sim}{$par}=~/;/) {
413            
414 0         0 my $tmp=$data{$sim}{$par};
415 0         0 my $tmps=($tmp=~s/;/,/g);
416 0 0       0 if($tmps>=$nsims){$nsims=$tmps+1}
  0         0  
417 0         0 print MOD &strip(
418             "*my \@tmp$par=split(/;/,\$$par);
419             *\$data{$par} = [\@tmp$par];
420             *print STDERR \"# $par = \$$par\\n\" if \$v;
421             *\$resheader.= \"# $par = \$$par\\n\";
422             ");
423             } else {
424 2 50       6 if($par=~/^_/) {
425 0         0 print MOD &strip(
426             "*\$data{$par} = [\$$par];
427             *print STDERR \"# $par = \$$par\\n\" if \$v;
428             *\$resheader.= \"# $par = \$$par\\n\";
429             ");
430             } else {
431 2         11 print MOD &strip(
432             "*\$data{$par} = \$$par; # no reason for array
433             *print STDERR \"# $par : \$$par\\n\" if \$v; # no reason to print
434             *\$resheader.= \"# $par : \$$par\\n\"; # no reason to print
435             ");
436             }
437             }
438             }
439 2         43 $prevkey=$par;
440             }
441              
442 1         9 print MOD &strip(
443             "*my \$nsims=$nsims;\n"
444             );
445              
446              
447 1         3 foreach my $par (sort keys %{$data{$sim}}) {
  1         4  
448              
449 2 50       7 if ($data{$sim}{$par}=~/,/) { # if more than one item
450             # support for "for to step"-style lists
451 0         0 $data{$sim}{$par}=&expand_list($data{$sim}{$par});
452 0         0 my $parlist=$data{$sim}{$par};
453 0         0 $parlist=~s/,/ /g;
454             #support for "grouped" parameters
455 0 0       0 if(exists $grouped{$par}) {
456 0 0       0 if($grouped{$par} eq $par){ # the "leader" of the group
457 0         0 my $leader=$par;
458 0         0 foreach my $var (sort keys %grouped) {
459 0 0       0 if($grouped{$var} eq $leader){
460 0         0 my $varlist=$data{$sim}{$var};
461 0         0 $varlist=~s/,/ /g;
462 0         0 print MOD &strip(
463             "*my \@${var}list = qw($varlist);
464             *\$last{$var}=\$${var}list[\@${var}list-1];
465             ");
466             }
467             }
468 0         0 print MOD &strip("*foreach my \$${par} (\@${par}list) {\n");
469 0         0 foreach my $var (sort keys %grouped) {
470 0 0       0 ($var eq $par) && next;
471 0 0       0 if($grouped{$var} eq $leader){
472 0         0 print MOD &strip("*my \$${var}=shift(\@${var}list);\n");
473             }
474             }
475             }
476             } else {
477 0         0 print MOD &strip(
478             "*my \@${par}list = qw($parlist);
479             *\$last{$par}=\$${par}list[\@${par}list-1];
480             *foreach my \$${par} (\@${par}list) {\n"
481             );
482             }
483             }
484             }
485 1         6 print MOD &strip(
486             "*\$i++;
487             *open(RES,\">\$dirname\/${sim}_C\$i.res\")|| do {print STDERR \"Can\'t open \$dirname\/${sim}_\$i.res\" if \$v;};
488             ");
489 1         4 print MOD &strip('
490             * print STDERR "#","-" x 79,"\n" if $v;
491             * print STDERR "# Parameters for simulation run $i:\n" if $v;
492             * print RES $resheader;
493             * print RES "#"."-" x 79,"\n";
494             * print RES "# Parameters for simulation run $i:\n";
495             ');
496              
497 1   0     7 my $simtempl=$data{$sim}{SIMTYPE}||$data{$sim}{SIMNAME}||$data{$sim}{SIMULATION}||$data{$sim}{TEMPLATE}||$data{$sim}{SIMTEMPL};
498             #$simtempl=~s/\.\w+$//;
499              
500 1   50     42 my $anatempl=$data{$sim}{ANALYSIS_TEMPLATE}||$data{$sim}{ANALYSIS}||$data{$sim}{ANATEMPL}||$data{$sim}{ANALYSIS_TEMPL}||$data{$sim}{ANA_TEMPLATE}||'None';#'NoAnalysisDefined';
501 1         2 my $subref=$anatempl;
502              
503 1         4 print MOD &strip('
504             *my $resfilename="'.$sim.'-'.$anatempl.'";
505             *$data{RESHEADER}=$resheader;
506             ');
507              
508 1         3 foreach my $par (sort keys %{$data{$sim}}) {
  1         7  
509 2 50       8 if ($data{$sim}{$par}=~/,/) { # if more than one item
510 0         0 print MOD &strip(
511             "*\$data{$par} = [\$$par];
512             *\$sweepeddata{$par} = \$$par;
513             *\$resfilename.=\"-${par}-\$$par\";
514             *print STDERR \"# $par = \$$par\\n\" if \$v;
515             *print RES \"# $par = \$$par\\n\";
516             ");
517             }
518             }
519              
520             ##WV21042003: old, sweep loops internal
521             #print MOD &strip(
522             #"* close RES;
523             #*\$resfilename.='.res';
524             #*#NEW01072003#rename \"\$dirname\/${sim}_C\$i.res\",\"\$dirname\/\$resfilename\";
525             #*my \$dataref = [\$nsims,\\\%data];
526             #*\$returnvalue=&main(\$dataset,\$i,\$dataref,\$resfilename,\$flagsref);
527             #*
528             #");
529              
530             #WV21042003: new, sweep loops external
531              
532             #The idea is to evaluate a condition inside the loop, after very sim
533             #If the condition is satisfied, skip the next
534              
535 1         6 print MOD &strip(
536             "* close RES;
537             *my \$dataref = [\$nsims,\\\%data];
538             *#my \$nsims=&pre_run(\$dataset,\$i,\$dataref,\$flagsref);
539             *\$nsims=&pre_run(\$dataset,\$i,\$dataref,\$flagsref);
540             *my \$dataref_postproc = [\$nsims,\\\%data,\\\%sweepeddata,\\\%last];
541             *foreach my \$simn (1..\$nsims) {
542             *\$leaveloop && last;
543             *\$returnvalue=&run(\$nsims,\$simn);
544             *#print STDERR \"RET:\$returnvalue=\$nsims,\$simn\\n\";
545             *
546             *#Call postprocessor inside loop to see if we can leave the loop early
547             *#chdir \$dirname;
548             *#print \"SUBREF:$subref\\n\";
549             *#\$leaveloop=&Simulation::Automate::PostProcessors::$subref(\$dataset,\$i,\$dataref_postproc,\$flagsref,[\$returnvalue],\$preprocref,2);
550             *#chdir '..';
551             *#print \"LEAVE: \$leaveloop\\n\";
552             *}
553             *\$returnvalue=&post_run();
554             *
555             ");
556              
557              
558 1         6 print MOD &strip(<<"ENDPP");
559             *chdir \$dirname;
560             *my \$dataref1 = [\$nsims,\\\%data,\\\%sweepeddata,\\\%last];
561             *#&Simulation::Automate::PostProcessors::$subref(\$dataset,\$i,\$dataref1,\$flagsref,\$returnvalue,\$preprocref);
562             *&prepare(\$dataset,\$i,\$dataref1,\$flagsref,\$returnvalue);
563             *chdir '..';
564             ENDPP
565              
566 1         4 foreach my $par (reverse sort keys %{$data{$sim}}) {
  1         4  
567 2 50       8 if ($data{$sim}{$par}=~/,/) {
568 0 0 0     0 if( not exists $grouped{$par} or (exists $grouped{$par} and ($grouped{$par} eq $par))) {
      0        
569 0         0 print MOD &strip(
570             "*} #END of $par\n"
571             );
572             }
573             }
574             }
575              
576 1         5 print MOD &strip(<<"ENDPP");
577             *chdir \$dirname;
578             *my \$dataref2 = [\$nsims,\\\%data,\\\%sweepeddata,\\\%last];
579             *#&Simulation::Automate::PostProcessors::$subref(\$dataset,\$i,\$dataref2,\$flagsref,1);
580             *&prepare(\$dataset,\$i,\$dataref2,\$flagsref,1);
581             *chdir '..';
582             ENDPP
583              
584 1         4 print MOD &strip(<<"ENDTAIL");
585             * return \$returnvalue;
586             *} #END of execute_${sim}_loop
587             ENDTAIL
588 1         5 $data{$sim}{TITLE}=$title;
589             } #END of loop over sims
590              
591 1         94 close MOD;
592 1 50       4 print STDERR "...Done\n\n" if $verbose;
593              
594 1         8 return \%data;
595             } #END of generate loop module
596              
597             #-------------------------------------------------------------------------------
598             sub strip {
599 20     20 0 94 my $line=shift;
600 20         194 $line=~s/(^|\n)\*/$1/sg;
601 20         82 return $line;
602             }
603             #-------------------------------------------------------------------------------
604             #
605             # This subroutine takes a reference to %specific as generated by allow_multiple_sims($datafile)
606             # So %multisimdata is actually %specific
607             # Then, it turns this into a hash of hashes:
608             # for every $sim, there's a hash with as key the parameter name and as value its value-list
609             # This is %data, which is returned to $dataref in generate_loop_module()
610             #
611             sub fill_data_hash_multi {
612 1     1 0 2 my $dataref=shift; # reference to %specific
613 1         2 my %data=();
614 1         4 my %multisimdata=%$dataref;
615 1         7 foreach my $sim (keys %multisimdata) {
616              
617 1         3 foreach (@{$multisimdata{$sim}}){
  1         3  
618              
619 3 50       17 if(/^\s*_/) {
    50          
620              
621 0         0 my @line=();#split(/\s*=\s*/,$_);
622             # changed to allow expressions with "="
623 0         0 my $line=$_;
624 0 0       0 ($line=~s/^([A-Z0-9_]+)?\s*=\s*//)&&($line[0]=$1);
625 0         0 $line[1]=$line;
626 0         0 $line[1]=~s/\s*\,\s*/,/g;
627 0         0 $line[1]=~s/\s*\;\s*/;/g;
628             #13082004:What if we just replace ; by , here?
629 0 0       0 ($line[1]!~/[a-zA-Z]/) &&($line[1]=~s/;/,/g); # if there are no expressions
630              
631 0         0 $data{$sim}{$line[0]}=$line[1];
632             } elsif (/:/) {
633 3         5 my @line=();#split(/\s*:\s*/,$_);
634             # changed to allow expressions with ":"
635 3         5 my $line=$_;
636 3 50       23 ($line=~s/^([A-Z0-9_]+)?\s*\:\s*//)&&($line[0]=$1);
637 3         5 $line[1]=$line;
638             #strip trailing spaces
639 3         9 $line[1]=~s/\s+$//;
640 3         24 $data{$sim}{$line[0]}=$line[1];
641             } #if
642             } # foreach
643             }
644 1         4 return \%data;
645             } #END of fill_data_hash_multi
646              
647             #-------------------------------------------------------------------------------
648             #
649             # this subroutine splits the datafile into a common part (@common) and a number
650             # of simtype-specific parts ( %specific{$simtype}); then, it pushes @common onto
651             # @{$specific{$simtype}} and returns \%specific
652             # So every key in %specific points to an array with all variables needed for that simtype
653             #
654             sub allow_multiple_sims {
655 1     1 0 7 my $datafile=shift;
656 1         3 my @sims=();
657 1         2 my $simpart=0;
658 1         8 my $simpatt='NOPATTERN';
659 1         4 my @common=();
660 1         7 my %specific=();
661 1         22 my %grouped=();
662 1         7 my $simtype='NOKEY';
663 1         3 my $skip=0;
664 1 50       63 open(DATA,"<$datafile")|| die "Can't open $datafile\n";
665              
666 1         35 while() {
667              
668 3 50       14 /^\s*\#/ && next;
669 3 50       21 /^\s*$/ && next;
670 3         5 chomp;
671             # allow include files for configuration variables
672 3 50       9 /INCL.*\s*:/ && do {
673 0         0 my $incl=$_;
674 0         0 $incl=~s/^.*\:\s*//;
675 0         0 $incl=~s/\s+$//;
676 0 0       0 my @incl=($incl=~/[,;]/)?split(/\s*[,;]\s*/,$incl):($incl);
677 0         0 foreach my $inclf (@incl) {
678 0 0       0 open(INCL,"<$inclf")|| die $!;
679 0         0 while(my $incl=) {
680 0 0       0 $incl=~/^\s*\#/ && next;
681 0 0       0 $incl=~/^\s*$/ && next;
682 0         0 chomp $incl;
683             # only configuration variables in include files!
684 0 0       0 ($incl=~/:/) && do {push @common,$incl};
  0         0  
685             }
686 0         0 close INCL;
687             }
688             }; # END of allow INCL files
689             #print STDERR "$_\n";
690 3         8 s/(\#.*)//; # strip comments
691 3         7 s/[;,]\s*$//; # be tolerant: remove separators at end of line
692 3 100 33     125 if(/SIM(TYPE|NAME|ULATION|TEMPL)|\bTEMPLATE\s*:/) {
    50          
    50          
693 1         7 my $sims=$_;
694 1         3 s/TEMPLATE/SIMULATION/;
695 1         2 s/\.\w+$//;
696 1         12 (my $par,$simpatt)=split(/\s*:\s*/,$sims);
697 1         3 $simpatt=~s/\s*\,\s*/|/g;
698 1         3 $simpatt=~s/\s+//g;
699 1         3 @sims=split(/\|/,$simpatt);
700 1         7 my $ext='';
701 1         7 foreach my $sim (@sims){
702 1         3 $sim=~s/(\.\w+)$//;
703 1         16 $ext=$1;
704             };
705 1 50 33     9 if($ext && $ext=~/^\./){
706 0         0 push @common,"TEMPL: $ext\n";
707             }
708 1         3 $simpatt=join('|',@sims);
709 1         4 $simpatt='('.$simpatt.')';
710             } elsif(/$simpatt/) {
711 0         0 $skip=0;
712 0         0 $simtype=$1;
713             #$simtype=~s/\.\w+$//;
714 0         0 $simpart=1
715             } elsif(/^\s*[a-zA-Z]/&&!/:/) {
716 0         0 $simpart=0;
717 0         0 $skip=1;
718 0         0 print STDERR "$_: Not present in simlist. Skipping data.\n";
719             }
720 3 50       11 /^\s*GROUP\s*:\s*([\_A-Z0-9\,\;\s]+)$/ && do {
721 0         0 my $groupline=$1;
722             #This assumes a single GROUP line with a semicol-separated list of comma-separated values
723             #Too complex. Just allow multiple GROUP lines, one per group
724             #my @grouped=split(/\s*\;\s*/,$groupline);
725             #foreach my $group (@grouped){
726             #my @groupline=split(/\s*\,\s*/,$group);
727             #foreach my $item (@groupline){
728             #$grouped{$item}=$groupline[0];
729             #}
730             #}
731 0         0 my @groupline=split(/\s*[\,\;]\s*/,$groupline);
732 0         0 foreach my $item (@groupline){
733 0         0 $grouped{$item}=$groupline[0];
734             }
735 0         0 next;
736             };
737 3 50       10 if($simpart) {
    50          
738 0         0 push @{$specific{$simtype}},$_;
  0         0  
739             } elsif(!$skip) {
740 3         18 push @common,$_;
741             } else {
742 0         0 print STDERR "Skipped: $_\n" ;
743             }
744              
745             } #while
746 1         14 close DATA;
747              
748 1         5 foreach my $sim (@sims) {
749 1         6 push @{$specific{$sim}},@common;
  1         9  
750             }
751              
752 1         12 return (\%specific,\%grouped);
753             } #END of allow_multiple_sims
754             #-------------------------------------------------------------------------------
755             #
756             # this subroutine expands for-to-step lists in enumerated lists
757             #
758             sub expand_list {
759 2     2 0 5 my $list=shift;
760 2         3 $list=~s/\#.*$//;
761 2 50       12 my $sep=($list=~/;/)?';':','; #
762              
763 2         40 my @list=split(/\s*$sep\s*/,$list);
764 2 50 33     11 if(@list==3 && $list!~/[a-zA-Z]/) { #
765 0 0 0     0 if(
      0        
766             (
767             ($list[0]<$list[1] && $list[2]>0)||($list[0]>$list[1] && $list[2]<0)
768             ) && (
769             abs($list[2])
770             )
771             ) {
772 0         0 my $start=$list[0];
773 0         0 my $stop=$list[1];
774 0         0 my $step=$list[2];
775 0         0 $list="$start";
776 0         0 my $i=$start;
777 0   0     0 while(("$i" ne "$stop")&&((($stop>=0)&&($i<$stop))||(($stop<0)&&($i>$stop)))) { #yes, strange, but Perl says 0.9>0.9 is true!
      0        
778 0         0 $i+=$step;
779 0         0 $list.="$sep$i";
780             }
781             #print "LIST: $list\n";
782             #die;
783             }
784             }
785              
786 2         10 return $list;
787             } # END of expand_list
788             #===============================================================================
789              
790             sub execute_loop {
791 1     1 0 2 my $datafilename=shift;
792 1         3 my $dataset=shift;
793              
794 1         832 require "./Loops_$dataset.pm";
795             #eval("
796             #use Loops_$dataset;
797             #");
798              
799 1         5 my $simref=shift;
800 1         3 my @flags=@{shift(@_)};
  1         4  
801 1         3 my $nosims=$flags[2];
802 1         2 my $verbose=$flags[4];
803              
804 1         1 foreach my $sim (sort keys %{$simref}) {
  1         7  
805 1         1 my $commandline=${$simref}{$sim}->{COMMAND};
  1         4  
806              
807 1 50       5 $commandline && do {
808 1         5 $commandline=~s/inputfile//i;
809 1         4 $commandline=~s/outputfile//i;
810 1         3 $commandline=~s/\s\-+\w+//g;
811 1         3 $commandline=~s/^\s+//;
812 1         5 $commandline=~s/\s+$//;
813             };
814 1 50       9 my @maybe_files=($commandline)?split(/\s+/,$commandline):();
815              
816             # extension for template files
817 1   50     2 my $templ=${$simref}{$sim}->{TEMPLEXT}||${$simref}{$sim}->{TEMPL}||'.templ';
818 1   50     1 my $dev=${$simref}{$sim}->{DEVTYPE}||${$simref}{$sim}->{DEVICE}||'';
819              
820 1         4 my $dirname= "${sim}-$dataset";
821              
822 1 50 33     46 if(-e $dirname && -d $dirname) {
823 1 50       4 if ($nosims==0) {
824 1 50       3 print STDERR "\n# Removing old $dirname dir\n" if $verbose;
825 1 50       5 if ($verbose) {
826 0         0 print `rm -Rf $dirname`;
827             } else {
828 1         5963 system("rm -Rf $dirname");
829             }
830             } else {
831 0 0       0 print STDERR "\n# Cleaning up $dirname dir\n" if $verbose;
832 0 0       0 if ($verbose) {
833 0         0 print `rm -f $dirname/$sim-*`;
834 0         0 print `rm -f $dirname/tmp*`;
835             } else {
836 0         0 system("rm -f $dirname/tmp*");
837             }
838             }
839             }
840              
841 1 50 33     126 if (not -e "TEMPLATES/SIMTYPES/$sim$templ" and not -e "TEMPLATES/$sim$templ" ) {
842            
843 0         0 print STDERR "No templates for simulation $sim. Skipped.\n";# if $verbose; #always warn!
844 0         0 next;
845              
846             } else {
847             #if the template in under TEMPLATES, make a simlink to TEMPLATES/SIMTYPES
848 1 50 33     47 if (-e "TEMPLATES/$sim$templ" and not -l "TEMPLATES/SIMTYPES/$sim$templ" ) {
849 0         0 system("cd TEMPLATES/SIMTYPES && ln -s ../$sim$templ .");
850             }
851 1         141 mkdir $dirname, 0755;
852              
853 1 50       28 if (-e "TEMPLATES/SIMTYPES/$sim$templ") {
854 1         10783 system("cp TEMPLATES/SIMTYPES/$sim$templ $dirname");
855             } else {
856 0         0 die "There's no simulation template for $sim in TEMPLATES/SIMTYPES\n";
857             }
858 1 50       59 if($dev){
859 0 0       0 if (-e "TEMPLATES/DEVTYPES/$dev$templ") {
860 0         0 system("cp TEMPLATES/DEVTYPES/$dev$templ $dirname");
861             } else {
862 0 0       0 print STDERR "No device template for $dev in TEMPLATES/DEVTYPES.\n" if $verbose;
863             }
864             }
865             # any file with this pattern is copied to the rundir.
866 1 50       82 if (-d "SOURCES") {
867 1 50       185 if(){
868 0         0 system("cp SOURCES/$sim* $dirname");
869             }
870 1         25 foreach my $maybe_file(@maybe_files){
871 1 50 33     61 if(-e "SOURCES/$maybe_file" and not -e "$dirname/$maybe_file"){
872 0         0 system("cp SOURCES/$maybe_file $dirname/$maybe_file");
873             }
874             }
875             }
876             }
877 1 50       11 print STDERR "#" x 80,"\n" if $verbose;
878 1 50       9 print STDERR "#\n" if $verbose;
879 1 50       7 print STDERR "# Simulation type: $sim, device dir ".`pwd`."#\n" if $verbose;
880 1 50       8 print STDERR "#" x 80,"\n" if $verbose;
881              
882 1         338 eval('&Loops_'.$dataset.'::execute_'.$sim.'_loop($dataset,\@flags);');
883              
884             } #sims
885 1         36 return 1;
886             } #END of &execute_loop
887             #==============================================================================
888             #Routines to support script for simulation automation.
889             #The function &main() is called from the innermost loop of
890             #Loops_*.pm
891             push @Simulation::Automate::EXPORT, qw(
892             main
893             pre_run
894             run
895             post_run
896             );
897              
898 2     2   1274 use Simulation::Automate::Analysis;
  2         7  
  2         576  
899              
900             ##################################################################################
901             my $simpid=undef;
902              
903              
904              
905             #========================================================================================
906             # NEW IMPLEMENTATION TO ALLOW POSTPROCESSING AFTER EVERY ELEMENT IN SWEEP
907             #========================================================================================
908             my @results=();
909             my @sweepvarnames=();
910             my %simdata=();
911             my $simtype='NO_SIMTYPE';
912             my $dataset='NO_DATASET';
913             my $count=0;
914             my $batch; my $interactive; my $nosims; my $plot; my $verbose; my $warn;
915             my $output_filter_pattern= '.*';
916             my $command='perl inputfile outputfile';
917             my $dirname= 'NO_DIRNAME';
918             my $devtype='NO_DEVTYPE';
919             my $simtitle='NO_TITLE';
920             my $title="#$devtype $simtype simulation\n";
921             my $ext='.templ';
922             my $extin='.pl';
923             my $workingdir = 'NO_WORKINGDIR';
924             #------------------------------------------------------------------------------
925              
926             sub pre_run {
927             #called as:&pre_run(\$dataset,\$i,\$dataref,\$flagsref);
928 1     1 0 6 $dataset=shift;
929 1         4 $count=shift;
930 1         1 my $dataref=shift;
931 1         2 my $flagsref=shift;
932              
933 2     2   14 use Cwd;
  2         6  
  2         6786  
934              
935             #extract flags from flagsref
936 1         2 ($batch,$interactive,$nosims,$plot,$verbose,$warn)=@{$flagsref};
  1         5  
937             #extract number of sims and ref to simdata from dataref
938 1         2 (my $nsims, my $simdataref)=@{$dataref};
  1         3  
939             #put simdata in a hash
940 1         2 %simdata=%{$simdataref};
  1         10  
941              
942 1 50       5 print STDERR '#',"-" x 79, "\n" if $verbose;
943              
944 1   50     9 $command=$simdata{COMMAND}||'perl inputfile outputfile';
945 1   50     13 $output_filter_pattern=$simdata{OUTPUT_FILTER_PATTERN}|| '.*';
946 1   0     10 $simtype=$simdata{SIMTYPE}||$simdata{SIMNAME}||$simdata{SIMULATION}||$simdata{TEMPLATE}||$simdata{SIMTEMPL}||'';
947             #$simtype=~s/\.\w+$//;
948 1         7 $dirname= "${simtype}-$dataset";
949 1   50     19 $devtype=$simdata{DEVTYPE}||$simdata{DEVICE}||$simdata{DEVTEMPL}||'';
950 1         5 $simtitle=$simdata{TITLE};
951 1         5 @sweepvarnames=();
952 1         7 foreach my $key (keys %simdata) {
953 4 50       14 ($key!~/^_/) && next;
954 0 0       0 ($simtitle=~/$key/) && do {
955 0         0 $simtitle=~s/$key/$key:$simdata{$key}/;
956             };
957 0         0 my $ndata=@{$simdata{$key}};
  0         0  
958 0 0       0 if($ndata>1) {
959 0         0 push @sweepvarnames,$key;
960             }
961             }
962 1   33     11 $title="#$simtitle\n"||"#$devtype $simtype simulation\n";
963 1   50     13 $ext=$simdata{TEMPLEXT}||$simdata{TEMPL}||'.templ';
964 1   50     7 $extin=$simdata{EXT}||'.pl';
965 1         8765 $workingdir =cwd();
966 1         64 chdir "$workingdir/$dirname";
967 1         29 return $nsims;
968             } #END of pre_run()
969             #------------------------------------------------------------------------------
970              
971             sub run {
972             #called as:&run(\$nsims,\$simn);
973 1     1 1 3 my $nsims=shift;
974 1         6 my $simn=shift;
975              
976             ## INPUT FILE CREATION
977              
978 1 50       15 if($nsims==1){$simn=''} else {
  1         11  
979             # print STDERR "# Subrun $simn of $nsims \n" if $verbose;
980 0 0       0 if($simn==1){
981 0 0       0 print STDERR "# Sweep $nsims values for " if $verbose;
982 0         0 foreach my $sweepvarname(@sweepvarnames){
983 0 0       0 print STDERR "$sweepvarname " if $verbose;
984             }
985 0 0       0 print STDERR ":\n" if $verbose;
986             }
987 0         0 foreach my $sweepvarname(@sweepvarnames){
988 0 0       0 print STDERR $simdata{$sweepvarname}->[$simn-1],' ' if $verbose;
989             # print STDERR " $sweepvarname = ",$simdata{$sweepvarname}->[$simn-1] if $verbose;
990             }
991 0 0       0 print STDERR " \n" if $verbose;
992              
993             # foreach my $sweepvarname(@sweepvarnames){
994             # print STDERR " $sweepvarname = ",$simdata{$sweepvarname}->[$simn-1] if $verbose;
995             #}
996             #
997             }
998 1         13 my $inputfile= "${simtype}_${simn}$extin";
999 1         8 my $outputfile= "${simtype}_C${count}_${simn}.out";
1000 1         8 my $commandline=$command;
1001 1         16 $commandline=~s/inputfile/$inputfile/ig;
1002 1         178 $commandline=~s/outputfile/$outputfile/ig;
1003            
1004 1         130 open (NEW, ">$inputfile");
1005              
1006 1         9 foreach my $type ($devtype,$simtype) {
1007 2 100       12 if($type) {
1008 1 50       4 my $nsim=($simn eq '')?0:$simn;
1009 1         13 &gen_sim_script ($nsim-1,"$simtype$ext",\%simdata,\*NEW,$dataset,$warn);
1010             }
1011             } # device and simulation templates
1012 1         55 close (NEW);
1013              
1014 1 50       5 if($nosims==0) {
1015 1 50       4 if($verbose) {
1016 0 0       0 if (!defined($simpid = fork())) {
    0          
1017             # fork returned undef, so failed
1018 0         0 die "cannot fork: $!";
1019             } elsif ($simpid == 0) {
1020             # fork returned 0, so this branch is the child
1021 0         0 exec("$commandline");
1022             # if the exec fails, fall through to the next statement
1023 0         0 die "can't exec $commandline : $!";
1024             } else {
1025             # fork returned neither 0 nor undef,
1026             # so this branch is the parent
1027 0         0 waitpid($simpid, 0);
1028             }
1029             } else { # not verbose
1030 1 50       5 print STDERR "\n" if $verbose;
1031 1   50     3915 $simpid = open(SIM, "$commandline 2>&1 |") || die "can't fork: $!";
1032 1         118 open(LOG,">simlog");
1033 1         1317238 while () {
1034 6         36 print LOG;
1035 6 50       55 /$output_filter_pattern/ && do {
1036 6         7165 print STDERR;# if $verbose;
1037             };
1038             } # while sinulation is running
1039 1         119 close LOG;
1040 1         19 my $ppid=getpgrp($simpid);
1041 1 50       9 if(not $ppid) {
1042 0 0       0 close SIM || die "Trouble with $commandline: $! $?";
1043             }
1044 1 50       6 print STDERR "\n" if $verbose;
1045             } #verbose or not
1046              
1047 1 50       7 if($nsims>1) {
1048             #Postprocessing
1049 0         0 &egrep($output_filter_pattern,"${simtype}_C${count}_${simn}.out",'>>',"${simtype}_C${count}_.out");
1050             }
1051             } # if simulations not disabled
1052 1 50       5 my $i=($nsims>1)?$simn-1:0;
1053 1         58 open(RES,"<${simtype}_C${count}_${simn}.out");
1054 1         30 $results[$i]=;
1055 1         4 my $another=; # This takes the next line, if any,
1056 1 50       7 if($another) { # and if there is one, it assigns the filename to $results[$i]
1057 1         4 $results[$i]="${simtype}_C${count}_${simn}.out";
1058             }
1059 1         15 close RES;
1060              
1061             #no need to return @results, it's a package global now. Maybe return $results[$i], makes more sense.
1062 1         3 my $result= $results[$i];
1063 1         5 chomp $result;
1064 1         44 return $result; # PostProcessors are only called after &main() exits.
1065             } # END of run()
1066             #------------------------------------------------------------------------------
1067             sub post_run {
1068             #called as:&post_run();
1069 1 50   1 0 6 if($nosims==0){
1070             #Postprocessing after sweep
1071 1         21 &egrep($output_filter_pattern, "${simtype}_C${count}_.out", '>>', "${simtype}_C$count.res");
1072 1 50       23 if( $results[0]=~/${simtype}_C\d+.*\.out/) {
1073 1         28 open(RES,"${simtype}_C$count.res");
1074 1         21 @results=;
1075 1         11 close RES;
1076             }
1077             }
1078 1         29 chdir "$workingdir";
1079              
1080 1         6 return \@results; # PostProcessors are only called after &main() exits.
1081              
1082             } # END of post_run()
1083             #==============================================================================
1084              
1085             #print STDERR "\n","#" x 80,"\n#\t\t\tSynSim simulation automation tool\n#\n# (c) Wim Vanderbauwhede 2000,2002-2003. All rights reserved.\n# This program is free software; you can redistribute it and/or modify it\n# under the same terms as Perl itself.\n#\n","#" x 80,"\n";
1086              
1087             #-------------------------------------------
1088             # SUBROUTINES used by main, pre_run, run, post_run
1089             #-------------------------------------------
1090              
1091             #--------------------------------------
1092             # GENERATION OF THE SIMULATION SCRIPT
1093             #--------------------------------------
1094              
1095             #WV What happens: the templates for _SIMTYPE are read in
1096             #WV and the variables are substituted with the values from the .data file
1097              
1098             sub gen_sim_script {
1099              
1100 1     1 0 2 my $nsim=shift;
1101 1         2 my $templfilename=shift;
1102 1         1 my $simdataref=shift;
1103 1         2 my %simdata=%{$simdataref};
  1         28  
1104 1         2 my $fh=shift;
1105 1         2 my $dataset=shift;
1106 1         3 my $warn=shift;
1107 1         2 my %exprdata=();
1108 1         2 my %keywords=();
1109 1         10 foreach my $key ( sort keys %simdata) {
1110             #make sure substitutions happen in keyword values too
1111 4 50       12 if ($key!~/^_/ ) {
1112 4 50       12 if( $simdata{$key}=~/^_/) {
1113 0         0 my $parameter=$simdata{$key};
1114 0         0 ${$keywords{$parameter}}{$key}=1;
  0         0  
1115             }
1116 4         7 next;
1117             }
1118              
1119 0 0       0 if(@{$simdata{$key}}==1) {
  0         0  
1120 0         0 $exprdata{$key}=&check_for_expressions(\%simdata,$key,$nsim);
1121 0         0 foreach my $keyword (keys %{$keywords{$key}}) {
  0         0  
1122 0         0 $simdata{$keyword}=$exprdata{$key};
1123             }
1124             } # if..else
1125             } # foreach
1126              
1127             # OPEN TEMPLATE
1128 1 50       36 open (TEMPL, "<$templfilename")||die "Can't open $templfilename\n";
1129 1         18 while (my $line = ) {
1130 17         31 foreach my $key (keys %simdata) {
1131 68 50       130 ($key!~/^_/) && next;
1132 0         0 my $ndata=@{$simdata{$key}};
  0         0  
1133 0 0       0 if($ndata>1) {
1134 0 0       0 if($line =~ s/$key(?!\w)/$simdata{$key}->[$nsim]/g){
1135             #print STDERR "# $key = ",$simdata{$key}->[$nsim],"\n" if $warn;
1136             }
1137             } else {
1138             #my $simdata=&check_for_expressions(\%simdata,$key,$nsim);
1139             #A dangerous addidtion to make SynSim handle words
1140 0   0     0 $exprdata{$key}||=$simdata{$key}->[0];
1141 0         0 $line =~ s/$key(?!\w)/$exprdata{$key}/g;
1142             #print STDERR "# $key = ",$simdata{$key}->[0],"\nLINE:$line\n" if $warn;
1143             } # if..else
1144             } # foreach
1145            
1146             # check for undefined variables
1147 17   33     48 while($line=~/\b(_\w+?)\b/&&$line!~/$1\$/) {
1148 0         0 my $nondefvar=$1;
1149 0         0 $line=~s/$nondefvar/0/g; # All undefined vars substituted by 0
1150 0 0       0 print STDERR "\nWarning: $nondefvar ($templfilename) not defined in $dataset.\n" if $warn;
1151             } # if some parameter is still there
1152 17         62 print $fh $line;
1153             } # while
1154 1         16 close TEMPL;
1155              
1156             } # END OF gen_sim_script
1157             #------------------------------------------------------------------------------
1158             sub egrep {
1159 1     1 0 5 my $pattern=shift;
1160 1         2 my $infile=shift;
1161 1         5 my $mode=shift;
1162 1         1 my $outfile=shift;
1163 1         28 open(IN,"<$infile");
1164 1         30 open(OUT,"$mode$outfile");
1165 1         46 print OUT grep /$pattern/,;
1166              
1167 1         13 close IN;
1168 1         25 close OUT;
1169             }
1170             #------------------------------------------------------------------------------
1171             sub check_for_expressions {
1172 0     0 0   my $dataref=shift;
1173 0           my $key=shift;
1174 0           my $nsim=shift;
1175 0           my %simdata=%{$dataref};
  0            
1176 0           my $expr=$simdata{$key}->[0];
1177 0 0         if($expr=~/(_[A-Z_]+)/) { # was "if"
1178 0           while($expr=~/(_[A-Z_]+)/) { # was "if"
1179             #variable contains other variables
1180             #_A =3*log(_B)+_C*10-_D**2
1181             #_A =3 ;log;_B;;_C;10;_D;;2
1182 0           my @maybevars=split(/[\ \*\+\-\/\^\(\)\[\]\{\}\?\:\=\>\<]+/,$expr);
1183 0           my @vars=();
1184 0           foreach my $maybevar ( @maybevars){
1185 0 0         ($maybevar=~/_[A-Z]+/)&& push @vars,$maybevar;
1186             }
1187 0           foreach my $var (@vars) {
1188 0 0         my $simn=(@{$simdata{$var}}==1)?0:$nsim;
  0            
1189 0           $expr=~s/$var/$simdata{$var}->[$simn]/g;
1190             }
1191             }
1192             #print STDERR "$key=$expr=>",eval($expr),"\n";
1193             }
1194 0           return eval($expr);
1195             }
1196              
1197             ################################################################################
1198             #
1199             # These routines are not used by synsim
1200             # They are used by make install
1201             #
1202             ################################################################################
1203              
1204             # Create simulation directory etc.
1205             sub setup {
1206              
1207 0     0 0   my $HOME=$ENV{HOME};
1208 0           print "Local SinSym directory? [$HOME/SynSim]:";
1209 0           my $synsimroot=;
1210 0           chomp $synsimroot;
1211 0 0         if(not $synsimroot){$synsimroot="$HOME/SynSim"}
  0            
1212 0 0         if($synsimroot!~/^\//) {
1213 0           print "The directory $synsimroot will be created in $HOME\n";
1214 0           $synsimroot="$HOME/$synsimroot"
1215             }
1216              
1217 0 0         if(not -d "$synsimroot"){
1218 0           mkdir "$synsimroot", 0755;
1219             }
1220              
1221              
1222 0           print "Simulation project directory? [SynSimProject]:";
1223 0           my $project=;
1224 0           chomp $project;
1225 0 0         if(not $project){$project='SynSimProject'}
  0            
1226              
1227              
1228 0           print "Creating $project directory structure in $synsimroot...\n";
1229 0           mkdir "$synsimroot/$project", 0755;
1230 0           mkdir "$synsimroot/$project/SOURCES", 0755;
1231 0           mkdir "$synsimroot/$project/TEMPLATES", 0755;
1232 0           mkdir "$synsimroot/$project/TEMPLATES/DEVTYPES", 0755;
1233 0           mkdir "$synsimroot/$project/TEMPLATES/SIMTYPES", 0755;
1234 0 0         if(-d "eg"){
1235 0 0         if(-e "eg/synsim"){
1236 0           system("cp eg/synsim $synsimroot/$project/synsim");
1237             }
1238 0 0         if(-e "eg/synsim.data"){
1239 0           system("cp eg/synsim.data $synsimroot/$project/synsim.data");
1240             }
1241              
1242 0 0         if(-e "eg/TEMPLATES/test.templ"){
1243 0           system("cp eg/TEMPLATES/test.templ $synsimroot/$project/TEMPLATES/");
1244             }
1245             }
1246              
1247 0           &localinstall(0,$synsimroot);
1248              
1249             } # END of setup()
1250              
1251             #------------------------------------------------------------------------------
1252              
1253             # Local Simulation::Automate (SynSim) installation
1254             sub localinstall {
1255 0   0 0 0   my $full=shift||1;
1256 0   0       my $synsimroot=shift||'';
1257              
1258 0           my $HOME=$ENV{HOME};
1259 0 0         if(not $synsimroot) {
1260 0           print "Local SinSym directory? [$HOME/SynSim]:";
1261 0           $synsimroot=;
1262 0           chomp $synsimroot;
1263 0 0         if(not $synsimroot) {$synsimroot="$HOME/SynSim"}
  0            
1264             }
1265 0 0         if(not -d "$synsimroot"){
1266 0           mkdir "$synsimroot", 0755;
1267             }
1268 0           print "Creating local SynSim directory $synsimroot/Simulation/Automate ...\n";
1269 0 0         if(not -d "$synsimroot/Simulation") {
1270 0           mkdir "$synsimroot/Simulation", 0755;
1271             }
1272 0 0         if(not -d "$synsimroot/Simulation") {
1273 0           mkdir "$synsimroot/Simulation", 0755;
1274             }
1275 0 0         if(not -d "$synsimroot/Simulation/Automate") {
1276 0           mkdir "$synsimroot/Simulation/Automate", 0755;
1277             }
1278 0 0         if(-d "Automate") {
1279 0           foreach my $module (qw(PostProcessors Dictionary)) {
1280 0 0         if( -e "Automate/$module.pm"){
1281 0           system("cp Automate/$module.pm $synsimroot/Simulation/Automate/$module.pm");
1282             }
1283             }
1284 0 0         if($full) {
1285 0           foreach my $module (qw(Remote PostProcLib Analysis)){
1286 0 0         if( -e "Automate/$module.pm"){
1287 0           system("cp Automate/$module.pm $synsimroot/Simulation/Automate/$module.pm");
1288             }
1289             }
1290 0 0         if( -e "Automate.pm"){
1291 0           system("cp Automate.pm $synsimroot/Simulation/Automate.pm");
1292             }
1293             } # if full local install
1294             } # if directory Automate exists in current dir.
1295              
1296             } # END of localinstall()
1297              
1298             ######################## User Documentation ##########################
1299              
1300              
1301             ## To format the following documentation into a more readable format,
1302             ## use one of these programs: perldoc; pod2man; pod2html; pod2text.
1303             ## For example, to nicely format this documentation for printing, you
1304             ## may use pod2man and groff to convert to postscript:
1305             ## pod2man Automate.pod | groff -man -Tps > Automate.ps
1306              
1307              
1308             =head1 NAME
1309              
1310             Simulation::Automate - A Simulation Automation Tool
1311              
1312             The set of modules is called B.
1313              
1314             The tool itself is called B, the command C.
1315              
1316             =head1 REQUIREMENTS
1317              
1318             =over 4
1319              
1320             =item * a unix-like system
1321              
1322             =item * perl 5
1323              
1324             =item * gnuplot for postprocessing (optional)
1325              
1326             =back
1327              
1328             =head1 SYNOPSIS
1329              
1330             use Simulation::Automate;
1331              
1332             &synsim();
1333              
1334             =head1 DESCRIPTION
1335              
1336             SynSim is a generic template-driven simulation automation tool. It works with any simulator that accepts text input files and generates text output (and even those that don't. See L for special cases). It executes thousands of simulations with different input files automatically, and processes the results. Postprocessing facilities include basic statistical analysis and automatic generation of PostScript plots with Gnuplot. SynSim is entirely modular, making it easy to add your own analysis and postprocessing routines.
1337              
1338             =head1 INSTALLATION
1339              
1340             =head2 1. Download and extract the archive
1341              
1342             =over 4
1343              
1344             =item 1.
1345             Download the gzipped tar file F
1346              
1347             =item 2.
1348             Extract the archive:
1349              
1350             tar -zxvf Simulation-Automate-0.9.5.tar.gz
1351              
1352             =back
1353              
1354             =head2 2. Simple local installation
1355              
1356             This installation procedure will install the Simulation::Automate modules in a directory of your choice, and create a template directory structure for your SynSim project.
1357              
1358             =over 4
1359              
1360             =item 1. Run the local install script:
1361              
1362             In the main directory of the distribution (i.e. the directory which contains the file C), type:
1363              
1364             perl local_install.pl
1365              
1366             =item 2. Enter the installation directory
1367              
1368             The install script asks for the name of the directory in which it will put SynSim:
1369              
1370             Local SinSym directory? [/local/home/wim/SynSim]:
1371              
1372             If you enter just a name, the installer assumes that the directory is in your home directory. If you want to install SynSim outside your home directory, enter a full path.
1373              
1374             =item 3. Enter the project directory name
1375              
1376             The install script asks for the name of directory where you will run SynSim:
1377              
1378             Simulation project directory? [SynSimProject]:
1379              
1380             This directory is a subdirectory of the local SynSim directory.
1381              
1382             =back
1383              
1384             That's it. Now you can go to your project directory and run the synsim script as a test:
1385              
1386             ./synsim
1387              
1388             This will run a simple test. If the installation was succesful, it will display the follwing message:
1389              
1390             SynSim Installation Test
1391            
1392             Simulation::Automate version 0.9.6
1393            
1394             installed locally in /home/wim/SynSim/Test
1395            
1396             Finished SynSim run
1397            
1398              
1399             =head2 3. Perl-style installation
1400              
1401             This is the typical Makefile.PL-driven installation procedure. It is only required for system-wide installation, but it works for local installation as well.
1402              
1403             =over
1404              
1405             =item 1.
1406             Create the Makefile:
1407              
1408             cd Simulation-Automate-0.9.5
1409             perl Makefile.PL
1410              
1411             =item 2.
1412             Make Simulation::Automate:
1413              
1414             make
1415              
1416             =item 3.
1417             Test Simulation::Automate:
1418              
1419             make test
1420              
1421             =item 4.
1422             Install Simulation::Automate:
1423              
1424             This requires you to be root:
1425              
1426             su
1427             make install
1428              
1429             or
1430              
1431             sudo make install
1432              
1433              
1434             =item 5.
1435             For a local installation
1436              
1437             This does not require you to be root:
1438              
1439             make localinstall
1440              
1441             or
1442              
1443             perl -e "use Simulation::Automate;
1444             &Simulation::Automate::localinstall();"
1445              
1446             =item 6.
1447             Setup your local SynSim project (
1448              
1449             SynSim is the name for the tool contained in Simulation::Automate. This step creates the directory structure for your simulations:
1450              
1451             make setup
1452             or
1453              
1454             perl -e "use Simulation::Automate;
1455             &Simulation::Automate::setup();"
1456              
1457             =back
1458              
1459             =head2 4. Archive structure
1460              
1461             The archive structure is as follows:
1462              
1463             README
1464             Makefile.PL
1465             Automate.pm
1466             local_install.pl
1467             Automate/
1468             Remote.pm
1469             PostProcLib.pm
1470             Analysis.pm
1471             Dictionary.pm
1472             PostProcessors.pm
1473              
1474             eg/
1475             synsim
1476             synsim.data
1477             ErrorFlags.data
1478             Histogram.data
1479             SweepVar.data
1480             Expressions.data
1481             gnuplot.data
1482             SOURCES/
1483             bufsim3.cc
1484             MersenneTwister.h
1485             TEMPLATES/
1486             test.templ
1487             DEVTYPES/
1488             SIMTYPES/
1489             bufsim3.templ
1490             PLUGINS/
1491              
1492              
1493             =head1 CONFIGURATION
1494              
1495             To configure SynSim for use with your simulator, you must create a set of files in your SynSim project directory structure. This paragraph gives an overview of the different types of files and their place in the SynSim project directory structure.
1496              
1497             =head2 SynSim project directory structure
1498              
1499             You can create a SynSim directory structure with C or C (see L for details). If you already have an existing project, you can do this:
1500              
1501             =over 4
1502              
1503             =item *
1504             Create a new project directory:
1505              
1506             mkdir NewProject
1507              
1508             =item *
1509             Copy the C script from the old project:
1510              
1511             cp oldProject/synsim NewProject
1512              
1513             =item *
1514             Go to the C directory and run C with the C<-D> option:
1515              
1516             cd NewProject
1517             ./synsim -D
1518              
1519             =back
1520              
1521             If you want to create it manually, this is the structure. Directories between square brackets are optional.
1522              
1523             YourProject/
1524             synsim
1525             YourDataFile.data
1526             [SOURCES/]
1527             TEMPLATES/
1528             YourSimTempl.templ
1529             [DEVTYPES/]
1530             [SIMTYPES/]
1531             [PLUGINS/]
1532             [Simulation/SynSim/]
1533             [Dictionary.pm]
1534             [PostProcessors.pm]
1535              
1536             The C script is the actual script that runs the DOE. It contains the 2 lines from the L.
1537             The local Simulation/Automate modules are only required if you want to customize the postprocessing.
1538            
1539             =head2 Source files
1540              
1541             The directory F is optional. It should contain all files which are required "read-only" by your simulator (e.g. header files, library files, wrappers).
1542              
1543             =head2 Template files
1544              
1545             Template files are files in which simulation variables will be substituted by their values to create the input file for your simulator. They must be stored in the F directory, and have by convention the extension C<.templ>.
1546              
1547             B
1548              
1549             The template file format is free, but the variables to be substituted by SynSim I be in uppercase and start with an underscore:
1550              
1551             Examples:
1552              
1553             _VAR1
1554             _LONG_VARIABLE_NAME
1555              
1556             To create a template file, start from an existing input file for your simulator. Replace the values of the variables to be modified by SynSim by a SynSim variable name (e.g.
1557             var1 = 2.5 => var1 = _VAR1). Put the template files in F.
1558              
1559              
1560             B Relative paths to source files
1561              
1562             SynSim creates a run directory ath the same level as the SOURCES and TEMPLATES directories. All commands (compilations etc.) are executed in that directory. As a consequence, paths to source files (e.g. header files) should be "C<../SOURCES/>I".
1563              
1564             B The F and F subdirectories
1565              
1566             SynSim can create an input file by combining two different template files, generally called device templates and simulation templates. This is useful in case you want to run different types of simulations on different devices, e.g. DC analysis, transient simulations, small-signal and noise analysis on 4 different types of operational amplifiers. In total, this requires 16 different input files, but only 8 different template files (4 for the simulation type, 4 for the device types). If you want to use this approach, device templates should go in F and simulation templates in F.
1567             SynSim will check both directories for files as defined in the datafile. If a matching file is found in F, it will be prepended to the simulation template from F.
1568              
1569             =head2 Datafile
1570              
1571             The datafile is the input file for C. It contains the list of simulation variables and their values to be substituted in the template files, as well as a number of configuration variables. See L for more information.
1572              
1573             =head2 Postprocessing and Preprocessing (optional)
1574              
1575             The F module contains routines to perform postprocessing on the simulation results (e.g. plotting, statistical analysis, etc). A number of generic routines are provided, as well as a library of functions to make it easier to develop your own postprocessing routines. See L for a full description).
1576              
1577             Before the raw data are sent to the postprocessor, it is possible (and very easy) to preprocess the raw data. See L for more details.
1578              
1579             Custom postprocessing and preprocessing routines can either be stored in the F directory (preferred) or directly in the local F module (more intended for modified versions of the generic routines).
1580              
1581             =head2 Dictionary (optional)
1582              
1583             The F module contains descriptions of the parameters used in the simulation. These descriptions are used by the postprocessing routines to make the simulation results more readable. See L for a full description).
1584              
1585             =head1 DATAFILE DESCRIPTION
1586              
1587             The datafile defines which simulations to run, with which parameter values to use, and how to run the simulation. By convention, it has the extension C<.data>.
1588              
1589             =head2 Syntax
1590              
1591             The datafile is a case-sensitive text file with following syntax:
1592              
1593             =over 4
1594              
1595             =item Comments and blanks
1596              
1597             Comments are preceded by '#'.
1598             Comments, blanks and empty lines are ignored
1599              
1600             =item Parameters
1601              
1602             Parameters (simulation variables) are in UPPERCASE with a leading '_', and must be separated from their values with a '='.
1603              
1604             =item Keywords
1605              
1606             Keywords (configuration variables) are in UPPERCASE, and must be separated from their values with a ':'.
1607              
1608             =item Lists of values
1609              
1610             Lists of values have one or more items. The list separator is a comma ','.
1611              
1612             Example:
1613              
1614             _PAR1 = 1,1,2,3,5,8,13
1615              
1616             If a list has 3 elements START,STOP,STEP, then if possible this list will be expanded as a for-loop from START to STOP with step STEP.
1617              
1618             Example:
1619              
1620             _NBUFS = 16,64,8 # from 16 to 64 in steps if 8: 16,24,32,40,48,56,64
1621              
1622             =item Section headers for multiple simulation types (optional)
1623              
1624             These must be lines containing only the simulation type
1625              
1626             =back
1627              
1628             =head2 Simulation variables
1629              
1630             The main purpose of the datafile is to provide a list of all variables and their values to be substituted in the template files.
1631              
1632             =over 4
1633              
1634             =item Default behaviour: combine values
1635              
1636             A simulation will be performed for every possible combination of the values for all parameters.
1637              
1638             Example:
1639              
1640             _PAR1 = 1,2
1641             _PAR2 = 3,4,5
1642              
1643             defines 6 simulations: (_PAR1,_PAR2)=(1,3),(1,4),(1,5),(2,3),(2,4),(2,5)
1644              
1645             Simulation results for all values in ','-separated list are stored in a separate files.
1646              
1647              
1648             =item Alternative behaviour: group values
1649              
1650             It is possible (See the keyword B under L) to define groups of variables. For every parameter in a group, the value list must have the same number of items. The values of all variables at the same position in the list will be used.
1651              
1652             Example:
1653              
1654             GROUP: _PAR1,_PAR2
1655              
1656             _PAR1 = 0;1;2;4
1657             _PAR2 = 3;4;5;6
1658              
1659             defines 4 simulations: (_PAR1,_PAR2)=(0,3);(1,4);(2,5);(4,6)
1660              
1661             =back
1662              
1663             =head2 Configuration variables
1664              
1665             A number of configuration variables ("keywordsw) are provided to configure SynSim's behaviour. There is no mandatory order, but they must appear before the simulation variable. For the default order, see the L.
1666             In alphabetical order, they are:
1667              
1668             =over 4
1669              
1670              
1671             =item ANALYSIS
1672              
1673             B ANALYSIS_TEMPLATE, ANATEMPL
1674              
1675             Name of the routine to be used for the result analysis (postprocessing). This routine must be defined in PostProcessors.pm or in a file in the F directory. A number of generic routines are provided, see L.
1676              
1677             =item COMMAND
1678              
1679             The command line for the program that runs the input file, i.e. the simulator command (default: perl). SynSim looks for the words B and and substitutes them with the actual file names.
1680              
1681             Examples:
1682              
1683             yoursim1 -i INPUTFILE -o OUTPUTFILE
1684             yoursim2 INPUTFILE > OUTPUTFILE
1685              
1686             =item DEVTYPE (optional)
1687              
1688             The name of the device on which to perform the simulation. If defined, SynSim will look in TEMPLATES/DEVTYPES for a file with TEMPL and DEVTYPE, and prepend this file to the simulation template before parsing. This keyword can take a list of values
1689              
1690             =item EXT
1691              
1692             Extension of input file (default: .pl)
1693              
1694             Some simulators expect a particular extension for the input file. This can be specified with the keyword B.
1695              
1696             =item GROUP (optional)
1697              
1698             This keyword can be used to change the default behaviour of creating nested loops for every parameter.
1699             It takes as argument a list of parameters. The behaviour for grouped parameters is to change at the same time. All parameter lists in the group must have the same number of values. More than one group can be created.
1700              
1701             Example:
1702              
1703             # First group: 2 parameters, each 4 values
1704             GROUP: _PAR_A1,_PAR_A2
1705             # Second group: 3 parameters, each 3 values
1706             GROUP: _PAR_B1,_PAR_B2,_PAR_B3
1707             # SynSim will run 4*3 simulations (default without groups would be 16*27)
1708              
1709             _PAR_A1 = 0;1;2;4
1710             _PAR_A2 = 3;4;5;6
1711              
1712             _PAR_B1 = -1;1;2
1713             _PAR_B2 = 3;4;7
1714             _PAR_B3 = 3;6;15
1715              
1716             =item INCLUDE (optional)
1717              
1718             If the value of INCLUDE is an exisiting filename, this datafile will be included on the spot.
1719              
1720             =item NORMVAR (optional)
1721              
1722             The name of the variable to normalise the results with. The results will be divided by the corresponding value of the variable.
1723              
1724             =item NRUNS (optional)
1725              
1726              
1727             =item OUTPUT_FILTER_PATTERN (optional)
1728              
1729             A Perl regular expression to filter the output of the simulation (default : .*). Tis is very usefull for very verbose simulators. The results file will only contain the filtered output.
1730              
1731             =item PREPROCESSOR (optional)
1732              
1733             The name of a function which modifies C<@results> before the actual postprocessing. Very usefull to "streamline" the raw results for postprocessing.
1734              
1735             =item TEMPLATE
1736              
1737             B SIMULATION, SIMTEMPL, SIMTYPE
1738              
1739             The name of the template file, with or without extension. By convention, this is the same as the type of simulation to be performed. If no extension is given, SynSIm checks for a B keyword; if this is not defined, the extenstion defaults to C<.templ>. SynSim will look for the template file in F and F.
1740              
1741             B Multiple simulation types
1742              
1743             The value of SIMULATION can be a ','-separated list. In this case, SynSim will use the datafile for multiple types of simulations. Every item in the list can be used as a section header, demarkating a section with variables particular to that specific simulation.
1744              
1745             =item TEMPLEXT (optional)
1746              
1747             Extension of template files (default: C<.templ>)
1748              
1749             =item TITLE
1750              
1751             The title of the DOE. This title is used on the plots, but typically it is the first line of the datafile and describes the DOE.
1752              
1753             =item XVAR (optional)
1754              
1755             B SWEEPVAR
1756              
1757             The name of the variable to be sweeped. Mandatory if the postprocessing routine is XYPlot.
1758              
1759             The number of times the simulation has to be performed. For statistical work.
1760              
1761             =item XCOL (optional)
1762              
1763             The column in the output file which contains the X-values.
1764              
1765             =item YCOL (optional)
1766              
1767             B DATACOL
1768              
1769             The column in the output file which contains the simulation results (default: 2). Mandatory if using any of the generic postprocessing routines.
1770              
1771             =item XLABEL, YLABEL, LOGSCALE, PLOTSTYLE, XTICS, YTICS, XSTART, XSTOP, YSTART, YSTOP (optional)
1772              
1773             Variables to allow more flexibility in the customization of the plots. They are identical to the corresponding (lowercase) C keywords, see the gnuplot documentation for details. The most commonly used, XLABEL and YLABEL are the X and Y axis labels. LOGSCALE is either X, Y or XY, and results in a logarithmic scale for the chosen axis.
1774              
1775             =back
1776              
1777             =head2 Expressions
1778              
1779             The SynSim datafile has support for expressions, i.e. it is possible to express the value list of a variable in terms of the values of other variables.
1780              
1781             Example:
1782              
1783             # average packet length for IP dist
1784             _MEANPL = ((_AGGREGATE==0)?2784:9120)
1785             # average gap width
1786             _MEANGW= int(_MEANPL*(1/_LOAD-1))
1787             # average load
1788             _LOAD = 0.1;0.2;0.3;0.4;0.5;0.6;0.7;0.8;0.9
1789             # aggregate
1790             _AGGREGATE = 0,12000
1791              
1792             The variables used in the expressions must be defined in the datafile, although not upfront. Using circular references will not work.
1793             The expression syntax is Perl syntax, so any Perl function can be used. Due to the binding rules, it is necessary to enclose expressions using the ternary operator ?: with brackets (see example).
1794              
1795             =head1 RUNNING SYNSIM
1796              
1797             The SynSim script must be executed in a subdirectory of the SynSim
1798             directory which contains the TEMPLATES subdir and the datafile (like the Example directory in the distribution).
1799              
1800             The command line is as follows:
1801              
1802             ./synsim [-h -D -i -p -P -v -N ] [datafile] [remote hostname]
1803              
1804             The C script supports following command line options:
1805              
1806             none: defaults to -f synsim.data
1807             -D : Create an empty SynSim directory structure in the current directory.
1808             -v : 'verbose'. Sends simulator output to STDOUT
1809             -i : interactive. Calls gv or ggv to display a plot of the results.
1810             Implies -p -v.
1811             -p : plot. This enables generation of postscript plots via gnuplot.
1812             A postprocessing routine is required to generate the plots.
1813             -P : Plot. This option can be used to display plots created with -p.
1814             -w : 'warnings'. Show warnings about undefined variables.
1815             -N : 'No simulations'. Performs only postprocessing.
1816             -h, -? : short help message
1817              
1818             If [remote hostname] is provided, SynSim will try to run the simulation on the remote host.
1819              
1820             The current implementation requires:
1821              
1822             -ssh access to remote host
1823              
1824             -scp access to remote host
1825              
1826             -rsync server on the local host
1827              
1828             -or,alternatively, an NFS mounted home directory
1829              
1830             -as such, it will (probably) only work on Linux and similar systems
1831              
1832              
1833             =head1 POSTPROCESSING
1834              
1835             Postprocessing of the simulation results is handled by routines in the C module. This module uses the C and optionally C and C.
1836              
1837             =head2 Generic Postprocessors
1838              
1839             SynSim comes with a number of generic postprocessing routines.
1840              
1841             =over 4
1842              
1843             =item XYPlot
1844              
1845             Required configuration variables: C
1846              
1847             Creates a plot using C as X-axis and all other variables as parameters. This routine is completely generic.
1848              
1849             =item CondXYPlot
1850              
1851             Required configuration variables: C,C and C.
1852              
1853             Creates a plot using C as X-axis; C is checked against the condition C (or C). The first value of C that meets the condition is plotted. All other variables are parameters. This routine is completely generic.
1854              
1855             =item XYPlotErrorBars
1856              
1857             Required configuration variables: C, C
1858              
1859             Optional configuration variables: C
1860              
1861             Creates a plot using C as X-axis and all other variables as paramters. Calculates average and 95% confidence intervals for C simulation runs and plots error flags. This routine is fully generic, the confidence interval (95% by default) can be set with NSIGMAS. See eg/ErrorFlags.data for an example datafile.
1862              
1863             =item Histogram
1864              
1865             Required configuration variables: C
1866              
1867             Optional configuration variables: C, C, C
1868              
1869             Creates a histogram of the simulation results. This requires the simulator to produce raw data for the histograms in a tabular format. When specifying logscale X or XY for the plot, the histogram bins will be logarithmic. See eg/Histogram.data for an example.
1870             The number of bins in the histogram must be specified via C. The width of the bins can be set with C, in which case C and C will be calculated. When C or C are set, C is calculated. It is possible to specify either C or C, the undefine value will be calculated.
1871              
1872             =back
1873              
1874             =head2 Preprocessing the raw results
1875              
1876             All of the above routines have hooks for simple functions that modify the C<@results> array. To call these functions, include them in the datafile with the C variable. e.g:
1877              
1878             PREPROCESSOR : modify_results
1879              
1880             All functions must be put in the PLUGINS folder or in the PostProcessors.pm module, and the template could be like this:
1881              
1882             sub modify_results {
1883             foreach my $results_line (@results) {
1884             #Do whatever is required
1885             }
1886            
1887             } # End of modify_results
1888              
1889             =head1 DICTIONARY
1890              
1891             The F module contains descriptions of the parameters used in the simulation. These descriptions are used by the postprocessing routines to make the simulation results more readable. The dictionary is stored in an associative array called C. The description of the variable is stored in a field called 'title'; Descriptions of values are stored in fields indexed by the values.
1892              
1893             Following example illustrates the syntax:
1894              
1895             # Translate the parameter names and values into something meaningful
1896             %Dictionary::make_nice=(
1897            
1898             _BUFTYPE => {
1899             title=>'Buffer type',
1900             0=>'Adjustable',
1901             1=>'Fixed-length',
1902             2=>'Multi-exit',
1903             },
1904             _YOURVAR1 => {
1905             title=>'Your description for variable 1',
1906             },
1907            
1908             _YOURVAR2 => {
1909             title=>'Your description for variable 2',
1910             'val1' => 'First value of _YOURVAR2',
1911             'val3' => 'Second value of _YOURVAR2',
1912             },
1913              
1914             );
1915              
1916             =head1 OUTPUT FILES
1917              
1918             SynSim creates a run directory C<{SIMTYPE}->I<[datafile without .data]>. It copies all necessary template files and source files to this directory; all output files are generated in this directory.
1919              
1920             SynSim generates following files:
1921              
1922             =over 4
1923              
1924             =item *
1925              
1926             Output files for all simulation runs.
1927              
1928             The names of these files are are C<{SIMTYPE}_C>I<[counter]_[simulation number]>C<.out>
1929              
1930             I is increased with every new combination of variables except for C.
1931              
1932             I is the position of the value in the C- list.
1933              
1934             =item *
1935              
1936             Combined output file for all values in a ';'-separated list.
1937              
1938             The names of these files are are C<{SIMTYPE}_C>I<[counter]>C<_.out>
1939              
1940             I is increased with every new combination of variables in ','-separated lists.
1941              
1942             Only the lines matching C (treated as a Perl regular expression) are put in this file.
1943              
1944             =item *
1945              
1946             Combined output file for all values in a ';'-separated list, with a header detailing all values for all variables.
1947              
1948             The names of these files are are C<{SIMTYPE}_C>I<[counter]>C<.res>,
1949              
1950             I is increased with every new combination of variables in ','-separated lists.
1951              
1952             Only the lines in the C<.out> files matching C (treated as a Perl regular expression) are put in this file.
1953              
1954              
1955             =item *
1956              
1957             Separate input files for every item in a ';'-separated list.
1958              
1959             The names of these files are are C<{SIMTYPE}_>I<[simulation number]>C<.{EXT}>
1960              
1961             I is the position of the value in the list.
1962              
1963             These files are overwritten for every combination of variables in ','-separated lists.
1964              
1965             =back
1966              
1967              
1968             =head1 WRITING POSTPROCESSING ROUTINES
1969              
1970             In a lot of cases you will want to create your own postprocessing routines. First of all, it is important to understand the SynSim output, so make sure you have read L. Apart from that, there is a very simple API.
1971              
1972             =head2 PostProcLib
1973              
1974             =over
1975              
1976             =item *
1977             All variables from the datafile are exported in a hash called C<%simdata>
1978              
1979             The value list for every variable is a Perl list. This means that you can access the values like this:
1980              
1981             my @importantvars = @{$simdata{_VAR1}}
1982              
1983             or
1984              
1985             my $importantvar = $simdata{_VAR1}[0]
1986              
1987             The same holds for configuration variables, but in general they only have a single value, so:
1988              
1989             my $x_variable = $simdata{XVAR}
1990              
1991             =item *
1992             Easy-typing names
1993              
1994             Furthermore, every variable can be accessed using a short name. Instead of
1995              
1996             $simdata{_VAR}
1997              
1998             you can use
1999              
2000             $_var
2001              
2002             This is especially handy for configuration variables, e.g.
2003              
2004             $plotstyle
2005              
2006             instead of
2007              
2008             $simdata{PLOTSTYLE}
2009              
2010             =item *
2011             Current set of values for the DOE
2012              
2013             The current set of values for the DOE is available in the hash C<%current_set_vals>. The keys are the variable names, the values the current value for the variable.
2014              
2015             Example: A simple DOE with 2 variables.
2016              
2017             _VAR1=1,2,3
2018             _VAR2=3,4
2019              
2020             This DOE has 6 sets. After the fourth run, the values of the set will be:
2021              
2022             $current_set_vals{_VAR1}==2
2023             $current_set_vals{_VAR1}==4
2024              
2025             The current set is also available in string format through C<$current_set_str>:
2026              
2027             $current_set_str eq '_VAR1-2-_VAR2-4'
2028              
2029             This is useful because this string is part of the name of the results file.
2030              
2031             If the configuration variable C is defined, there is an additional string C<$current_set_except_setvar_str>, which contains the current set except the C. This is usefull for conditional postprocessing, see e.g. CondXYPlot in PostProcessors.pm.
2032              
2033             =item *
2034             Raw results
2035              
2036             The raw results of the last simulation run are available in the array C<@results>. Every element in this array is identical to the corresponding line in the output file for the given simulation run.
2037              
2038             It is also possible to access the results files: C<$results_file_name> contains the filename of the current results file, and C<@all_results_file_names> is a list of all results files so far.
2039              
2040             =item *
2041             Deciding when to call the postprocessor.
2042              
2043             SynSim allows to call your postprocessing routine after every run. However, postprocessing generally only makes sense at certain points in the execution of the DOE. SynSim provide two variables: C<$last>, which indicates the end of a sweep, C<$verylast> which indicates the end of the DOE.
2044              
2045             =back
2046              
2047             In summary, following variables are exported:
2048              
2049             %simdata # contains all datafile variables
2050             #and their values/value lists
2051             @results # memory image of the results file
2052             %current_set_vals # values for the current set
2053             $current_set_str # same in string format
2054             $current_set_except_setvar_str
2055             $results_file_name
2056             @all_results_file_names
2057             $last # indicates end of a sweep
2058             $verylast # indicates end of the DOE
2059              
2060             An example of how all this is used:
2061              
2062             sub YourRoutine {
2063            
2064             ## Define your own variables.
2065             ## As every variable can have a list of values,
2066             ## $simdata{'_YOURVAR1'} is an array reference.
2067            
2068             my $yourvar=${$simdata{'_YOURVAR1'}}[0];
2069            
2070             my @sweepvarvals=@{$simdata{$sweepvar}};
2071            
2072             ## $verylast indicates the end of all simulations
2073             if(not $verylast) {
2074            
2075             ## what to do for all simulations
2076            
2077             ## $last indicates the end of a sweep
2078             if($last) {
2079             # Do something at the end of every sweep
2080             } # if last
2081             } else {
2082             ## On the very last run, collect the results into one nice plot
2083             &gnuplot_combined($firstplotline,$plotlinetempl);
2084             }
2085            
2086             } #END of YourRoutine()
2087              
2088              
2089             =head2 Statistical analysis
2090              
2091             A module for basic statistical analysis is also available (C). Currently, the module provides 2 routines:
2092              
2093             =over 4
2094              
2095             =item calc_statistics():
2096              
2097             To calculate average, standard deviation, min. and max. of a set of values.
2098              
2099             Arguments:
2100              
2101             C<$file>: name of the results file. The routine requires the data to be in whitespace-separated columns.
2102              
2103             C<$par>: Determines if the data will be differentiated before processing ($par='DIFF') or not (any other value for $par).
2104             Differentiation is defined as subtracting the previous value in the
2105             array form the current value. A '0' is prepended to the array to avoid
2106             an undefined first point.
2107              
2108             C<$datacol>: column to use for data
2109              
2110             C<$title>: optional, a title for the histogram
2111              
2112             C<$log>: optional, log of values before calculating histogram or not ('LOG' or '')
2113              
2114              
2115             Use:
2116             my $file="your_results_file.res";
2117             my $par='YOURPAR';
2118             my $datacol=2;
2119             my %stats=%{&calc_statistics($file,[$par, $datacol])};
2120              
2121             my $avg=$stats{$par}{AVG}; # average
2122             my $stdev=$stats{$par}{STDEV}; # standard deviation
2123             my $min=$stats{$par}{MIN}; # min. value in set
2124             my $max=$stats{$par}{MAX}; # max. value in set
2125              
2126             =item build_histograms():
2127              
2128             To build histograms. There are 3 extra arguments:
2129              
2130             $nbins: number of bins in the histogram
2131             $min: force the value of the smallest bin (optional)
2132             $max: force the value of the largest bin (optional)
2133              
2134             use:
2135             my $par='DATA';
2136             my %hists=%{&build_histograms("your_results_file.res",
2137             [$par,$datacol],$title,$log,$nbins,$min,$max)};
2138              
2139             NOTE: Because the extra arguments are last, the $title and $log arguments can not be omitted. If not needed, supply ''.
2140              
2141             =back
2142              
2143             =head1 EXAMPLES
2144              
2145             Here are some examples of how to use SynSim for different types of simulators.
2146              
2147             =head2 1. Typical SPICE simulator
2148              
2149             Normal use: spice -b circuit.sp > circuit.out
2150              
2151             With SynSim:
2152              
2153             =over 4
2154              
2155             =item 1. Create a template file
2156              
2157             Copy circuit.sp to TEMPLATES/SIMTYPE/circuit.templ
2158             Replace all variable values with SynSim variable names.
2159              
2160             e.g. a MOS device line in SPICE:
2161              
2162             M1 VD VG VS VB nch w=10u l=10u
2163              
2164             becomes
2165              
2166             M1 VD VG VS VB _MODEL w=_WIDTH l=_LENGTH
2167              
2168             =item 2. Create a data file (e.g. circuit.data)
2169              
2170             TITLE: MOS drain current vs. length
2171             SIMTYPE : circuit
2172             COMMAND : spice -b inputfile > outputfile
2173              
2174             # Required for postprocessing
2175             OUTPUT_FILTER_PATTERN : Id # keep only the drain current on the output file
2176             ANALYSIS_TEMPLATE : SweepVar # default template for simple sweep
2177             SWEEPVAR : _L # we sweep the length, the other variables are parameters
2178             DATACOL: 2 # first col is the name
2179              
2180             _L = 1u,2u,5u,10u,20u,50u
2181             _W = 10u,100u
2182             _MODEL = nch
2183              
2184             There are more possible keywords, cf. L.
2185              
2186             =item 3. Now run synsim
2187              
2188             ./synsim -p -i -v -f IDvsL.data
2189              
2190             -p to create plots
2191             -i means interactive, so the plots are displayed during simulation
2192             -v for verbose output
2193             -f because the filename is not the default name
2194              
2195             SynSim will run 12 SPICE simulations and produce 1 plot with all results.
2196              
2197             =item 4. Results
2198              
2199             All results are stored in the run directory, in this case:
2200              
2201             circuit-IDvsL
2202              
2203             =back
2204              
2205             =head2 2. Simulator with command-line input and fixed output file
2206              
2207             Normal use: simplesim -a50 -b100 -c0.7
2208              
2209             Output is saved in out.txt.
2210              
2211             With SynSim:
2212              
2213             =over 4
2214              
2215             =item 1. Create a template file
2216              
2217             As simplesim does not take an input file, we create a wrapper simplesim.templ in TEMPLATES/SIMTYPE.
2218             This file is actually a template for a simple perl script:
2219              
2220             system("simplesim -a_VAR1 -b_VAR2 -c_VAR3");
2221             system("cp out.txt $ARGV[0]");
2222              
2223             =item 2. Create a data file (e.g. test.data)
2224              
2225             TITLE: simplesim test
2226             SIMTYPE : simplesim
2227             COMMAND : perl inputfile outputfile
2228              
2229             =item 3. Now run synsim
2230              
2231             ./synsim -f test.data
2232              
2233             SynSim will run without any messages and produce no plots.
2234              
2235             =item 4. Results
2236              
2237             All results are stored in the run directory, in this case:
2238              
2239             simplesim-test
2240              
2241             =back
2242              
2243             =head2 3. Simulator without input file, configured at compile time
2244              
2245             Normal use: Modify values for #if and #ifdef constants in the header file; then compile and run.
2246              
2247             e.g.:
2248              
2249             vi bufsim3.h
2250             g++ -o bufsim3 bufsim3.cc
2251             ./bufsim3 > outputfile
2252              
2253             With SynSim:
2254              
2255             =over 4
2256              
2257             =item 1. Put the source code (bufsim3.cc) in SOURCES
2258              
2259             =item 2. Create a template file
2260              
2261             As bufsim3 does not take an input file, we create a wrapper bufsim3.templ in TEMPLATES/SIMTYPE.
2262             This file is actually a template for a perl script that writes the header file, compiles and runs the code:
2263              
2264             open(HEADER,">bufsim3.h");
2265             print HEADER <<"ENDH";
2266             #define NBUFS _NBUFS
2267             #define NPACKETS _NPACK
2268             #AGGREGATE _AGGREGATE
2269             ENDH
2270             close HEADER;
2271              
2272             system("g++ -o bufsim3 bufsim3.cc");
2273             system("./bufsim3 $ARGV[0]");
2274              
2275             =item 3. Create a datafile (e.g. Aggregate.data)
2276              
2277             TITLE: bufsim3 test (_NBUFS, _NPACK) # will be substituted by the values
2278             SIMTYPE : bufsim3
2279             COMMAND : perl inputfile outputfile
2280              
2281             =item 4. Run synsim
2282              
2283             ./synsim -w -v -f Aggregate.data
2284              
2285             SynSim will run verbose and flag all variables not defined in the datafile.
2286              
2287             =item 4. Results
2288              
2289             All results are stored in the run directory, in this case:
2290              
2291             bufsim3-Aggregate
2292              
2293             =back
2294              
2295             =head2 4. Circuit simulator which produces binary files.
2296              
2297             Normal use: spectre circuit.scs -raw circuit.raw
2298              
2299             With SynSim:
2300              
2301             =over 4
2302              
2303             =item 1. Create a template file
2304              
2305             Copy circuit.scs to TEMPLATES/SIMTYPE/circuit.templ
2306             Replace all variable values with SynSim variable names.
2307              
2308             =item 2. Create a data file
2309              
2310             The .raw file is a binary file, so it should not be touched. SynSim creates output files with extension .out, and combines these with the headers etc. (cf. L). By keeping the extension .raw, the simulator output files will not be touched.
2311              
2312             In the datafile:
2313              
2314             TITLE: Spectre simulation with SPF output
2315             EXT: .scs
2316             COMMAND: spectre inputfile -raw outputfile.raw > outputfile
2317              
2318             =item 3. Run synsim
2319              
2320             SynSim will process C, but not C.
2321              
2322             =item 4. Postprocessing
2323              
2324             To access the binary files, you will have to write your own postprocessing routines. Most likely they will rely on an external tool to process the binary data. The files will be found in the run directory, and have names as described in L, with the extra extension .raw.
2325              
2326             =back
2327              
2328             =head1 WRAPPERS
2329              
2330             If the simulator command line does not follow the format required by SynSim, a simple shell or perl wrapper is enough to make SynSim understand it.
2331             The wrapper script must be stored under F; it should be written such that all relative paths are correct when it is executed under F. That is because SynSim runs in a subdirectory fo the project directory. This means that, if the command line contains relative paths to a subdirectory, these paths must be prepended with '../'.
2332              
2333             =head2 1. No is wrapper required if the simulator takes input from a file with an arbitrary name and sends output in any way to a file with an arbitrary name:
2334              
2335             $ simulator INPUTFILE OUTPUTFILE
2336             $ simulator --o OUTPUTFILE INPUTFILE
2337             $ simulator -i INPUTFILE > OUTPUTFILE
2338             $ simulator < INPUTFILE > OUTPUTFILE
2339              
2340             =head2 2. Simulators with fixed input file name:
2341              
2342             Example:
2343              
2344             $ simulator sim.conf > sim.out
2345              
2346             Wrapper:
2347              
2348             $ simulator_wrapper.sh INPUTFILE > OUTPUTFILE
2349              
2350             The file C contains 2 lines:
2351            
2352             mv $1 sim.conf
2353             simulator sim.conf
2354              
2355             =head2 3. Simulator with a fixed output file name:
2356              
2357             Example:
2358              
2359             $ simulator INPUTFILE
2360              
2361             The outputfile is called C.
2362              
2363             Wrapper:
2364              
2365             $ simulator_wrapper.sh INPUTFILE OUTPUTFILE
2366              
2367             The file C contains 2 lines:
2368            
2369             simulator $1
2370             mv output.txt $2
2371              
2372             =head2 4. Simulator takes input file from a subdirectory
2373              
2374             Example:
2375              
2376             $ simulator ../Config/INPUTFILE > OUTPUTFILE
2377              
2378             The F directory is in this case at the same level of project directory.
2379              
2380             Wrapper:
2381            
2382             $ simulator_wrapper.sh INPUTFILE > OUTPUTFILE
2383              
2384             The file C contains 2 lines. Note the '../' prepended to the paths:
2385            
2386             cp $1 ../../Config
2387             simulator ../../Config/INPUTFILE
2388              
2389             =head2 5. Simulator produces output in a subdirectory
2390              
2391             Example:
2392              
2393             $ simulator INPUTFILE OUTPUTFILE
2394              
2395             The C is generated in the F subdirectory.
2396              
2397             Wrapper:
2398              
2399             $ simulator_wrapper.sh INPUTFILE OUTPUTFILE
2400              
2401             The file C contains 2 lines. Note the '../' prepended to the path:
2402            
2403             simulator $1 $2
2404             cp ../Results/$2 .
2405              
2406             =head2 6. Simulator with command-line input and fixed output file
2407              
2408             $ simulator -a50 -b100 -c0.7
2409              
2410             Output is saved in out.txt.
2411              
2412             In this case, there is no actual wrapper script. We will create a simple shell script simulator.templ in TEMPLATES/. This script will act as the input file.
2413              
2414             Wrapper:
2415              
2416             $ bash INPUTFILE OUTPUTFILE
2417              
2418             We need the explicit call to bash because the INPUTFILE does not have the -x flag set.
2419              
2420             The file simulator.templ in TEMPLATES/ contains 2 lines:
2421            
2422             simulator -a_VAR1 -b_VAR2 -c_VAR3
2423             cp out.txt $1
2424              
2425             SynSim will create simulator.sh from this template file, and then will call bash to execute this shell script.
2426              
2427             =head2 7. Simulator requires multiple input files
2428              
2429             Example:
2430              
2431             $ simulator config.in topo.in > out.res
2432              
2433             Wrapper:
2434              
2435             $ perl INPUTFILE OUTPUTFILE
2436              
2437             Again, there is no actual wrapper script. The C template is in this case a perl script which contains itself templates for both input files. The script will create both input files, then run the simulator.
2438              
2439             A possible implementation of simulator.templ:
2440              
2441             #!/usr/bin/perl
2442             #Template for simulator with multiple input files
2443             my $config_templ=<<"ENDCONF";
2444             /* This is the config.in template */
2445             int var1 = _VAR1;
2446              
2447             ...
2448              
2449             ENDCONF
2450              
2451             my $topo_templ=<<"ENDTOPO";
2452             ;;This is the topo.in template
2453             var2 = _VAR2
2454              
2455             ...
2456              
2457             ENDTOPO
2458              
2459             open CONF,">config.in";
2460             print CONF $config_templ;
2461             close CONF;
2462              
2463             open TOPO, ">topo.in";
2464             print TOPO $topo_templ;
2465             close TOPO;
2466              
2467             system("simulator config.in topo.in > $ARGV[0]");
2468            
2469             #END of simulator.templ
2470              
2471             SynSim will create C and then will call C to run the script
2472              
2473             =head1 TO DO
2474              
2475             This module is still Alpha, a lot of work remains to be done to make it more user-friendly. The main tasks is to add a GUI. A prototype can be found on my web site, it is already useful but too early to include here. The next version will also make it easier to create your own postprocessing routines.
2476              
2477             =head1 AUTHOR
2478              
2479             Wim Vanderbauwhede
2480              
2481             =head1 COPYRIGHT
2482              
2483             Copyright (c) 2000,2002-2003 Wim Vanderbauwhede. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
2484              
2485             =head1 SEE ALSO
2486              
2487             gnuplot L
2488              
2489             =cut