[Tinyos-beta-commits] CVS: tinyos-1.x/beta/TOSSIM-CC2420/PowerTOSSIM README, NONE, 1.1 avr_cycle_counts.txt, NONE, 1.1 bb2asm.pl, NONE, 1.1 bb2cycle.pl, NONE, 1.1 cilly.asm.exe, NONE, 1.1 compile.pl, NONE, 1.1 counter.ml, NONE, 1.1 cpuprof.py, NONE, 1.1 fixnames.pl, NONE, 1.1 mica2_energy_model.txt, NONE, 1.1 msp430_cycle_counts.txt, NONE, 1.1 msp_cpuprof.py, NONE, 1.1 mypp.pl, NONE, 1.1 postprocess.py, NONE, 1.1 telosA_energy_model.txt, NONE, 1.1 telosB_energy_model.txt, NONE, 1.1

Yang overbored at users.sourceforge.net
Sat Mar 12 23:23:12 PST 2005


Update of /cvsroot/tinyos/tinyos-1.x/beta/TOSSIM-CC2420/PowerTOSSIM
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27290/PowerTOSSIM

Added Files:
	README avr_cycle_counts.txt bb2asm.pl bb2cycle.pl 
	cilly.asm.exe compile.pl counter.ml cpuprof.py fixnames.pl 
	mica2_energy_model.txt msp430_cycle_counts.txt msp_cpuprof.py 
	mypp.pl postprocess.py telosA_energy_model.txt 
	telosB_energy_model.txt 
Log Message:
Added support for PowerTOSSIM, including MSP430 CPU cycle counting.
Added specific support for Telos Revision A and B.
Updated the HPL to support starting/stopping.



--- NEW FILE: README ---
This directory contains various scripts for PowerTOSSIM, a power
simulation addon to TOSSIM.  See
http://www.eecs.harvard.edu/~shnayder/ptossim/ for details and/or
email shnayder at eecs.harvard.edu if you have questions.


--- NEW FILE: avr_cycle_counts.txt ---
add	1
adc	1
adiw	2
sub	1
subi	1
sbc	1
sbci	1
sbiw	2
and	1
andi	1
or	1
ori	1
eor	1
com	1
neg	1
sbr	1
cbr	1
inc	1
dec	1
tst	1
clr	1
ser	1
mul	2
muls	2
mulsu	2
fmul	2
fmuls	2
fmulsu	2
rjmp	2
ijmp	2
eijmp	2
jmp	3
rcall	3.5
icall	3.5
eicall	4
call	4.5
ret	4.5
reti	4.5
cpse	2
cp	1
cpc	1
cpi	1
sbrc	2
sbrs	2
sbic	2
sbis	2
brbs	1.5
brbc	1.5
breq	1.5
brne	1.5
brcs	1.5
brcc	1.5
brsh	1.5
brlo	1.5
brmi	1.5
brpl	1.5
brge	1.5
brlt	1.5
brhs	1.5
brhc	1.5
brts	1.5
brtc	1.5
brvs	1.5
brvc	1.5
brie	1.5
brid	1.5
mov	1
movw	1
ldi	1
lds	2
ld	2
ld	2
ld	2
ld	2
ld	2
ld	2
ldd	2
ld	2
ld	2
ld	2
ldd	2
sts	2
st	2
st	2
st	2
st	2
st	2
st	2
std	2
st	2
st	2
st	2
std	2
lpm	3
lpm	3
lpm	3
elpm	3
elpm	3
elpm	3
spm	0
in	1
out	1
push	2
pop	2
lsl	1
lsr	1
rol	1
ror	1
asr	1
swap	1
bset	1
bclr	1
sbi	2
cbi	2
bst	1
bld	1
sec	1
clc	1
sen	1
cln	1
sez	1
clz	1
sei	1
cli	1
ses	1
cls	1
sev	1
clv	1
set	1
clt	1
seh	1
clh	1
break	1
nop	1
sleep	1
wdr	1

--- NEW FILE: bb2asm.pl ---
#!/usr/bin/perl

# A script to generate basic block->asm statement mappings

# Input: 
# --- The basepath of local files (at the moment, the compiler is 
#     spitting out relative paths, while the debugging info has full 
#     names)
# --- cycle counts for each instruction type
# --- A BB dump 
# --- The object file with debug symbols

# The bb_linenum_map lines look like:
#1       $TOSDIR/platform/pc/external_comm.c:228
#2       $TOSDIR/platform/pc/Nido.nc:115
# ....

# The cycle count file looks like:
# cls\t1
# sbi\t2
# brid\t1.5
#  So fractional values are allowed (for instructions which can take
#  varying numbers of cycles)

# Output: A file with BB number\tAVR cycle count pairs 
# Line format: 'bb#\tcycle_count\n'
# Won't output a line if there isn't any info for it.

use Cwd 'realpath';

# Debugging flags
$DBG_OBJDUMP = 0;
$DBG_BBDUMP = 0;
$DBG_BB_CODE_MAP = 0;
$DBG_MAP_COMPUTE = 0;

$usage = 
"Usage: bb2asm.pl basepath cycle_counts bb_linenum_map main.exe bb_cycle_map\n".
"       basepath - path to add to start of relative filenames\n".
"       cycle_counts - file with instruction->number of cycles map\n".
"       bb_linenum_map - the basic block->line number mappings\n".
"       main.exe - the mica2 assembly, with debugging symbols\n".
"       bb_cycle_map - the output: a map of BB# -> AVR cycles\n\n";

die $usage if(scalar @ARGV != 5);

$basepath = shift @ARGV;
$cycle_counts = shift @ARGV;
$bb_dump = shift @ARGV;
$objfile = shift @ARGV;
$bb_cycle_map = shift @ARGV;

$me = `whoami`;
chomp($me);


# Do some checks
if($basepath =~ m|^[^/]|) {
    die "Basepath must start with '/'\n" . $usage;
}

# Remove any trailing '/'
$basepath =~ s|/$||;

open (CYCLE_COUNTS, $cycle_counts) || die "Can't open $cycle_counts: $!";

while(<CYCLE_COUNTS>) {
    chomp;
    ($opcode, $ncycles) = split /\t/;
    $cycles{$opcode} = $ncycles;
}

close CYCLE_COUNTS;

# File must be compiled with -g for this to work!!!
open (OBJDUMP, "msp430-objdump -s -d -l $objfile |") || die "Can't run objdump on $objfile: $!";

while(<OBJDUMP>) {
    chomp();
    if(/^\//) {
	($cur_file, $cur_line) = split /:/, $_;
	# Get a canonical name out of this filename
	unless ($path = realpath($cur_file)) {
	    warn "realpath '$cur_file' failed: $!\n";
	    $path = $cur_file;  # just use the current path
	}
	$path =~ s|/.*$me/|~/|;  # replace "/blah/blah/blah/username" with "~/"
	$cur_file = $path;
	} elsif( /^\s*$/ ) {
	$cur_line = "";
    } elsif($cur_line ne "") {
	$asm{$cur_file}{$cur_line} .= "$_\n";
    }
}

close OBJDUMP;

open (BBDUMP, $bb_dump) || die "Can't open $bb_dump: $!";

while(<BBDUMP>) {
    chomp();
    /^(\d+)\t([^:]*):(\d+)$/;
    ($bb, $file, $line) = ($1, $2, $3);
    if($file =~ m|^[^/]| && $file !~ m|^\~|) {
	die "This shouldn't happen!\n";
	# Filename does not start with '/' or '~', so add the basepath
	$file = $basepath . "/" . $file;
    }
    $bbinfo{$bb} = { "file" => $file, 
	"line" => $line,
	"code" => "" };
    $revmap{$file}{$line} = $bb;
}

close BBDUMP;

if($DBG_OBJDUMP) {
    print "Line -> ASM mappings\n";
    print "--------------------\n\n";

    foreach $f (sort keys %asm) {
	foreach $l (sort {$a <=> $b} keys %{$asm{$f}}) {
	    print "$f, $l\n";
	    print $asm{$f}{$l};
	    print "--------------------------\n\n";
	}
    }
}


if($DBG_BBDUMP) {
    print "BB->file,line mappings\n";
    foreach $bb (sort {$a <=> $b} keys %bbinfo) {
	print $bb, ",", $bbinfo{$bb}{"file"}, ":",$bbinfo{$bb}{"line"},"\n";
    }
    print "--------------------------\n\n";
    print "Reverse ( [file, line]->bb ) mappings\n";
    foreach $f (sort keys %revmap) {
	print "$f: ";
	foreach $l (sort {$a <=> $b} keys %{$revmap{$f}}) {
	    print "($l,", $revmap{$f}{$l},") ";
	}
	print "\n";
    }
}



foreach $f (sort keys %revmap) {
    print "file = $f\n" if $DBG_MAP_COMPUTE;

    @bb_lines = sort {$a <=> $b} keys %{$revmap{$f}};
    @asm_lines = sort {$a <=> $b} keys %{$asm{$f}};

    print "bb_lines = ", join(" ", @bb_lines), "\n" if $DBG_MAP_COMPUTE;
    print "asm_lines = ", join(" ", @asm_lines), "\n" if $DBG_MAP_COMPUTE;
    next if scalar(@asm_lines) == 0;
    # Now go through and find the asm_lines that go with each
    # bb_line
    while($cur_bb_line = shift @bb_lines) {
	print "bb_line = $cur_bb_line\n" if $DBG_MAP_COMPUTE;
	# Get rid of any lines that aren't in a basic block
	# This probably won't happen at all, but might at the start of 
	# a file
	print "asm_line = '".$asm_lines[0]."'\n" if $DBG_MAP_COMPUTE;

	while(defined($asm_lines[0]) && ($asm_lines[0] < $cur_bb_line)) {
	    shift @asm_lines;
	}
	if($bb_lines[0]) {
	    # Get all the lines till the next BB
	    while(defined($asm_lines[0]) &&
		defined($bb_lines[0]) &&
		($asm_lines[0] < $bb_lines[0]) ) {
		$bb = $revmap{$f}{$cur_bb_line};
		$bbinfo{$bb}{"code"} .= $asm{$f}{$asm_lines[0]};
		shift @asm_lines;
	    }
	} else {
	    # Last BB in the file, so get all the remaining lines
	    while(@asm_lines) {
		$bb = $revmap{$f}{$cur_bb_line};
		$bbinfo{$bb}{"code"} .= $asm{$f}{$asm_lines[0]};
		shift @asm_lines;
	    }
	}
    }
}


