From: Dan White Date: Thu, 3 Feb 2011 23:56:49 +0000 (-0600) Subject: Add sanitized scripts for public consumption. X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=295a2514290dbb0537dbfb76ecdc2e8e0c0eaad0;p=pubbin.git Add sanitized scripts for public consumption. --- diff --git a/chrome b/chrome new file mode 100755 index 0000000..be86e98 --- /dev/null +++ b/chrome @@ -0,0 +1,6 @@ +#!/bin/bash + +# run chromium / google-chrome on current display hack + +DISPDIR=$(echo $DISPLAY | awk -F. '{print $1}') +exec google-chrome --user-data-dir=$HOME/.config/google-chrome/$DISPDIR $@ diff --git a/cleanup-timesamples b/cleanup-timesamples new file mode 100755 index 0000000..dd2763f --- /dev/null +++ b/cleanup-timesamples @@ -0,0 +1,12 @@ +#!/bin/bash + +# cleanup data from timeSampler, +# removes null entries and sorts by time + +TMPFILE=$(tempfile) +for f in $(ls -1 $HOME/.timeSampler.*); do + grep -v "null$" $f | sort > $TMPFILE + cp $TMPFILE $f +done + +rm -f $TMPFILE diff --git a/extblock b/extblock new file mode 100755 index 0000000..669c543 --- /dev/null +++ b/extblock @@ -0,0 +1,63 @@ +#!/usr/bin/perl -w + +# usage: extblock infile rem_out spattern scount epattern ecount +# +# Dan White + +# From infile, start copying the contents to stdout after finding spattern +# scount times. Once epattern has been found ecount times (typically 1), copy +# the remaininder of infile to rem_out. + +# Originally written to iteratively pick out HSPICE listing output related to +# .print statements, e.g.: +# extblock infile remfile "^x" 1 "^y" 1 > print_block.csv + +# There are better ways of doing this, probably with sed or awk, but I don't +# know those languages. + +open(INFILE, $ARGV[0]) or die "Can't open file [ $ARGV[0] ] for reading."; +open(OUTFILE, '>'.$ARGV[1]) or die "Can't open file [ $ARGV[1] ] for writing."; +my $spattern=$ARGV[2]; +my $scount=$ARGV[3]; +my $epattern=$ARGV[4]; +my $ecount=$ARGV[5]; + +my $sc=0; +while() { + #find start pattern + if(/$spattern/) { + if($sc<$scount) { + $sc++; + next; + } else { + last; + } + } + next; +} + +print; +my $ec=1; +while() { + #find end pattern + if(/$epattern/) { + if($ec<$ecount) { + $ec++; + print; + next; + } + #this is the ending line target + print; + last; + } + print; +} + +#copy rest of file to rem_file +#including the previous last line! +print OUTFILE; +while() { + print OUTFILE; +} + + diff --git a/findchips.sh b/findchips.sh new file mode 100755 index 0000000..4202899 --- /dev/null +++ b/findchips.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# dirty hack to quickly look for a chip by PN + +browser=${BROWSER:-"xdg-open"} +encoded=$(echo "$1" | perl -MURI::Escape -lne 'print uri_escape($_)') +$browser "http://www.findchips.com/avail?part=$encoded" + diff --git a/getuntil.pl b/getuntil.pl new file mode 100755 index 0000000..153c335 --- /dev/null +++ b/getuntil.pl @@ -0,0 +1,36 @@ +#!/usr/bin/perl -w + +# getuntil infile start_pattern scount end_pattern ecount +# cat's file until it finds 'pattern' and exits + +if($ARGV[0] eq '-h') { + print "Usage:\n"; + print "getuntil infile start_pattern scount end_pattern ecount\n"; + exit(1); +} + +$infile=$ARGV[0]; +$spattern=$ARGV[1]; +$scount=$ARGV[2]; +$epattern=$ARGV[3]; +$ecount=$ARGV[4]; + +open(IFP, $infile); + +$sc=0; +$ec=0; +while(){ + if ($sc < $scount) { + if (/$spattern/) { $sc++; } + if ($sc == $scount) { print; } + } elsif ($ec < $ecount) { + #within start and end sections + if (/$epattern/) { $ec++; } + print; + } else { + last; + } +} + +exit(0); + diff --git a/interleave.sh b/interleave.sh new file mode 100755 index 0000000..e87b5f6 --- /dev/null +++ b/interleave.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# (C) Dan White , GPL license + +VERBOSE=0 + +function usage() { +cat << EOF +Usage: $0 [-o output.pdf] infile1.pdf [infile2.pdf [...]] + +Output a pdf whose pages are infile1:1, infile2:1 ... infile1:2, infile2:2 +The number of output pages is the length of the longest input file times the +number of input files. +EOF +} + +letters=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) +declare -i nfiles=0 +declare -i maxpages=0 +outfile="output.pdf" +while [ "$1" != "" ]; do + if [ "$1" == "-o" ]; then + #set name of output file to non-default value + outfile=$2 + shift + elif [ "$1" == "-h" ]; then + usage + exit 1 + else + infiles[$nfiles]=$1 + npages[$nfiles]=$(pdftk $1 dump_data | tail -n1 | awk '{print $2}') + [[ npages[$nfiles] -gt $maxpages ]] && maxpages=${npages[$nfiles]} + let "nfiles=nfiles+1" + if [[ $nfiles -gt 26 ]]; then + echo "OOPS: can only handle 26 files to be interleaved presently" + exit 1 + fi + fi + shift +done + +#show some info +if [ $VERBOSE == 1 ]; then + #echo "letters: ${letters[*]}" + echo "infiles: ${infiles[*]}" + echo "npages: ${npages[*]}" + echo "maxpages: $maxpages" +fi + +#do the deed +# +# there are nfiles circular buffers of pages of varying lengths, the number of +# output pages is maxpages*nfiles. +for i in $(seq 1 $maxpages); do + [[ $VERBOSE == 1 ]] && echo "page $i" + #assign each file a letter for referencing with pdftk + pre="" + #cat the appropriate page number of each file, looping through the shorter + #ones, to an aggregate collection of pages + post="" + for fnum in $(seq 0 $(($nfiles -1)) ); do + pre="$pre ${letters[$fnum]}=${infiles[$fnum]}" + post="$post ${letters[$fnum]}$((i % npages[$fnum] +1))" + done + pdftk $pre cat $post output $outfile-p$i.pdf +done + +#cat all the aggregations together into the final page stream +echo "putting all together" +pdftk $outfile-p*.pdf cat output $outfile +rm -f $outfile-p*.pdf + diff --git a/lcdoff b/lcdoff new file mode 100755 index 0000000..2a01805 --- /dev/null +++ b/lcdoff @@ -0,0 +1,2 @@ +#!/bin/bash +xset dpms force off diff --git a/note b/note new file mode 100755 index 0000000..fd81e9a --- /dev/null +++ b/note @@ -0,0 +1,40 @@ +#!/bin/bash + +if [ "$1" == "-h" ]; then + echo "Quick note taking function" + echo "Usage: note [-h] [-f otherFile] [- | note string]" + echo "-f file Append note to FILE instead" + echo "other arguments are appended to \$NOTES_FILE environment variable" + echo "if no arguments, edit note file directly" + exit 1 +fi + +#TIMESTAMP=`date` +TIMESTAMP=`date +"%F %k:%M:%S"` + +# export to a different note file +if [ "$1" == "-f" ]; then + NOTES_FILE=$2 + shift 2 + echo "using file: $NOTES_FILE" >&2 +fi + +# create the time-stamped note +cat << END_NOTE_TEXT >> $NOTES_FILE + +$TIMESTAMP +---------------------------------------- +END_NOTE_TEXT + +#text is from stdin +if [ "$1" == "-" ]; then + cat >> $NOTES_FILE +else + echo $* >> $NOTES_FILE +fi + +# edit the note if no (remaining) arguments +if [ $# -eq 0 ]; then + $EDITOR + $NOTES_FILE +fi + diff --git a/octopart.sh b/octopart.sh new file mode 100755 index 0000000..ade00b1 --- /dev/null +++ b/octopart.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +browser=${BROWSER:-"xdg-open"} + +encoded=$(echo "$1" | perl -MURI::Escape -lne 'print uri_escape($_)') +echo $encoded + +$browser "http://octopart.com/parts/search?q=$encoded&js=on" + diff --git a/parent_has.sh b/parent_has.sh new file mode 100755 index 0000000..27ea180 --- /dev/null +++ b/parent_has.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Dan White + +function parent_has { +# $1 - file/folder to look for in pwd and parents + if [ -e $1 ]; then + return 0 + elif [ $PWD == "/" ]; then + return 1 + fi + + cd $(dirname $PWD) + parent_has "$1" +} + +parent_has "$1" + diff --git a/sms b/sms new file mode 100755 index 0000000..58507b4 --- /dev/null +++ b/sms @@ -0,0 +1,26 @@ +#!/bin/bash + +# Dan White + +SMSTO=${SMSTO:-"dansms"} + +function usage { +cat << EOF +Usage: sms "subject" [filename | -] + +send the contents of stdin or 'filename' to \$SMSTO ($SMSTO) +EOF +} + +if [[ $# -eq 0 ]] || [[ $1 == "-h" ]] ; then + usage + exit 1 +fi + +SUBJECT=$1 + +if [ -r "$2" ]; then + cat "$2" | email -s "$SUBJECT" $SMSTO +else + email -b -s "$SUBJECT" $SMSTO +fi diff --git a/sppp b/sppp new file mode 100755 index 0000000..c553175 --- /dev/null +++ b/sppp @@ -0,0 +1,20 @@ +#!/bin/bash + +# preprocessor for spice files +# lines start with "**" to trigger the parser +# Example +# *spice netlist title +# **ifdef GNUCAP +# +# *gnucap specific stuff +# +# **else +# +# *hspice specific stuff +# +# **endif +# .end +# +gpp -U "" "" "(" "," ")" "(" ")" "#" "\\" \ + -M "**" "\n" " " " " "\n" "(" ")" $@ + diff --git a/tag b/tag new file mode 100755 index 0000000..9e5d288 --- /dev/null +++ b/tag @@ -0,0 +1,160 @@ +#!/usr/bin/env python + +# Dan White + +"""Recurse from current or given directory and display all folders with +tags.""" + +import optparse +import os +import sys +import re + +try: + import cStringIO as StringIO +except ImportError: + import StringIO + +try: + import optcomplete +except ImportError: + optcomplete = None + +#ignore tmp and hidden folders +RE_DO_NOT_FOLLOW_DIR = re.compile(r'^tmp$|^\.') + +#tag prefix, these must match +TAG_PREFIX = '.tag.' +#RE_TAG = re.compile(r'^\.tag') +RE_TAG = re.compile(r'^' + TAG_PREFIX.replace('.', '\.')) + +# +# Options +# +optParser = optparse.OptionParser() +optParser.add_option('-a', '--add', dest='add', action='store', type='string', + help='add TAG to folder', metavar='TAG') + +optParser.add_option('-d', '--delete', dest='delete', action='store', + type='string', + help='remove TAG from folder', metavar='TAG') + +optParser.add_option('-l', '--list', dest='list', action='store_true', + default=False, + help="list tags in all folders which have them") + +optParser.add_option('-t', '--tag', dest='tag', action='store', type='string', + help='list folders which have given comma-sep tag(s)') + +optParser.add_option('-r', '--recurse', dest='recurse', action='store_true', + default=False, + help='recurse into child folders') + +optParser.add_option('-R', '--no-recurse', dest='recurse', action='store_false', + help='do not recurse into child folders (default)') + +_cwd = os.getcwd() +_HOME = os.getenv('HOME') + +def herePath(p, base=None): + '''Return the given path relative to base''' + if base: + return p.replace(base,'.') + else: + return p + + +def listTags(baseDir): + files = os.listdir(baseDir) + tags = [t.replace(TAG_PREFIX, '') for t in files if RE_TAG.match(t)] + tags.sort() + return tags + + +def findTag(tag, baseDir): + s = StringIO.StringIO() + for (path, dirs, files) in os.walk(baseDir): + dirs[:] = [d for d in dirs if not RE_DO_NOT_FOLLOW_DIR.match(d)] + tags = [t.replace(TAG_PREFIX, '') for t in files if t.startswith(TAG_PREFIX)] + if tag in tags: + print>>s, path + return s.getvalue().rstrip() + + +def addTag(tag, baseDir): + try: + open(baseDir + '/' + TAG_PREFIX + tag, 'r') + print "ee's already got one (%s)" % tag + except IOError: + t = open(baseDir + '/' + TAG_PREFIX + tag, 'w') + t.close() + + +def deleteTag(tag, baseDir): + try: + os.remove(baseDir + '/' + TAG_PREFIX + tag) + except OSError: + print 'tag already not present (%s)' % tag + + + +def main(): + if optcomplete: + optcomplete.autocomplete(optParser) + + (opt, args) = optParser.parse_args() + arglen = len(args) + #print opt + #print args + + taglist = [] + if arglen == 0: + walkDir = _cwd + elif arglen == 1: + walkDir = os.path.expandvars(os.path.expanduser(args[0])) + walkDir = walkDir.rstrip(os.sep) + elif arglen >=2: + walkDir = os.path.expandvars(os.path.expanduser(args[0])) + walkDir = walkDir.rstrip(os.sep) + taglist = args[1:] + + if opt.list: + if opt.recurse: + alltags = {} + for (path, dirs, files) in os.walk(walkDir): + dirs[:] = [d for d in dirs if not RE_DO_NOT_FOLLOW_DIR.match(d)] + tags = [t.replace(TAG_PREFIX,'') for t in files + if RE_TAG.match(t)] + tags.sort() + if tags: + for t in tags: + if t in alltags: + alltags[t].append(path) + else: + alltags[t] = [path] + print '%s:' % herePath(path, walkDir) + print '\n'.join(tags) + #usedtags = alltags.keys() + #usedtags.sort() + #print + #print 'tags defined at:' + #for t in usedtags: + #print '%s:' % t + #print '\n'.join(alltags[t]) + else: + print '\n'.join(listTags(walkDir)) + elif opt.tag: + for t in opt.tag.split(',') + taglist: + print 'adding', t + print findTag(t, walkDir) + elif opt.add: + for t in opt.add.split(',') + taglist: + print 'adding', t + addTag(t, walkDir) + elif opt.delete: + for t in opt.delete.split(','): + deleteTag(t, walkDir) + +if __name__ == '__main__': + main() + diff --git a/tdrec b/tdrec new file mode 100755 index 0000000..5e69327 --- /dev/null +++ b/tdrec @@ -0,0 +1,73 @@ +#!/usr/bin/env python + +# recursive todo - runs todo in all sub-directories which have a todo list in +# them and only displays if there is actual output +# +# Dan White +# idea from Bash version by Brian Herlihy +# + +import re +import os +import subprocess +import sys + +# +# semi-volatile options +# + +#replaced with path to current .todo +#HEADER_STRING = 'TODO %s' +HEADER_STRING = '\n=== %s ===' + +#--force-colour necessary to keep color information +DEFAULT_DEVTODO_OPTIONS = '--force-colour --filter -children' + +#do not recurse into these directories +DO_NOT_FOLLOW_DIR_RE = re.compile(r'^tmp$|^\.|^Mail$') + +#re for finding the final newline from todo output immediately before +#the final terminal color-changing code string +LAST_NL_RE = re.compile(r'(\n)(\033\[0m$)') + +usage = '''\ +Usage: %s [devtodo options] +Recursively displays devtodo .todo databases from the current directory. +Default options are: %s ''' + +# +# display usage, pass options to devtodo, or use default options +# +if sys.argv[1:]: + #help if requested + if sys.argv[1] == '-h' or sys.argv[1] == '--help': + print usage % (os.path.basename(sys.argv[0]), DEFAULT_DEVTODO_OPTIONS) + sys.exit() + DEVTODO_OPTIONS = '--force-colour ' + ' '.join(sys.argv[1:]) +else: + DEVTODO_OPTIONS = DEFAULT_DEVTODO_OPTIONS + +DEVTODO_COMMAND = 'todo --database %s/.todo ' + DEVTODO_OPTIONS + +# +# real functionality +# +def herePath(p, base=None): + '''Return the given path relative to base''' + if base: + return p.replace(base,'').lstrip('/') + else: + return p + +cwd = os.getcwd() +for (dpath, dnames, fnames) in os.walk(cwd): + dnames[:] = [d for d in dnames if not DO_NOT_FOLLOW_DIR_RE.match(d)] + if '.todo' in fnames: + #f = os.popen(DEVTODO_COMMAND % dpath, 'r') + f = subprocess.Popen(DEVTODO_COMMAND % dpath, shell=True, + stdout=subprocess.PIPE).stdout + todoOutput = f.read() + if todoOutput: + print HEADER_STRING % herePath(dpath, cwd) + print LAST_NL_RE.sub('\g<2>', todoOutput) + diff --git a/termcolors.sh b/termcolors.sh new file mode 100755 index 0000000..e15d528 --- /dev/null +++ b/termcolors.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# from http://tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html + +# +# This file echoes a bunch of color codes to the +# terminal to demonstrate what's available. Each +# line is the color code of one forground color, +# out of 17 (default + 16 escapes), followed by a +# test use of that color on all nine background +# colors (default + 8 escapes). +# + +T='gYw' # The test text + +echo -e "\n 40m 41m 42m 43m\ + 44m 45m 46m 47m"; + +for FGs in ' m' ' 1m' ' 30m' '1;30m' ' 31m' '1;31m' ' 32m' \ + '1;32m' ' 33m' '1;33m' ' 34m' '1;34m' ' 35m' '1;35m' \ + ' 36m' '1;36m' ' 37m' '1;37m'; + do FG=${FGs// /} + echo -en " $FGs \033[$FG $T " + for BG in 40m 41m 42m 43m 44m 45m 46m 47m; + do echo -en "$EINS \033[$FG\033[$BG $T \033[0m"; + done + echo; +done +echo diff --git a/texify b/texify new file mode 100755 index 0000000..f34a7e7 --- /dev/null +++ b/texify @@ -0,0 +1,47 @@ +#!/bin/bash + +# texify [options] file.tex +# Runs latex on file, runs again if necessary. +# outputs warnings and errors + +# 'rubber' works better... + + +CLEAN=0 +if [ "$1" == "-c" ]; then + shift + CLEAN=1 +fi + +tmpfile=tmp`date +%F-%H%M%S` + +echo "Rerun" > $tmpfile +while grep -q "Rerun\|exist, replaced" $tmpfile; do + #run LaTeX and catch output + echo -n "texify: running LaTeX..." + #latex -interaction=nonstopmode --output-format=pdf $* > $tmpfile + pdflatex -interaction nonstopmode \ + -output-format pdf \ + -halt-on-error \ + $@ > $tmpfile + echo "done" + + #quit on error + if grep -A4 "^!" $tmpfile; then + if grep "pdfTeX warning" $tmpfile; then + continue; + else + rm $tmpfile; + exit 1; + fi + fi +done + +#only print warnings, if any +grep -A1 Warning $tmpfile + +rm $tmpfile +if [ $CLEAN -eq 1 ]; then + rm *.out *.toc *.aux *.log +fi + diff --git a/textmail b/textmail new file mode 100755 index 0000000..ba81260 --- /dev/null +++ b/textmail @@ -0,0 +1,26 @@ +#!/bin/bash + +MYSELF='dan' + +function usage { +cat << EOF +Usage: textmail 'subject' [filename] + +send the contents of stdin or 'filename' to \$MAILTO ($MAILTO) +EOF +} + +if [ $# -eq 0 ] || [ $1 == "-h" ]; then + usage + exit 1 +fi + +SUBJECT=$1 +MAILCMD="email -s $SUBJECT $MYSELF" +MAILCMD="email -s $SUBJECT $MAILTO" + +if [ "$2" == "" ]; then + cat - | $MAILCMD +else + cat $2 | $MAILCMD +fi diff --git a/vimpager b/vimpager new file mode 100755 index 0000000..35f64d1 --- /dev/null +++ b/vimpager @@ -0,0 +1,56 @@ +#!/bin/sh +# Shell script to start Vim with less.vim. +# Read stdin if no arguments were given. + +files=$@ +if [ -z "$files" ]; then files="-"; fi + +less_vim() { + vim -R -c 'let no_plugin_maps = 1' \ + -c 'runtime! macros/less.vim' \ + -c 'set mouse=h' "$@" +} + +do_ps() { + ps fauxw +} + +pproc() { + if uname -s | grep -iq linux; then + ps -p $1 -o comm= + elif uname -s | grep -iq cygwin; then + ps -p $1 | sed -e 's/^I/ /' | grep -v PID + fi +} + +ppid() { + if uname -s | grep -iq linux; then + ps -p $1 -o ppid= + elif uname -s | grep -iq cygwin; then + ps -p $1 | sed -e 's/^I/ /' | grep -v PID | awk '{print $2}' + fi +} + +# Check if called from man or perldoc +MAN_LIKE_PROGS="man\|pydoc\>\|ipython\|python" +if do_ps | grep -q '\(man\|perl\|py\(doc\|thon\)\)\>'; then + proc=$$ + while next_parent=`ppid $proc` && [ $next_parent != 1 ]; do + #echo `pproc $next_parent` + #if pproc $next_parent | grep -q 'man\|pydoc\>'; then + if pproc $next_parent | grep -q $MAN_LIKE_PROGS; then + #echo "found man-like-prog" + perl -pi -e 's/\e\[[^m]*m//g' | col -b \ + | less_vim -c 'set ft=man' -; exit + #less_vim -c 'set ft=man' -; exit + elif pproc $next_parent | grep -q 'perl\(doc\|$\)\>'; then + perl -pi -e 's/\e\[[^m]*m//g' | col -b \ + | less_vim -c 'set ft=man' -; exit + #col -b < $files | less_vim -c "set ft=man" -; exit + fi + proc=$next_parent + done +fi + +#echo "not man-like" +less_vim $files diff --git a/vwf2pwl.py b/vwf2pwl.py new file mode 100755 index 0000000..c90ec80 --- /dev/null +++ b/vwf2pwl.py @@ -0,0 +1,224 @@ +#!/usr/bin/python + +# Dan White + +import os +import sys +import re + +from decimal import Decimal + +try: + import psyco + psyco.full() +except ImportError: + pass + +def usage(): + print >>sys.stderr, ''' +Usage: vwf2pwl.py digitalinputs.vwf + +vwf file format: + [one name=value parameter per line] + [space-separated column labels for voltage source names AND node names] + [one line per bit interval of 0 or 1 for each column, no spaces between] + +Example .vwf contents for testing an adder: + clockdelay=500p + clockrisefall = 100p + risefall=200p + bittime=1n + bitlow=0 + bithigh=5 + a3 a2 a1 a0 b3 b2 b1 b0 + 00000000 + 00010001 + 00010010 + 11111111 + 01011010 + 01011011 + +Include the generated file, which also includes the Voltage-source definitons +for the input nodes as: + .include "foo.pwl" + +The "clockdelay=" parameter, if present, also generates a voltage source for a +clock as "Vclock clock 0 PWL ..." with a rising edge at every bittime with an +offset of clockdelay. Hence, set "clockdelay=" to the maximum setup time of +your registers and the data on each line will be clocked in at the right time. +Parameter "clockrisefall=" is optional to separately specify the clock rise/ +fall time. +''' + + +def info(s): + print 'INFO:', s + + +def error(s): + print 'ERROR:', s + sys.exit(1) + + +def warn(s): + print 'WARNING:', s + + +def mkvwf(d): + t = Decimal('0.0') + + #first bit interval starts at t=0, start from this value + lastbit = d[0] + bitv = Decimal(lastbit) * (bithigh - bitlow) + bitlow + s = '+ 0 %s' % str(bitv) + output(s) + + trf = risefall + tb = bittime - risefall + t += trf + tb + for bit in d[1:]: + if bit != lastbit: + ti = t + trf + tf = ti + tb + lastbitv = Decimal(lastbit) * (bithigh - bitlow) + bitlow + bitv = Decimal(bit) * (bithigh - bitlow) + bitlow + output('+ %s %s' % (str(t), str(lastbitv))) + output('+ %s %s' % (str(ti), str(bitv))) + #output('+ %s %s' % (str(tf), str(bitv))) + + t += trf + tb + lastbit = bit + + +RE_UNIT = re.compile(r'^([0-9e\+\-\.]+)(t|g|meg|x|k|mil|m|u|n|p|f)?') +def unit(s): + """Takes a string and returns the equivalent float. + '3.0u' -> 3.0e-6""" + mult = {'t' :Decimal('1.0e12'), + 'g' :Decimal('1.0e9'), + 'meg':Decimal('1.0e6'), + 'x' :Decimal('1.0e6'), + 'k' :Decimal('1.0e3'), + 'mil':Decimal('25.4e-6'), + 'm' :Decimal('1.0e-3'), + 'u' :Decimal('1.0e-6'), + 'n' :Decimal('1.0e-9'), + 'p' :Decimal('1.0e-12'), + 'f' :Decimal('1.0e-15')} + + m = RE_UNIT.search(s.lower()) + try: + if m.group(2): + return Decimal(Decimal(m.group(1)))*mult[m.group(2)] + else: + return Decimal(m.group(1)) + except: + error("Bad unit: %s" % s) + + + +if len(sys.argv) < 2: + usage() + sys.exit(1) + +vwf = sys.argv[1] +if not vwf.endswith('.vwf'): + usage() + print "Error: File must have a .vwf extension" + sys.exit(1) + +pwl = vwf.replace('.vwf', '.pwl') + +fvwf = open(vwf) +fpwl = open(pwl, 'w') + + +#read in the vwf definition file + +#get parameters +requiredParams = ('risefall', 'bittime', 'bitlow', 'bithigh') +params = {'clockdelay':None, 'clockrisefall':None} + +line = fvwf.readline() +while '=' in line: + name, value = line.split('=') + name = name.strip() + value = value.strip() + params[name] = value + line = fvwf.readline() + +#check +for p in requiredParams: + if p not in params: + error("%s is not specified, aborting." % p) + +info('Parameters:') +for p,v in params.iteritems(): + info(' %s = %s' % (p, v)) + +if params['clockdelay']: + info("Adding a clock at 'clock' node.") + +#get column labels +inputs = [c.strip() for c in line.strip().split()] +info("Columns: %s" % inputs) + +#read in data +data = {} +for i in inputs: + data[i] = [] + +for line in fvwf: + vector = line.strip() + if len(vector) != len(inputs): + error("Must have same # characters as column labels: %s" % line.strip()) + + i = 0 + for bit in vector: + data[inputs[i]].append(bit) + i += 1 + +#outputs +output = lambda s: fpwl.write(s + '\n') + +#get the numbers +risefall = unit(params['risefall']) +bittime = unit(params['bittime']) +bitlow = unit(params['bitlow']) +bithigh = unit(params['bithigh']) + +#output clock definition if specified +if params['clockdelay']: + #calculate clock high time + if params['clockrisefall']: + clockrisefall = unit(params['clockrisefall']) + else: + clockrisefall = risefall + + clockhigh = Decimal('0.5') * (bittime - clockrisefall) + clockperiod = bittime + + params['clockrisefall'] = str(clockrisefall) + params['clockhigh'] = str(clockhigh) + params['clockperiod'] = str(clockperiod) + + clk = 'Vclock clock 0 pulse(%(bitlow)s %(bithigh)s %(clockdelay)s %(clockrisefall)s %(clockrisefall)s %(clockhigh)s %(clockperiod)s)' % params + info(clk) + output(clk) + output('') + +#output each input source +for name in inputs: + d = data[name] + + s = 'V%s %s 0 PWL' % (name, name) + info(s) + output(s) + + #first bit interval starts at t=0, start from this value + bit = d[0] + bitv = Decimal(bit) * (bithigh - bitlow) + bitlow + + mkvwf(d) + output('') +