From 295a2514290dbb0537dbfb76ecdc2e8e0c0eaad0 Mon Sep 17 00:00:00 2001 From: Dan White Date: Thu, 3 Feb 2011 17:56:49 -0600 Subject: [PATCH] Add sanitized scripts for public consumption. --- chrome | 6 ++ cleanup-timesamples | 12 +++ extblock | 63 +++++++++++++ findchips.sh | 8 ++ getuntil.pl | 36 +++++++ interleave.sh | 72 ++++++++++++++ lcdoff | 2 + note | 40 ++++++++ octopart.sh | 9 ++ parent_has.sh | 18 ++++ sms | 26 +++++ sppp | 20 ++++ tag | 160 +++++++++++++++++++++++++++++++ tdrec | 73 +++++++++++++++ termcolors.sh | 29 ++++++ texify | 47 ++++++++++ textmail | 26 +++++ vimpager | 56 +++++++++++ vwf2pwl.py | 224 ++++++++++++++++++++++++++++++++++++++++++++ 19 files changed, 927 insertions(+) create mode 100755 chrome create mode 100755 cleanup-timesamples create mode 100755 extblock create mode 100755 findchips.sh create mode 100755 getuntil.pl create mode 100755 interleave.sh create mode 100755 lcdoff create mode 100755 note create mode 100755 octopart.sh create mode 100755 parent_has.sh create mode 100755 sms create mode 100755 sppp create mode 100755 tag create mode 100755 tdrec create mode 100755 termcolors.sh create mode 100755 texify create mode 100755 textmail create mode 100755 vimpager create mode 100755 vwf2pwl.py 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('') + -- 2.25.1