if($DBG_BB_CODE_MAP) {
    print "\n\nBB->Code map\n";
    print "-------------------\n\n";

    foreach $bb (sort {$a <=> $b} keys %bbinfo) {
	print $bb, ",", $bbinfo{$bb}{"file"},":", $bbinfo{$bb}{"line"},"\n";
	$code = $bbinfo{$bb}{"code"};
	print $code;
	print "Num cycles: ", &code_cycles($code), "\n";

	print "-----------------\n\n";
    }
}

open(OUTPUT, ">$bb_cycle_map") || die "Can't open $bb_cycle_map: $!";

foreach $bb (sort {$a <=> $b} keys %bbinfo) {
    $code = $bbinfo{$bb}{"code"};
    $cycles = &code_cycles($code);
    print OUTPUT "$bb\t$cycles\n" unless ($cycles == 0);
}

close(OUTPUT) || die "Can't close $bb_cycle_map: $!";


sub code_cycles {
    # rows are operand type, cols are opcode group
    # corresponds to table 3-15
    @fmt2tab =
    ([1, 3, 4],
	[3, 4, 4],
	[3, 4, 5],
	[0, 4, 5],
	[4, 5, 5],
	[4, 5, 5],
	[4, 5, 5]);

    # rows are src operand type, cols are dst operand type
    # corresponds to table 3-16
    @fmt1tab =
    ([1, 2, 4, 4, 4],
	[2, 3, 5, 5, 5],
	[2, 3, 5, 5, 5],
	[2, 3, 5, 5, 5],
	[3, 3, 6, 6, 6],
	[3, 3, 6, 6, 6],
	[3, 3, 6, 6, 6]);

    # Expansions of emulated instructions.
    %emulated = (
	'ret' => 'mov	@sp+,	pc',
	'adc' => 'addc	#0,	dst',
	'adc.b' => 'addc.b	#0,	dst',
	'clrc' => 'bic	#1,	sr',
	'clr' => 'mov	#0,	dst',
	'clr.b' => 'mov.b	#0,	dst',
	'decd' => 'sub	#2,	dst',
	'decd.b' => 'sub.b	#2,	dst',
	'inc' => 'add	#1,	dst',
	'inc.b' => 'add.b	#1,	dst',
	'incd' => 'add	#2,	dst',
	'incd.b' => 'add.b	#2,	dst',
	'inv' => 'xor	#0xffff,	dst',
	'inv.b' => 'xor.b	#0xff,	dst',
	'pop' => 'mov	@sp+,	dst',
	'rla' => 'add	dst,	dst',
	'rla.b' => 'add.b	dst,	dst',
	'rlc' => 'addc	dst,	dst',
	'rlc.b' => 'addc	dst,	dst',
    );

    # Takes a chunk of assembly code.  Assumes that it's a basic block. 
    # Uses the $cycles{$opcode} map to get total number of cycles for it.
    my($total) = 0;
    my($code) = shift;
    my(@lines) = split /\n/, $code;
    foreach $line (@lines) {
	next if($line =~ /^\s*$/ || $line =~ /\.\.\./);   # Skip empty lines
	@fields = split /\t/, $line;
	$opcode = $fields[2];
	$operand1 = $fields[3];
	$operand2 = $fields[4];

	# TODO add check back in
#	if(not defined $cycles{$opcode}) {
#	    print STDERR "code = '$code'";
#	    print STDERR "line = '$line'";
#	    print STDERR "Fields: ", join('/', at fields), "\n";
#	    print STDERR "opcode = '$opcode'\n";
#	    die "no mapping for '$opcode'";
#	}

	# Sometimes, the operands might be stuck together (no tab)
	@fakeOps = split /,/, $operand1;
	if ($fakeOps[1] ne '') {
		$operand1 = $fakeOps[0];
		$operand2 = $fakeOps[1];
		$fields[3] = $operand1;
		$fields[4] = $operand2;
	}

	# Remove trailing comma from operand1
	$operand1 =~ s/,$//;
	$operand2 =~ s/;.*$//;

	# Expand emulated instructions.
	if ($emulated{$opcode} ne '') {
	    my $expansion = $emulated{$opcode};
	    #print "Expanding $opcode\n";
	    $expansion =~ s/dst/$operand1/g;
	    push @lines, "\t\t$expansion";
#	    print join "\n", @lines;
	    next;
	}

	# Cycle calculation based on info from:
	# MSP430 User's Guide 2004
	# Section 3.4.4: Instruction Cycles and Lengths
	if ($opcode eq '' and $fields[1] =~ /^[\da-f]{2} 0[02]\s+$/) {
	    # This is a no-op, so skip it.
	    next;
	} elsif ($opcode eq '' and ($fields[1] =~ /^[\da-f]{2} [\da-f]{2}\s+$/
		or $fields[1] =~ /^\.\.\.\s*$/)) {
	    # TODO WHAT TO DO ABOUT THESE WEIRD THINGS?
	    next;
	} elsif ($opcode =~ /^\.word$/) {
	    # TODO WHAT TO DO ABOUT THESE WEIRD THINGS?
	    next;
	} elsif ($opcode =~ /^(jc|jge|jl|jmp|jn|jnc|jne|jnz|jz)$/) {
	    # Format-III instructions.
	    # All jumps require two cycles.
	    $count = 2;
	    #print "COUNT $count\n";
	} elsif ($operand1 ne '' and $operand2 ne '') {
	    # Format-I instructions.
	    $operand1Type = getOperand1Type($operand1, $code, $line, $fields);

	    $_ = $operand2;
	    if (/^(r\d+|sr|pc|sp)$/) {
		$operand2Type = 0;
	    } elsif (/^PC$/) {
		$operand2Type = 1;
	    } elsif (/^(-?0x(\d|[a-fA-F])+|-?\d+)\((r\d+|sr|pc|sp)\)$/) {
		$operand2Type = 2;
	    } elsif (/^(-?0x(\d|[a-fA-F])+|-?\d+)$/) {
		$operand2Type = 3;
	    } elsif (/^&(-?0x(\d|[a-fA-F])+|-?\d+)$/) {
		$operand2Type = 4;
	    } else {
		print STDERR "CODE\n$code";
		print STDERR "line = '$line'";
		print STDERR "FIELDS\n",join('/', @fields),"\n";
		die 'invalid operand 2 for format-I instruction';
	    }
	    $count = $fmt1tab[$operand1Type][$operand2Type];
	} elsif ($operand2 eq '') {
	    # Format-II instructions.
	    $operandType = getOperand1Type($operand1, $code, $line, $fields);

	    $_ = $opcode;
	    if (/^(rra|rra.b|rrc|rrc.b|swpb|sxt)$/) {
		$opcodeGroup = 0;
	    } elsif (/^push$/) {
		$opcodeGroup = 1;
	    } elsif (/^call$/) {
		$opcodeGroup = 2;
	    } else {
		print STDERR "CODE\n$code";
		print STDERR "LINE\n$line\n";
		die 'invalid opcode for format-II instruction.';
	    }

	    if ($operandType == 3 and $opcodeGroup == 0) {
		print STDERR "CODE\n$code";
		print STDERR "line = '$line'";
		die 'invalid opcode+operand for format-II instruction.' 
	    }

	    $count = $fmt2tab[$operandType][$opcodeGroup];

	    #print "OPERANDTYPE $operandType\tOPCODE $opcodeGroup\tCOUNT $count\n";
	} else {
	    print STDERR "CODE\n$code";
	    print STDERR "line = '$line'";
	    die 'unknown instruction format.';
	}

	#print "COUNT $count\tTOTAL $total\n";
	$total += $count;
    }
    return $total;
}

sub getOperand1Type {
    $operand = shift;
    $code = shift;
    $line = shift;
    $fields = shift;

    $_ = $operand;
    if (/^(r\d+|sr|pc|sp)$/) {
	$operandType = 0;
    } elsif (/^\@(r\d+|sr|pc|sp)$/) {
	$operandType = 1;
    } elsif (/^\@(r\d+|sr|pc|sp)\+$/) {
	$operandType = 2;
    } elsif (/^#(-?0x(\d|[a-fA-F])+|-?\d+)$/) {
	$operandType = 3;
    } elsif (/^(-?0x(\d|[a-fA-F])+|-?\d+)\((r\d+|sr|pc|sp)\)$/) {
	$operandType = 4;
    } elsif (/^(-?0x(\d|[a-fA-F])+|-?\d+)$/) {
	$operandType = 5;
    } elsif (/^&(-?0x(\d|[a-fA-F])+|-?\d+)$/) {
	$operandType = 6;
    } else {
	print STDERR "CODE\n$code";
	print STDERR "LINE\n$line\n";
	print STDERR "FIELDS\n",join('/', @fields),"\n";
	print STDERR "OPERAND1\n",$operand,"\n";
	die 'invalid operand-1 type'
    }

    return $operandType;
}

--- NEW FILE: bb2cycle.pl ---
#!/usr/bin/perl

# Script to take BB execution counts generated by TOSSIM and convert them to cycle
# counts

$usage = 
    "Usage: bb2cycle.pl bb_exec_cnt bb_cycle_map\n".
    "       bb_exec_cnt: The basic block execution counts output by TOSSIM\n".
    "       bb_cycle_map: The bb -> cycle count map generated by bb2asm.pl\n\n";  


die $usage if(scalar @ARGV != 2);

$bb_exec_cnt = shift @ARGV;
$bb_cycle_map = shift @ARGV;

open(EXEC_CNT, $bb_exec_cnt) || die "Can't open $bb_exec_cnt: $!";
open(CYCLE_MAP, $bb_cycle_map) || die "Can't open $bb_cycle_map: $!";

while(<CYCLE_MAP>) {
    ($bb, $cnt) = split;
    $cycles{$bb} = $cnt;
}

while(<EXEC_CNT>) {
    ($mote, $bb, $cnt) = split;
    $total{$mote} += $cnt * $cycles{$bb};
}

foreach $mote (sort {$a <=> $b} keys %total) {
    print "$mote\t", $total{$mote}, "\n";
}
close(EXEC_CNT);
close(CYCLE_MAP);

--- NEW FILE: cilly.asm.exe ---
ELF










‰ÓÿщË‹D$
‹D$‰ÓÿщË‹D$ÿщË‹D$ƒÄÿáë
ƒì‰D$‰\$
,…ÿÿÿÿ¶.)Å9Õ†¡


…ÿÿÿÿ¶)ȍT


[...5532 lines suppressed...]



















—
5
eapify__24
heck__28
_171

amlCil__215
__795
mlCparser__209
208
r__33

long
ob_2509
n_1295
compare_162
un_859
sh_recvar_name_1098
3
lPtranal__hose_globals_825
low_forward
bals
arser__fun_2716

method_vinst_1044
val_1010
parse__fun_2476
kup_125
amlCil__method_vvdec_5102
--- NEW FILE: compile.pl ---
#!/usr/bin/perl -w

# Script to compile an TinyOS app with CPU profiling support.  
# Must be run from the base directory of the project (where the main 
# makefile is)
# The 'make pc' and 'make mica2' commands should behave the same as with 
# the TinyOS sample apps: create app.c and main.exe in the build/{platform} 
# directories.

# cilly must be in your path.

use Cwd;

if($ARGV[0] eq "--nomake") {
    $make = 0;
} else {
    $make = 1;
}

$ROOT = $ENV{"TOS"} . "/beta/TOSSIM-CC2420/PowerTOSSIM";

$SCRIPTDIR="$ROOT";
$BASEDIR = getcwd();
$CYCLECOUNTS = "$ROOT/msp430_cycle_counts.txt";
$CILLY = "$SCRIPTDIR/cilly.asm.exe";


# system() returns 0 on success, hence the &&s

if($make) {
    system("make pc sim,telosA") && die "Can't compile base app for pc!\n";

    system("make telos") && die "Can't compile base app for telos!\n";
}

system("cd build/pc && $CILLY --doCounter --out app.cil.c app.c > bb_line_tmp") && die "cilly error\n"; 

# print "cwd = ", getcwd(), "\n";

system("$SCRIPTDIR/fixnames.pl build/pc/bb_line_tmp > build/pc/bb_linenum_map") && die "fixnames.pl error\n";

chdir("build/pc") || die "Can't chdir: $!\n";

system("$SCRIPTDIR/mypp.pl app.cil.c") && die "mypp.pl error\n";

print "****************************\n";
print "$SCRIPTDIR/bb2asm.pl $BASEDIR  $CYCLECOUNTS bb_linenum_map ../telos/main.exe bb_cycle_map\n";
print "****************************\n";

system("$SCRIPTDIR/bb2asm.pl $BASEDIR  $CYCLECOUNTS bb_linenum_map ../telos/main.exe bb_cycle_map") && die "bb2asm.pl error\n";
 
system("gcc -O3 -o a.out app.cil.mypp.c -lpthread -lm");

# Clean up
system("rm bb_line_tmp") && die "rm failed\n";


--- NEW FILE: counter.ml ---
(*
 * counter.ml
 *
 * This file contains a CIL transformation that increments a counter
 * at the beginning of each basic block.
 *)

open Cil

let max_motes = 10000;;  (* Waste RAM, but who cares? It's only a few megs. *)

let num_bbs = ref 0;;
let cur_bb = ref 0;;

let myType = Formatcil.cType 
	       "int [%d:motes][%d:bbs]" 
	       [("motes", Fd max_motes); ("bbs",Fd !num_bbs) ];;

let cntArr = makeGlobalVar "bb_count" myType;; (* (TArray(intType, Some (integer !num_bbs),[]));; *)

(* Just count the number of basic blocks in the file *)
class countbbClass = object
  inherit nopCilVisitor

  method vstmt (s: stmt) : stmt visitAction = begin
    begin
      match s.skind with
	Instr instrs ->
	  num_bbs := !num_bbs + 1; 
      | _ -> ()
    end;
    DoChildren
  end
end

  
class instrumentClass = object
  inherit nopCilVisitor

  method vstmt (s: stmt) : stmt visitAction = begin
    begin
      match s.skind with
	  Instr instrs ->  begin
	    cur_bb := !cur_bb + 1;
	    print_string (string_of_int(!cur_bb) ^ "\t");
	    print_string (Pretty.sprint 76 (d_thisloc ()) );
	    print_string "\n";


	    (* Want "bb_count[" ^ string_of_int(!cur_bb) ^ "] =  bb_count[!cur_bb] + 1;" *)
	     let ctrInc = Formatcil.cInstr 
			    "%v:arr[%d:mote][%d:cnt] = %v:arr[%d:mote][%d:cnt] + 1; // BB # %d:cnt" 
			    locUnknown  
			    [ ("mote", Fd 42); 
			      ("cnt",Fd !cur_bb); 
			      ("arr", Fv cntArr)
			    ]; 

(*	    let ctrInc =
	      Set (var ctrVar,
		 BinOp (PlusA, Lval (var ctrVar), integer 1, intType),
		 locUnknown)
	      Set (var ctrVar,
		   BinOp (PlusA, Lval (var ctrVar), integer !cur_bb, intType),
		   locUnknown) *)
	    in
	      s.skind <- Instr (ctrInc :: instrs);
	  end
	| _ -> ()
    end;
    DoChildren
  end
end


let main (f: file) : unit = 
  visitCilFile ((new countbbClass) :> cilVisitor) f;

(*  print_string("DEBUG: There are " ^ string_of_int(!num_bbs) ^ " basic blocks\n"); *)

(*  f.globals <- GVarDecl (ctrVar, locUnknown) :: f.globals; *)

  visitCilFile ((new instrumentClass) :> cilVisitor) f;
  f.globals <- GVarDecl (cntArr, locUnknown) :: f.globals


let feature : featureDescr = {
  fd_name = "Counter";
  fd_enabled = ref false;
  fd_description = "increment a counter at the beginning of each basic block";
  fd_extraopt = [];
  fd_doit = main;
  fd_post_check = true;
  } 


--- NEW FILE: cpuprof.py ---
#!/usr/bin/python

# Script to do convert the bb exec counts into some useful form.
# reads the files bb_cycle_map, bb_exec_cnt, bb_linenum_map in the
# current directory

import sys;

COUNT_BLOCKS = 0
if '--countbbs' in sys.argv:
    COUNT_BLOCKS = 1

NUM_BLOCKS = 20   # Number of most expensive basic blocks to print
NUM_FILES = 20   # Number of most expensive files to print

nummotes = 0
cycle_map = {}
for line in  open('bb_cycle_map').readlines():
    (bb, cnt) = line.split('\t')
    cycle_map[int(bb)] = float(cnt)


filecycles = {}  # File->cycles mapping

exec_cnt = {}
# Skip the first line-it's a total that we don't need
for line in open('bb_exec_cnt').readlines():
    if not line.startswith('mote'):   # stupid me put totals in the file format
        (mote, bb, cnt) = line.split()
        mote = int(mote)
        if mote > nummotes:
            nummotes = mote
        if not mote in exec_cnt:
            exec_cnt[mote] = {}
        exec_cnt[mote][int(bb)] = float(cnt)

nummotes += 1

linenum_map = {}
for line in  open('bb_linenum_map').readlines():
    (bb, l) = line.split('\t')
    linenum_map[int(bb)] = l

def mycmp(a, b):
    # Want to sort in reverse order, so exchange a, b
    if COUNT_BLOCKS:
        return cmp(exec_cnt[m][b], exec_cnt[m][a])
    else:
        return cmp(exec_cnt[m][b] * cycle_map.get(b,0),
                   exec_cnt[m][a] * cycle_map.get(a,0))

# Takes a dictionary.  Returns the set of keys sorted by value
def sortdict(d):
    keys = d.keys()
    keys.sort(lambda a,b:cmp(d[a],d[b]))
    return keys

if COUNT_BLOCKS:
    print "Block counts:"
else:
    print "Cycle counts:"
print "     %12s%12s%12s%12s%12s%12s%12s" % ('App', 'System',
                                             'Lib', 'Interfaces',
                                             'Platform',  'Misc',  'Total')
for m in range(nummotes):
    filecycles = {}
    platform = 0
    app = 0
    system = 0
    interfaces = 0
    lib = 0
    misc = 0
    for bb in exec_cnt[m]:
        if COUNT_BLOCKS:
            cycles =  exec_cnt[m][bb]
        else:  # Count cycles instead
            cycles = cycle_map.get(bb,0) * exec_cnt[m][bb]

        # Get the filename
        t = linenum_map[bb].rfind(':')
        filename = linenum_map[bb][:t]
        if not filename in filecycles:
            filecycles[filename] = cycles
        else:
            filecycles[filename] += cycles
        
        if linenum_map[bb].find('/platform/') != -1:
#            print 'platform: ', linenum_map[bb]
            platform += cycles
        elif linenum_map[bb].find('/tos/system') != -1:
#           print 'system: ', linenum_map[bb]
            system += cycles
        elif linenum_map[bb].find('/tos/lib') != -1:
            lib += cycles
        elif linenum_map[bb].find('/tos/interfaces') != -1:
            interfaces += cycles
        elif linenum_map[bb].find('/apps/') != -1:
#            print 'app: ', linenum_map[bb]
            app += cycles
        else:
#            print 'misc: ', linenum_map[bb]
            misc += cycles

    print "%3d: %12s%12s%12s%12s%12s%12s%12s" % (m,app, system, lib,
                                                 interfaces, platform,
                                                 misc,
                                                 app+system+platform+misc)

    # Now lets figure out the top K basic blocks for this mote:
    blocks = exec_cnt[m].keys()
    blocks.sort(mycmp)
    print "Mote %d: %d most expensive BBs:"  % (m, NUM_BLOCKS)
    for bb in blocks[:NUM_BLOCKS]:
        print "%6d%15.1f   %s" % (bb, exec_cnt[m][bb], linenum_map[bb])
    
    # And now the files
    files = sortdict(filecycles)
    files.reverse()
    print "Mote %d: %d most expensive files:"  % (m, NUM_FILES)
    for f in files[:NUM_BLOCKS]:
        print "%15.1f   %s" % (filecycles[f], f)

--- NEW FILE: fixnames.pl ---
#!/usr/bin/perl -w

# Script to fix files... the automounter makes it nigh impossible to
# get canonical absolute pathnames, so we'll just strip out everything
# up to $USERNAME.

# Input lines of the format:
# number\tpath:number

# Output, same, except that the paths inside the home directory will
# all be of the form ~/blah/blah

use Cwd 'realpath';

$me = `whoami`;
chomp($me);

while(<>) {
    chomp();
    /^(\d+)\t([^:]*):(\d+)$/;
    ($bb, $file, $line) = ($1, $2, $3);
    if(/^\d+\t:-1/) {
	print "$_\n";
	next;
    }
    $path = realpath($file) || die "fixname.pl: realpath '$file' failed: $!\n";
    $path =~ s|/.*$me/|~/|;  # replace "/blah/blah/blah/username" with "~/"
    print "$bb\t$path:$line\n";
}

--- NEW FILE: mica2_energy_model.txt ---
# Energy model for the mica2
# see http://www.eecs.harvard.edu/~shnayder/ptossim/ for details
# Lines starting with '#' are comments

# Format: KEY\s+VALUE
# Unless otherwise specified, VALUE is a current in mA
# Value is always assumed to be a number

VOLTAGE	 3.0

# CPU numbers:
# Idle mode is what the CPU is in when not actively executing, but 
# no special action is taken.  The per-active-cycle numbers are added 
# on top of that
# Added .93mA to idle and active cpu power to account for the
# oscillator.  Need to make it separate later...

#CPU_ACTIVE			8.0
CPU_ACTIVE			8.93
#CPU_IDLE			3.2
CPU_IDLE			4.13
CPU_ADC_NOISE_REDUCTION		1.0
CPU_POWER_DOWN			0.103
CPU_POWER_SAVE			0.110
CPU_STANDBY			0.216
CPU_EXTENDED_STANDBY		0.223

# The startup mode for the cpu
CPU_INIT			3.2

CPU_FREQ	4000000
# It's actually 7382800, but the simulator is hardcoded for 4Mhz, and
# the fixes for that aren't merged yet
#CPU_FREQ	7382800


# These are actual measured numbers
RADIO_RX   7.03
RADIO_TX_00   3.72
RADIO_TX_01   5.21
RADIO_TX_03   5.37
RADIO_TX_06   6.47
RADIO_TX_09   7.05
RADIO_TX_0F   8.47
RADIO_TX_60   11.57
RADIO_TX_80   13.77
RADIO_TX_C0   17.37
RADIO_TX_FF	21.48
RADIO_OFF	0
 
# These are interpolated from above
RADIO_TX_02   5.3
RADIO_TX_04   5.75
RADIO_TX_05   6.1
RADIO_TX_07   6.67
RADIO_TX_08   6.87
RADIO_TX_0A   7.33
RADIO_TX_0B   7.6
RADIO_TX_0C   7.93
RADIO_TX_0E   8.15
RADIO_TX_40   9.5
RADIO_TX_50   10.5
RADIO_TX_70   12.6
RADIO_TX_90   15.0
RADIO_TX_E0   19.5

# The default power mode (0x0F, but python doesn't like hex numbers in floats)
RADIO_DEFAULT_POWER  15.00


# LED
LED		2.2
#default to off
LED_INIT	0

# EEPROM
EEPROM_READ	6.24
EEPROM_WRITE	18.40

#ADC
# we thought it took power, so it's tracked, but it actually doesn't
ADC	0.0

# If the sensor board is plugged in, it draws this much current at all times
SENSOR_BOARD	0.69

# Sensors - don't actually use power beyond the general sensor board power
SENSOR_PHOTO	0
SENSOR_TEMP	0
--- NEW FILE: msp430_cycle_counts.txt ---


--- NEW FILE: msp_cpuprof.py ---
#!/usr/bin/python

# Script to do convert the bb exec counts into some useful form.
# reads the files bb_cycle_map, bb_exec_cnt, bb_linenum_map in the
# current directory

import sys;

COUNT_BLOCKS = 0
if '--countbbs' in sys.argv:
    COUNT_BLOCKS = 1

NUM_BLOCKS = 20   # Number of most expensive basic blocks to print
NUM_FILES = 20   # Number of most expensive files to print

nummotes = 0
cycle_map = {}
for line in  open('bb_cycle_map').readlines():
    (bb, cnt) = line.split('\t')
    cycle_map[int(bb)] = float(cnt)


filecycles = {}  # File->cycles mapping

exec_cnt = {}
# Skip the first line-it's a total that we don't need
for line in open('bb_exec_cnt').readlines():
    if not line.startswith('mote'):   # stupid me put totals in the file format
        (mote, bb, cnt) = line.split()
        mote = int(mote)
        if mote > nummotes:
            nummotes = mote
        if not mote in exec_cnt:
            exec_cnt[mote] = {}
        exec_cnt[mote][int(bb)] = float(cnt)

nummotes += 1

linenum_map = {}
for line in  open('bb_linenum_map').readlines():
    (bb, l) = line.split('\t')
    linenum_map[int(bb)] = l

def mycmp(a, b):
    # Want to sort in reverse order, so exchange a, b
    if COUNT_BLOCKS:
        return cmp(exec_cnt[m][b], exec_cnt[m][a])
    else:
        return cmp(exec_cnt[m][b] * cycle_map.get(b,0),
                   exec_cnt[m][a] * cycle_map.get(a,0))

# Takes a dictionary.  Returns the set of keys sorted by value
def sortdict(d):
    keys = d.keys()
    keys.sort(lambda a,b:cmp(d[a],d[b]))
    return keys

if COUNT_BLOCKS:
    print "Block counts:"
else:
    print "Cycle counts:"
print "     %12s%12s%12s%12s%12s%12s%12s" % ('App', 'System',
                                             'Lib', 'Interfaces',
                                             'Platform',  'Misc',  'Total')
for m in range(nummotes):
    filecycles = {}
    platform = 0
    app = 0
    system = 0
    interfaces = 0
    lib = 0
    misc = 0
    for bb in exec_cnt[m]:
        if COUNT_BLOCKS:
            cycles =  exec_cnt[m][bb]
        else:  # Count cycles instead
            cycles = cycle_map.get(bb,0) * exec_cnt[m][bb]

        # Get the filename
        t = linenum_map[bb].rfind(':')
        filename = linenum_map[bb][:t]
        if not filename in filecycles:
            filecycles[filename] = cycles
        else:
            filecycles[filename] += cycles
        
        if linenum_map[bb].find('/platform/') != -1:
#            print 'platform: ', linenum_map[bb]
            platform += cycles
        elif linenum_map[bb].find('/tos/system') != -1:
#           print 'system: ', linenum_map[bb]
            system += cycles
        elif linenum_map[bb].find('/tos/lib') != -1:
            lib += cycles
        elif linenum_map[bb].find('/tos/interfaces') != -1:
            interfaces += cycles
        elif linenum_map[bb].find('/apps/') != -1:
#            print 'app: ', linenum_map[bb]
            app += cycles
        else:
#            print 'misc: ', linenum_map[bb]
            misc += cycles

    print "%3d: %12s%12s%12s%12s%12s%12s%12s" % (m,app, system, lib,
                                                 interfaces, platform,
                                                 misc,
                                                 app+system+platform+misc)

    # Now lets figure out the top K basic blocks for this mote:
    blocks = exec_cnt[m].keys()
    blocks.sort(mycmp)
    print "Mote %d: %d most expensive BBs:"  % (m, NUM_BLOCKS)
    for bb in blocks[:NUM_BLOCKS]:
        print "%6d%15.1f   %s" % (bb, exec_cnt[m][bb], linenum_map[bb])
    
    # And now the files
    files = sortdict(filecycles)
    files.reverse()
    print "Mote %d: %d most expensive files:"  % (m, NUM_FILES)
    for f in files[:NUM_BLOCKS]:
        print "%15.1f   %s" % (filecycles[f], f)

--- NEW FILE: mypp.pl ---
#!/usr/bin/perl -w 

# A script to preprocess the code that's been run through cilly before
# compiling it.  Fixes the number of basic blocks in several places

$usage = "Usage: mypp.pl file.c\n";
# Output is file.mypp.c

die $usage unless $ARGV[0]; 

$infile = $ARGV[0];
$outfile = $infile;
$outfile =~ s/\.c$/.mypp.c/;

die "ERROR: Not a .c file specified\n$usage" if($infile eq $outfile);

open (INPUT, $infile) || die "can't open $infile: $!";

$max = 0;
while(<INPUT>) {
    if(/^\s*bb_count\[42\]\[(\d+)\]/) {
	$max = $1 if ($1 > $max);
    }
}

$max++;  # Since things start with 0
print STDERR "There are $max basic blocks\n";
close INPUT;

# Now max contains the number of basic blocks
open (INPUT, $infile) || die "can't open $infile: $!";
open (OUTPUT, ">$outfile") || die "can't open $outfile: $!";

while(<INPUT>) {
    if(/int POWERPROF_BB_EXEC_COUNT/) {
	# Skip the declaration
	print OUTPUT $_;
	next; 
    }
	

    s/bb_count\[10000\]\[0\]/bb_count\[10000\]\[$max\]/;

    s/bb_count\[42\]/bb_count\[tos_state.current_node\]/g;

    s/int POWERPROF_NUM_BBS/int POWERPROF_NUM_BBS = $max/;    

    s/POWERPROF_BB_EXEC_COUNT/bb_count\[mote\]\[bb\]/g;

    print OUTPUT $_;
}

--- NEW FILE: postprocess.py ---
#!/usr/bin/python
# postprocess.py
# Author: Victor Shnayder <shnayder at eecs.harvard.edu>
# Postprocessing script that reads PowerTOSSIM state transition log and
# computes power and energy numbers.

from sys import argv
import sys

usage = """USAGE: postprocess.py [--help] [--debug] [--nosummary]
[--detail[=basename]]  [--maxmotes N]
[--simple] [--sb={0|1}] --em file trace_file

--help:              print this help message
--debug:             turn on debugging output
--nosummary:         avoid printing the summary to stdout
--detail[=basename]: for each mote, print a list of 'time\\tcurrent' pairs
              to the file basename$moteid.dat (default basename='mote')
--em file:           use the energy model in file
--sb={0|1}:          Whether the motes have a sensor board or not. (default: 0)
--maxmotes:          The maximum of number of motes to support. 1000 by default.
--simple:            Use a simple output format, suitable for machine parsing

By default, uses energy model from energy_model.txt in the current directory,
prints summary.
"""

summary = 1
prettyprint = 1
detail = 0
lineno = 0   # The line number in the trace file
emfile = "energy_model.txt"
tracefile = ""
model = {}      # The energy model (mappings such as CPU_ACTIVE->8.0)
state = [{}]    # The current state of execution ([mote][component])
total = [{}]   # The energy totals

# Hmm... might not actually want 1000 open files.  I guess I could
# open and close each one after each write.  Or just keep all the
# logs in memory and then write them out one at a time.  For now, just
# open each file when necessary and leave it at that
data_file = []  
basename = 'mote'

voltage = None
prev_current = []
prev_time = []

maxmotes = 1000
maxseen = 0
debug = 0
em = {}  # The energy model
sb = 0   # Whether there's a sensor board

#components = ["radio", "cpu", "cpu_cycles", "adc", "sensor", "led", "eeprom"]

# Types of total we want to track
totals = ["cpu", "radio", "adc", "leds", "sensor", "eeprom"]


def quit(showusage=0, error="Illegal arguments"):
    if error:
        print >> sys.stderr, "Error: ", error, "\n"

    if showusage:
        print >> sys.stderr, usage
    sys.exit()


# Handle arguments-this can be rewritten with a dictionary of lambdas, but
# that's for later (or I can just use an existing module)
def parse_args():
    global summary, maxmotes, emfile, tracefile, trace, argv, debug, basename
    global detail, prettyprint, sb
    argv = argv[1:]
    while argv:
        a=argv[0]
        if a == "--help":
            quit(1,"")
        elif a == "--nosummary":
            summary = 0
        elif a == "--simple":
            prettyprint = 0
        elif a.startswith("--detail"):
            detail = 1
            x=a.rfind('=')
            if x != -1:
                basename = a[x+1:]
                
        elif a.startswith("--sb="):
            t = a[5:]
            if t == "1":
                sb = 1
            elif t == "0":
                sb = 0
            else:
                quit(1)
            
                
        elif a == "--debug":
            debug = 1
        elif a == "--maxmotes":
            argv = argv[1:] # Consume this argument
            if not argv:
                quit(1)
            maxmotes = int(argv[0])
        elif a == "--em":
            argv=argv[1:]  # Consume this argument
            if not argv:
                quit(1)
            emfile = argv[0]  # Get the filename parameter
        else:
            tracefile = a
        argv = argv[1:]


    if tracefile == "":
        quit(1,"No tracefile specified")

    try:
        trace = open(tracefile)
    except IOError:
        quit(0,"Couldn't open trace file '"+tracefile+"'")


######### State initialization functions ##############

# Read energy model from file
def read_em():
    global model,lineno,em
    # Reads and parses the energy model file
    try:
        model = open(emfile)
    except IOError:
        quit(0,"Couldn't open energy model file '"+emfile+"'")

    l = model.readline()
    lineno += 1
    while l:
        l=l.strip()
        # Parse the line, skipping comments, blank lines
        if l == '' or l[0] == '#':
            l = model.readline()
            continue
#        print "splitting line '%s'" % l
        (k,v) = l.split()
        em[k]=float(v)
        l = model.readline()
        lineno += 1
    
def initstate():
    global state, total, voltage, prev_current, prev_time, data_file
    read_em()
    # initialize the various lists...
    state = [None] * maxmotes
    total = [None] * maxmotes
    prev_current = [None] * maxmotes
    prev_time = [0] * maxmotes
    data_file = [None] * maxmotes
    voltage = em['VOLTAGE']
    
    for mote in range(maxmotes):
        # Init each mote with base values
        state[mote] = {'radio':{'on':0, 'tx':0,
                                'txpower':em['RADIO_DEFAULT_POWER']}, 
                       'cpu': 'IDLE',
                       'cpu_cycles':0,
                       'adc': 0,
                       'adc_on': 0,
          # For the moment, all the same, but can be changed later
                       'sensor_board': sb,  
                       'sensor': {},
                       'led': {},
                       'eeprom': {'read':0, 'write':0}}
        total[mote] = {}
        prev_current[mote]={}
        for k in totals:
            prev_current[mote][k] = 0
        prev_current[mote]['total']=0
        for t in totals:
            total[mote][t] = 0

######################## Current computation #######################

def get_cpu_current(mote):
    return em["CPU_"+state[mote]["cpu"]]

def get_sensor_current(mote):
    mystate = state[mote]['sensor']
    total = 0
    # If the sensor board is plugged it draws a constant base current 
    if state[mote]['sensor_board']:
        total += em.get('SENSOR_BOARD')
    for (type,value) in mystate.items():
        if value==1:
            total += em.get("SENSOR_"+type, 0)
    return total

def get_adc_current(mote):
    # FIXME: if we discover that sampling actually takes energy
    # in addition to the base cost, add it in if sampling.
    if state[mote]['adc_on']:
        return em['ADC']
    else:
        return 0

def tx_current(x):
    """ Return the radio current for transmit power x """
    return em["RADIO_TX_"+("%02X" % x)]

def get_radio_current(mote):
	# Note that this sets the total power of the radio, so we have to include
	# numbers like RADIO_ON.
	#the state is:  {'on':ON/OFF,'tx': TX/RX,'txpower':PowerLevel}
	mystate = state[mote]['radio']
	power = 0
	if mystate['on']:
		power += em['RADIO_ON']
		if mystate['oscon']:
			power += em['RADIO_OSCON']
			if mystate['tx']:
				power += tx_current(mystate['txpower'])
			elif mystate['rx']:
				power += em['RADIO_RX']
	return power;

def get_leds_current(mote):
    # Count how many leds are on:
    numon = state[mote]['led'].values().count(1)
    return numon * em['LED']

def get_eeprom_current(mote):
    # Assumes that EEPROM can't read and write at the same time
    # I believe that's correct
    if state[mote]['eeprom']['read']:
        return em['EEPROM_READ']
    if state[mote]['eeprom']['write']:
        return em['EEPROM_WRITE']
    return 0
    

# There should probably be one entry for each key of the totals
# defined above
current_fn_map = {
    'cpu': get_cpu_current,
    'radio': get_radio_current,
    'adc': get_adc_current,
    'leds':get_leds_current,
    'sensor':get_sensor_current,
    'eeprom':get_eeprom_current}


def get_current(mote):
    total = 0
    for k in current_fn_map.keys():
        total += current_fn_map[k](mote)
    return total

def print_currents():
    for m in range(maxseen+1):
        print "mote %d: current %f" % (m, get_current(m))


######################## Event processing ##########################

# Add together a mote time from the trace (in CPU cycles)
# and a energy model time (in ms)
def time_add(motetime, emtime):
    return motetime + emtime / 1000.0 * em.get("CPU_FREQ",7370000)

# The handlers should just update the state.  Other functions are
# responsible for keeping track of totals.

def cpu_cycle_handler(mote, time, newstate):
    # the cpu cycle messages always have a single number, which is
    # the total since beginning of execution
    global state
    state[mote]['cpu_cycles'] = float(newstate[1])

def cpu_state_handler(mote, time, newstate):
    # Here are the possible states, from PowerStateM.nc:
    #        char cpu_power_state[8][20] = {"IDLE", \
    #                                       "ADC_NOISE_REDUCTION", \
    #                                       "POWER_DOWN", \
    #                                       "POWER_SAVE", \
    #                                       "RESERVED", \
    #                                       "RESERVED", \
    #                                       "STANDBY", \
    #                                       "EXTENDED_STANDBY"}
    # The energy model should have keys for each of the form CPU_`state`
    global state
    state[mote]["cpu"] = newstate[1]

def adc_handler(mote, time, newstate):
    global state
    #FIXME: The ADC has to be on for any ADC event to work-check this
    action = newstate[1]
    if action == 'SAMPLE':
        state[mote]["adc"] = 1
    elif action == 'DATA_READY':
        state[mote]["adc"] = 0
    elif action == 'ON':
        state[mote]["adc_on"] = 1
    elif action == 'OFF':
        state[mote]["adc_on"] = 0
    else:
        quit(0,"Line %d: Syntax error: adc action %s unknown" % (lineno,action))

def radio_state_handler(mote, time, newstate):
    """
    The radio is one of the more complicated pieces:
    The possible values for newstate:
    ON  - turn radio on.  As far as I can tell, goes back
    to it's previous state
    OFF - turn radio off.
    TX - go into transmit mode.  The transmit power is the same
         as it was before (either the default, or the latest SetRFPower)
    RX - go into receive mode
    SetRFPower XX  for some hex value of XX-there should be an
    energy model entry for RADIO_TX_XX
    
    Thus, the state for the radio is:
    {'on':ON/OFF,'tx': TX/RX,'txpower':PowerLevel}
    """
    global state
    oldstate = state[mote]['radio']
    op = newstate[1]
    if op == "ON":
        # Parameters are set to defaults when turning on
        oldstate['on'] = 1
		oldstate['oscon'] = 0
        oldstate['tx'] = 0 # Defaults to RX mode
        oldstate['txpower'] = em['RADIO_DEFAULT_POWER']
    elif op == "OFF": 
        oldstate['on'] = 0
		oldstate['oscon'] = 0
    elif op == "SetRFPower":
        oldstate['txpower'] = int(newstate[2],16)  # must be a hex number
    elif op == "TX":
        # The mica(1) stack, doesn't explicitly turn radio on, so
        # TX/RX transitions also turn it on.  Should be valid for mica2
        # as well, unless it tries to send while the radio is off, which
        # probably qualifies as a bug
        oldstate['on'] = 1 
		oldstate['oscon'] = 1
        oldstate['tx'] = 1
    elif op == "RX":
        oldstate['on'] = 1
		oldstate['oscon'] = 1
        oldstate['tx'] = 0
	elif op == "OSC_ON":
		oldstate['on'] = 1
		oldstate['oscon'] = 1
    else:
        quit(0,"Line %d: Syntax error: radio state %s unknown" % (lineno,op))
    

def led_state_handler(mote, time, newstate):
    """ The state for the LEDs is pretty simple:
        They start out off, and here we just keep track of which are on
        in a dictionary.  So the state[mote]['led'] looks like
        {'RED':onoff, 'GREEN':onoff, 'YELLOW':onoff}
    """
    global state
    msg = newstate[1]
    if msg.endswith("_OFF"):
        state[mote]['led'][msg[:-4]]=0
    else:
        assert msg.endswith("_ON")
        state[mote]['led'][msg[:-3]]=1

def sensor_state_handler(mote, time, newstate):
    global state
    # If we're doing sensor stuff, there must be a sensor board:
    type = newstate[1]
    action = newstate[2]
    if action == 'ON':
        state[mote]['sensor'][type] = 1
    elif action == 'OFF':
        state[mote]['sensor'][type] = 0
    else:
        quit(0, "Line %d: Syntax error: sensor state %s unknown"
             % (lineno, action))

def eeprom_state_handler(mote, time, newstate):
    global state
    type = newstate[1]
    action = newstate[2]
    if type == 'READ':
        if action == 'START':
            state[mote]['eeprom']['read'] = 1
        elif action == 'STOP':
            state[mote]['eeprom']['read'] = 0
        else:
            quit(0, "Line %d: Syntax error: EEPROM READ action %s unknown"
             % (lineno, action))
    elif type == 'WRITE':
        if action == 'START':
            state[mote]['eeprom']['write'] = 1
        elif action == 'STOP':
            state[mote]['eeprom']['write'] = 0
        else:
            quit(0, "Line %d: Syntax error: EEPROM WRITE action %s unknown"
             % (lineno, action))
    else:
        quit(0, "Line %d: Syntax error: EEPROM TYPE %s unknown"
             % (lineno, type))

# A table of event type to the appropriate handler
event_handler = {'CPU_CYCLES'  :    cpu_cycle_handler,
                 'CPU_STATE'   :    cpu_state_handler,
                 'ADC'  :          adc_handler,
                 'RADIO_STATE' :  radio_state_handler,
                 'LED_STATE'   :    led_state_handler,
                 'SENSOR_STATE': sensor_state_handler,
                 'EEPROM'      : eeprom_state_handler}


def time_diff(t_from, t_to):
    """Returns the difference, in seconds from 't_from' to 't_to', where both
    are expressed in cycles.  Uses the CPU_FREQ energy model parameter"""
    return (float(t_to) - float(t_from))/em['CPU_FREQ']

# Updates every total for every timestep.  This is inefficient,
# because if the radio is on for 100 events, there's no need to do 100
# small adds But it's simpler this way.  Can fix it (by making
# prev_time parametrized by total type) if it's a problem
def update_totals(time):
    global total
    for m in range(maxseen+1):
        for t in totals:
            td = time_diff(prev_time[m], time)
            total[m][t] += td * prev_current[m][t] * voltage

def update_currents(time):
    global prev_time, prev_current
    for m in range(maxseen+1):
        prev_time[m]=time
        for t in totals:
            prev_current[m][t] = current_fn_map[t](m)


def dump_currents(mote,time):
    global data_file, debug
    m=mote
    if not data_file[m]:
        # Open the file
        data_file[m] = open(basename + str(m)+".dat", "w")
        # Write the header
        data_file[m].write("#%11s" % "time");
        for x in ['total'] + totals:
            data_file[m].write("%12s" % x)
        data_file[m].write("\n")


    if debug: print prev_current[m]['total'], get_current(m)
    if prev_current[m]['total'] != get_current(m):
        # To make a square wave, print the previous currents up to "just
        # before now", then print the new currents
        tm = float(time) / em['CPU_FREQ'] - 0.000001
        data_file[m].write("%12f" % tm)
        for t in ['total'] + totals:
            c = float(prev_current[m][t])
            data_file[m].write("%12f" % c)
        data_file[m].write("\n");
        
        tm = float(time)/em['CPU_FREQ']
        c = get_current(m)
        prev_current[m]['total'] = c
        data_file[m].write("%12f%12f" % (tm,c))
        for t in totals:
            c = current_fn_map[t](m)
            data_file[m].write("%12f" % c);
        data_file[m].write("\n");


dbg_unknown_event_types = {}

# Takes a line, parses it, and performs the appropriate changes to the
# mote state and totals.
# The line format we expect consists of whitespace separated fields:
# DATA can consist of more than 1 field, but the rest must not
# junk POWER: Mote # STATE_TYPE {DATA...} at TIME(in cycles)
def handle_event(l):
    global maxseen, detail

    if debug: print lineno, l
    event = l.split()
    # Check if this is a power event
    if event[1] != "POWER:":
        return
    
    mote = int(event[3])
    if(mote > maxseen): maxseen = mote
    time = event[-1]
    #    print "handling event: '%s'" % l
    #    print event
    if event[4] in event_handler:
        # Update the totals up to just before this event
        update_totals(time)
        # Update the state due to this event
        event_handler[event[4]](mote,time,event[4:-2])
        if detail:
            # At this point, the state is updated, but still have the old
            # current values
            dump_currents(mote,time)
        # Update the prev_current values
        update_currents(time)
        
    else:
        global dbg_unknown_event_types
        if not event[4] in dbg_unknown_event_types:
            print "Don't know how to handle "+event[4]+" events"
            dbg_unknown_event_types[event[4]] = 1



########################  "Main" code ###################

def print_summary():
    global total
    global maxseen
    print "maxseen %d" % maxseen
    for mote in range(maxseen+1):
        sum = 0
        if not prettyprint:
            s = str(mote)+"   "
        for t in totals:
            if prettyprint:
                print "Mote %d, %s total: %f" % (mote, t, total[mote][t])
            else:
                s += "%.4f" % total[mote][t]
                s += "   "
            sum += total[mote][t]
        cpu_active_e = state[mote]['cpu_cycles'] * voltage * em['CPU_ACTIVE']/em['CPU_FREQ']
        if prettyprint: 
            print "Mote %d, cpu_cycle total: %f" % (mote, cpu_active_e)
        else:
            s += "%.4f" % cpu_active_e
            s += "   "
        sum += cpu_active_e
        if prettyprint:
            print "Mote %d, Total energy: %f\n" %(mote, sum)
        else:
            s += "%.4f" % sum
            print s


if __name__=='__main__':
    parse_args()
    initstate()
    lineno = 1
    l=trace.readline()
    while l:
        handle_event(l)
        lineno += 1
        l = trace.readline()

    if summary:
        print_summary()


    



--- NEW FILE: telosA_energy_model.txt ---
# Energy model for the Telos
# see http://www.eecs.harvard.edu/~shnayder/ptossim/ for details
# Lines starting with '#' are comments

# Format: KEY\s+VALUE
# Unless otherwise specified, VALUE is a current in mA
# Value is always assumed to be a number

VOLTAGE	 3.0

# CPU numbers:
# Idle mode is what the CPU is in when not actively executing, but 
# no special action is taken.  The per-active-cycle numbers are added 
# on top of that

CPU_ACTIVE			1.8
CPU_IDLE			0.052
CPU_STANDBY			0.0024
# TODO correct these values
CPU_ADC_NOISE_REDUCTION		1.0
CPU_POWER_DOWN			0.103
CPU_POWER_SAVE			0.110
CPU_EXTENDED_STANDBY		0.223

# The startup mode for the cpu
# TODO correct these values
CPU_INIT			3.2

# This is probably incorrect, but the simulator is hardcoded for 4Mhz, and
# the fixes for that in powertossim aren't merged yet
CPU_FREQ	4000000


# These are from the datasheet.
# Some of the numbers Joe measured match somewhat closely, off by .3mA.
# E.g., RX = 20, TX_00 = 17.7
RADIO_RX   19.7
RADIO_TX_00   17.4
RADIO_TX_01   16.5
RADIO_TX_02   15.2
RADIO_TX_03   13.9
RADIO_TX_04   12.5
RADIO_TX_05   11.2
RADIO_TX_06   9.9
RADIO_TX_07   8.5
#RADIO_TX_08   0
#RADIO_TX_09   0
#RADIO_TX_0A   0
#RADIO_TX_0B   0
#RADIO_TX_0C   0
#RADIO_TX_0E   0
#RADIO_TX_0F   0
#RADIO_TX_40   0
#RADIO_TX_50   0
#RADIO_TX_60   0
#RADIO_TX_70   0
#RADIO_TX_80   0
#RADIO_TX_90   0
#RADIO_TX_C0   0
#RADIO_TX_E0   0
#RADIO_TX_FF	0
RADIO_ON	0
RADIO_OSCON	0

# The default power mode (0x0F, but python doesn't like hex numbers in floats)
RADIO_DEFAULT_POWER  0.0

# TODO correct all the numbers from this point on

# LED
LED		2.2
#default to off
LED_INIT	0

# EEPROM
EEPROM_READ	6.24
EEPROM_WRITE	18.40

#ADC
# we thought it took power, so it's tracked, but it actually doesn't
ADC	0.0

# If the sensor board is plugged in, it draws this much current at all times
SENSOR_BOARD	0.69

# Sensors - don't actually use power beyond the general sensor board power
SENSOR_PHOTO	0
SENSOR_TEMP	0
VOLTAGE	3.0

# Joe's message
#
# In each file, the first row is distance, the second row is average value,
# and the third row is standard deviation.
# 
# recv - packet success rate
# lqi - lqi value as a function of the maximum value.  ie: lqi of 1
# corresponds to 110, lqi of 0 corresponds to 65.
# rssi - signal strength in dBm, you will need to convert to the radio's
# native rssi values (see datasheet)
# 
# here are power numbers for Telos:
# Mote Standby (RTC on)    5.1 uA
# MCU Idle (DCO on)        54.5 uA
# MCU Active               1.8 mA
# MCU + Radio RX           21.8 mA
# MCU + Radio TX (0dBm)    19.5 mA
# MCU + Flash Read         4.1 mA
# MCU + Flash Write        15.1 mA
# 
# wakeup times may not be in current power tossim, but this is the time it
# takes to transition from power down to active, multiplied by the current
# consumed in that state gives you the power you waste by starting the radio
# or MCU... just something that would be nice to get in there eventually. 
# MCU Wakeup               6 us
# Radio Wakeup             580 us
# 
# I also have numbers for MicaZ:
# 
# Mote Standby (RTC on)    27.0 uA
# MCU Idle (DCO on)        3.2 mA 
# MCU Active               8.0 mA
# MCU + Radio RX           23.3 mA
# MCU + Radio TX (0dBm)    21.0 mA
# MCU + Flash Read         9.4 mA
# MCU + Flash Write        21.6 mA
# 
# wakeup info:
# MCU Wakeup               180 us
# Radio Wakeup             860 us
# 
# -Joe
# 
# 
# 
#   1.0000000e+000	  3.0000000e+000	  9.0000000e+000	  1.2000000e+001	  1.5000000e+001	  2.0000000e+001	  2.5000000e+001	  3.0000000e+001	  3.5000000e+001	  5.0000000e+001	  5.5000000e+001	  6.5000000e+001	  7.5000000e+001	  8.5000000e+001	  9.5000000e+001	  1.0500000e+002	  1.1500000e+002	  1.2500000e+002	  1.3500000e+002	  1.5000000e+002	  1.7500000e+002	  1.9000000e+002	  2.0000000e+002	  2.2500000e+002	
#   1.0000000e+000	  1.0000000e+000	  1.0000000e+000	  1.0000000e+000	  1.0000000e+000	  9.9830076e-001	  9.9305679e-001	  9.9191176e-001	  9.7099573e-001	  9.9012721e-001	  8.9959527e-001	  9.2864832e-001	  6.7069641e-001	  7.0898749e-001	  7.7292225e-001	  6.0699019e-001	  4.8387097e-001	  6.6836263e-001	  5.0676507e-001	  5.3571429e-001	  3.6674146e-001	  2.5000000e-001	  1.2433862e-001	  0.0000000e+000	
#   0.0000000e+000	  0.0000000e+000	  0.0000000e+000	  0.0000000e+000	  0.0000000e+000	  1.5217949e-006	  1.5953405e-002	  1.6717950e-002	  8.5805197e-002	  3.1202740e-002	  1.5890991e-001	  2.0383086e-001	  2.7743986e-001	  3.7399393e-001	  2.5652034e-001	  3.2716744e-001	  1.1567529e-001	  4.2758101e-001	  3.1273977e-001	  3.6186641e-001	  2.9827014e-001	  1.3517656e-001	  2.6736732e-001	  0.0000000e+000	
# 
# 
# 
#   1.0000000e+000	  3.0000000e+000	  9.0000000e+000	  1.2000000e+001	  1.5000000e+001	  2.0000000e+001	  2.5000000e+001	  3.0000000e+001	  3.5000000e+001	  5.0000000e+001	  5.5000000e+001	  6.5000000e+001	  7.5000000e+001	  8.5000000e+001	  9.5000000e+001	  1.0500000e+002	  1.1500000e+002	  1.2500000e+002	  1.3500000e+002	  1.5000000e+002	  1.7500000e+002	  1.9000000e+002	  2.0000000e+002	  2.2500000e+002	
#  -5.0000000e+000	 -3.6972666e+001	 -3.7645155e+001	 -5.2282295e+001	 -5.8172419e+001	 -5.9801555e+001	 -6.2774638e+001	 -6.8945321e+001	 -7.0625093e+001	 -7.1370049e+001	 -7.0580249e+001	 -7.1120391e+001	 -7.0170213e+001	 -7.1000000e+001	 -7.0316849e+001	 -7.1000000e+001	 -7.0041593e+001	 -7.1200000e+001	 -7.6100000e+001	 -7.8800000e+001	 -8.0000000e+001	 -8.0229282e+001	 -8.2024194e+001	 -8.5957447e+001	
#   0.0000000e+000	  5.4443280e+000	  3.7133265e+000	  2.3515942e+000	  3.4909166e+000	  3.8473819e+000	  3.5159615e+000	  4.1263230e+000	  3.4460830e+000	  4.5158536e+000	  7.6943596e+000	  1.3019756e+001	  1.7342540e+001	  2.1362796e+001	  1.4857934e+001	  3.2027754e+001	  2.3495782e+001	  1.4985474e+000	  1.3997791e+001	  8.3433746e+000	  3.4261554e+000	  7.9204145e+000	  1.4034564e+001	  2.0170351e+000	
# 
# 
# 
#   1.0000000e+000	  3.0000000e+000	  9.0000000e+000	  1.2000000e+001	  1.5000000e+001	  2.0000000e+001	  2.5000000e+001	  3.0000000e+001	  3.5000000e+001	  5.0000000e+001	  5.5000000e+001	  6.5000000e+001	  7.5000000e+001	  8.5000000e+001	  9.5000000e+001	  1.0500000e+002	  1.1500000e+002	  1.2500000e+002	  1.3500000e+002	  1.5000000e+002	  1.7500000e+002	  1.9000000e+002	  2.0000000e+002	  2.2500000e+002	
#   9.3167928e-001	  9.3172050e-001	  9.2838997e-001	  9.2618378e-001	  9.2710038e-001	  9.2410780e-001	  9.1113900e-001	  9.0321637e-001	  8.7807560e-001	  8.9593267e-001	  7.9572783e-001	  8.3656970e-001	  5.8661251e-001	  6.6189559e-001	  6.3550314e-001	  4.9604161e-001	  3.3056241e-001	  5.3810073e-001	  3.5478245e-001	  4.4390572e-001	  3.6915175e-001	  2.7706553e-001	  1.4657210e-001	  0.0000000e+000	
#   4.0700328e-003	  3.8181885e-003	  4.8851738e-003	  6.6601911e-003	  6.0063107e-003	  7.7624898e-003	  3.1499005e-002	  3.9931096e-002	  9.7546236e-002	  4.1023312e-002	  1.7006415e-001	  1.2513008e-001	  1.7504235e-001	  2.8414129e-001	  1.8009302e-001	  2.0437215e-001	  1.2140026e-001	  2.5288831e-001	  1.4113228e-001	  1.9154149e-001	  1.5625198e-001	  1.0901758e-001	  3.3693791e-002	  0.0000000e+000	
# 
# 

--- NEW FILE: telosB_energy_model.txt ---
# Energy model for the Telos
# see http://www.eecs.harvard.edu/~shnayder/ptossim/ for details
# Lines starting with '#' are comments

# Format: KEY\s+VALUE
# Unless otherwise specified, VALUE is a current in mA
# Value is always assumed to be a number

VOLTAGE	 3.0

# CPU numbers:
# Idle mode is what the CPU is in when not actively executing, but 
# no special action is taken.  The per-active-cycle numbers are added 
# on top of that

CPU_ACTIVE			1.8
CPU_IDLE			0.0545
CPU_STANDBY			0.0051
# TODO correct these values
CPU_ADC_NOISE_REDUCTION		1.0
CPU_POWER_DOWN			0.103
CPU_POWER_SAVE			0.110
CPU_EXTENDED_STANDBY		0.223

# The startup mode for the cpu
# TODO correct these values
CPU_INIT			3.2

# This is probably incorrect, but the simulator is hardcoded for 4Mhz, and
# the fixes for that in powertossim aren't merged yet
CPU_FREQ	4000000


# These are from the datasheet.
# Some of the numbers Joe measured match somewhat closely, off by .3mA.
# E.g., RX = 20, TX_00 = 17.7
RADIO_RX   19.7
RADIO_TX_00   17.4
RADIO_TX_01   16.5
RADIO_TX_02   15.2
RADIO_TX_03   13.9
RADIO_TX_04   12.5
RADIO_TX_05   11.2
RADIO_TX_06   9.9
RADIO_TX_07   8.5
#RADIO_TX_08   0
#RADIO_TX_09   0
#RADIO_TX_0A   0
#RADIO_TX_0B   0
#RADIO_TX_0C   0
#RADIO_TX_0E   0
#RADIO_TX_0F   0
#RADIO_TX_40   0
#RADIO_TX_50   0
#RADIO_TX_60   0
#RADIO_TX_70   0
#RADIO_TX_80   0
#RADIO_TX_90   0
#RADIO_TX_C0   0
#RADIO_TX_E0   0
#RADIO_TX_FF	0
RADIO_ON	0
RADIO_OSCON	0

# The default power mode (0x0F, but python doesn't like hex numbers in floats)
RADIO_DEFAULT_POWER  0.0

# TODO correct all the numbers from this point on

# LED
LED		2.2
#default to off
LED_INIT	0

# EEPROM
EEPROM_READ	6.24
EEPROM_WRITE	18.40

#ADC
# we thought it took power, so it's tracked, but it actually doesn't
ADC	0.0

# If the sensor board is plugged in, it draws this much current at all times
SENSOR_BOARD	0.69

# Sensors - don't actually use power beyond the general sensor board power
SENSOR_PHOTO	0
SENSOR_TEMP	0
VOLTAGE	3.0

# Joe's message
#
# In each file, the first row is distance, the second row is average value,
# and the third row is standard deviation.
# 
# recv - packet success rate
# lqi - lqi value as a function of the maximum value.  ie: lqi of 1
# corresponds to 110, lqi of 0 corresponds to 65.
# rssi - signal strength in dBm, you will need to convert to the radio's
# native rssi values (see datasheet)
# 
# here are power numbers for Telos:
# Mote Standby (RTC on)    5.1 uA
# MCU Idle (DCO on)        54.5 uA
# MCU Active               1.8 mA
# MCU + Radio RX           21.8 mA
# MCU + Radio TX (0dBm)    19.5 mA
# MCU + Flash Read         4.1 mA
# MCU + Flash Write        15.1 mA
# 
# wakeup times may not be in current power tossim, but this is the time it
# takes to transition from power down to active, multiplied by the current
# consumed in that state gives you the power you waste by starting the radio
# or MCU... just something that would be nice to get in there eventually. 
# MCU Wakeup               6 us
# Radio Wakeup             580 us
# 
# I also have numbers for MicaZ:
# 
# Mote Standby (RTC on)    27.0 uA
# MCU Idle (DCO on)        3.2 mA 
# MCU Active               8.0 mA
# MCU + Radio RX           23.3 mA
# MCU + Radio TX (0dBm)    21.0 mA
# MCU + Flash Read         9.4 mA
# MCU + Flash Write        21.6 mA
# 
# wakeup info:
# MCU Wakeup               180 us
# Radio Wakeup             860 us
# 
# -Joe
# 
# 
# 
#   1.0000000e+000	  3.0000000e+000	  9.0000000e+000	  1.2000000e+001	  1.5000000e+001	  2.0000000e+001	  2.5000000e+001	  3.0000000e+001	  3.5000000e+001	  5.0000000e+001	  5.5000000e+001	  6.5000000e+001	  7.5000000e+001	  8.5000000e+001	  9.5000000e+001	  1.0500000e+002	  1.1500000e+002	  1.2500000e+002	  1.3500000e+002	  1.5000000e+002	  1.7500000e+002	  1.9000000e+002	  2.0000000e+002	  2.2500000e+002	
#   1.0000000e+000	  1.0000000e+000	  1.0000000e+000	  1.0000000e+000	  1.0000000e+000	  9.9830076e-001	  9.9305679e-001	  9.9191176e-001	  9.7099573e-001	  9.9012721e-001	  8.9959527e-001	  9.2864832e-001	  6.7069641e-001	  7.0898749e-001	  7.7292225e-001	  6.0699019e-001	  4.8387097e-001	  6.6836263e-001	  5.0676507e-001	  5.3571429e-001	  3.6674146e-001	  2.5000000e-001	  1.2433862e-001	  0.0000000e+000	
#   0.0000000e+000	  0.0000000e+000	  0.0000000e+000	  0.0000000e+000	  0.0000000e+000	  1.5217949e-006	  1.5953405e-002	  1.6717950e-002	  8.5805197e-002	  3.1202740e-002	  1.5890991e-001	  2.0383086e-001	  2.7743986e-001	  3.7399393e-001	  2.5652034e-001	  3.2716744e-001	  1.1567529e-001	  4.2758101e-001	  3.1273977e-001	  3.6186641e-001	  2.9827014e-001	  1.3517656e-001	  2.6736732e-001	  0.0000000e+000	
# 
# 
# 
#   1.0000000e+000	  3.0000000e+000	  9.0000000e+000	  1.2000000e+001	  1.5000000e+001	  2.0000000e+001	  2.5000000e+001	  3.0000000e+001	  3.5000000e+001	  5.0000000e+001	  5.5000000e+001	  6.5000000e+001	  7.5000000e+001	  8.5000000e+001	  9.5000000e+001	  1.0500000e+002	  1.1500000e+002	  1.2500000e+002	  1.3500000e+002	  1.5000000e+002	  1.7500000e+002	  1.9000000e+002	  2.0000000e+002	  2.2500000e+002	
#  -5.0000000e+000	 -3.6972666e+001	 -3.7645155e+001	 -5.2282295e+001	 -5.8172419e+001	 -5.9801555e+001	 -6.2774638e+001	 -6.8945321e+001	 -7.0625093e+001	 -7.1370049e+001	 -7.0580249e+001	 -7.1120391e+001	 -7.0170213e+001	 -7.1000000e+001	 -7.0316849e+001	 -7.1000000e+001	 -7.0041593e+001	 -7.1200000e+001	 -7.6100000e+001	 -7.8800000e+001	 -8.0000000e+001	 -8.0229282e+001	 -8.2024194e+001	 -8.5957447e+001	
#   0.0000000e+000	  5.4443280e+000	  3.7133265e+000	  2.3515942e+000	  3.4909166e+000	  3.8473819e+000	  3.5159615e+000	  4.1263230e+000	  3.4460830e+000	  4.5158536e+000	  7.6943596e+000	  1.3019756e+001	  1.7342540e+001	  2.1362796e+001	  1.4857934e+001	  3.2027754e+001	  2.3495782e+001	  1.4985474e+000	  1.3997791e+001	  8.3433746e+000	  3.4261554e+000	  7.9204145e+000	  1.4034564e+001	  2.0170351e+000	
# 
# 
# 
#   1.0000000e+000	  3.0000000e+000	  9.0000000e+000	  1.2000000e+001	  1.5000000e+001	  2.0000000e+001	  2.5000000e+001	  3.0000000e+001	  3.5000000e+001	  5.0000000e+001	  5.5000000e+001	  6.5000000e+001	  7.5000000e+001	  8.5000000e+001	  9.5000000e+001	  1.0500000e+002	  1.1500000e+002	  1.2500000e+002	  1.3500000e+002	  1.5000000e+002	  1.7500000e+002	  1.9000000e+002	  2.0000000e+002	  2.2500000e+002	
#   9.3167928e-001	  9.3172050e-001	  9.2838997e-001	  9.2618378e-001	  9.2710038e-001	  9.2410780e-001	  9.1113900e-001	  9.0321637e-001	  8.7807560e-001	  8.9593267e-001	  7.9572783e-001	  8.3656970e-001	  5.8661251e-001	  6.6189559e-001	  6.3550314e-001	  4.9604161e-001	  3.3056241e-001	  5.3810073e-001	  3.5478245e-001	  4.4390572e-001	  3.6915175e-001	  2.7706553e-001	  1.4657210e-001	  0.0000000e+000	
#   4.0700328e-003	  3.8181885e-003	  4.8851738e-003	  6.6601911e-003	  6.0063107e-003	  7.7624898e-003	  3.1499005e-002	  3.9931096e-002	  9.7546236e-002	  4.1023312e-002	  1.7006415e-001	  1.2513008e-001	  1.7504235e-001	  2.8414129e-001	  1.8009302e-001	  2.0437215e-001	  1.2140026e-001	  2.5288831e-001	  1.4113228e-001	  1.9154149e-001	  1.5625198e-001	  1.0901758e-001	  3.3693791e-002	  0.0000000e+000	
# 
# 



More information about the Tinyos-beta-commits mailing list