xschem/src/utile/stimuli.awk

928 lines
25 KiB
Awk
Executable File

#!/usr/bin/awk -f
# File: stimuli.awk
#
# This file is part of XSCHEM,
# a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit
# simulation.
# Copyright (C) 1998-2023 Stefan Frederik Schippers
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# convert from Lsim like stimuli file to spice PWL form:
# Stefan Schippers, 02-08-1999
# 04-08-1999: -bus notation is now supported
# 03-09-1999: -avoid writing pwl pairs if signal does non change
# 09-09-1999: -allow "z" values,
# -allow binary form mixed with hex: 12aa'0010011'ffff
# any character other than the allowed ones can be put
# in between.
# -correctly pad with z's missing MSB's (but see below....)
# -avoid negative time steps for (incorrectly given)
# stimuli files like:
# set wen 1
# set wen 0
# set wen 1
# ....
# -allow hi-Z state (!!!!!!) . This is done using a
# resistor vith value equal to a pwl auxiliary source
# in series to the voltage source
# -"eldo" or "spice" or "dump" keyword, which allows writing text that is
# copied directly without any interpretation, ex:
# eldo vwen_pad wen_pad 0 pulse 0 1.8 0 1n 1n 50n 100n
# 14-09-1999: - fixed horrible bug: string compare instead of numeric compare
# ....if(time <= pwltmp2)....
# - new feature: unspecified bits in bus assignment will
# preserve old values, added "x" or "X" for a don't
# change condition
# - powermill vector file is now ordered: signal list is in the
# same order as signal / bus declaration, for easier debugging
# - some performance optimizations (less split() calls).
# 17-09-1999: - added beginfile filename ..... endfile
# to write commands that are dumped to the named file,
# without any translation
# 20-09-1999 - eliminated the use of concatenated strings and split functions.
# 20-09-1999 - added "new_powermill" format that writes epic stimuli files
# using force_node_v ... and rel_node_v ...
# 23-09-1999 - added "eldo_simple" format, which prints only ideal voltage
# sources, not allowing hi-z state, used to generate powermill
# spicelike stimuli.
# - the routine that breaks long lines is now embedded
# - new sintax: stimuli are enclosed in beginfila name ... endfile
# keywords, allowing mixed formats on different files
# 25-09-1999 - new "origin" keyword that shifts the stimulus @ origin
# to time zero. Used to restart powermill simulations.
# 27-09-1999 - bugfixes (dump lines are printed at the end of stimuli file)
# 28-09-1999 - heap sort routine replaces insertion sort, (N log2(N) vs N^2)
# 11-11-1999 - When using hierarchical nodes (xi0.iref) substitute dots with
# underscores when using that node name for auxiliary nodes and
# voltage generator names, in eldo format.
# 30-12-1999 - fixed a bug in the hsort routine when one element arrays are passed.
# - prefixing a bus assignment with the tilde char (~) produces inverted data:
# ex: set apad ~AA'0101'FF ---> 0101 0101 1010 0000 0000
# - NEW!!!! added relative_powermill format, which generates stimuli files
# with no explicit reference to absolute time, usefull for interactive mode
# simulations, (generated file can be read with read_cmd_file command)
# example:
# rel_node_v no=aaa
# cont 0.002u
# force_node_v no=aaa v=0
# cont 1u
# rel_node_v no=aaa
# cont 0.002u
# force_node_v no=aaa v=3
# cont 1u
# rel_node_v no=aaa
# cont 0.002u
# force_node_v no=aaa v=0
# 01/01/2000 - Fixed a bug when printing the new relative_powermill format:
# when bus assignment is incomplete, tobinary() pads with
# spaces the undefined bus MSBits; in this case nothing must
# be forced on these signals. a test on space char is introduced.
# By the way, why not padding with "x" chars which mean don't
# change?
# 01/01/2000 - tobinary() pads missing bits with "x" chars, removed the test
# on space described above. I hope this does not introduce
# side effects/bugs.
# 10/01/2000 - Removed explicit pathnames. this is no more an awk script but a
# sh script, which in turn runs awk.
# 21/01/2000 - bugfix: the last "set whatever_node 1" assigment in stimuli file
# was incorrectly translated to "force_node_v no=whatever_node v=1"
# forcing thus to 1V instead of the Vcc value (which is normally <> 1V).
# 02-02-2000 - better precision using OFMT variable
# 30-03-2000 - added "release" keyword, to release signals before set for the first
# assignment (relative_powermill only)
# 01-06-2000 - dump lines are printed in the position they appear, not at end of file.
# eldo and spice keywords work as before
# 24-10-2001 - fixed a bug in write_pwl_pair.(incorrect eldo stimuli generation in
# case of assignment at time=previous time+slope).
# 21-11-2001 - NEW! ncsim format
# 03-12-2001 - clock and stop_clock directives, handled by external clock.awk program
# 04-12-2001 - Improvements in ncsim format (dont cares, single bit and bus slice
# assignments
# 12-07-2002 - Improvements in the clock keyword, now high and low voltage levels can
# be specified too, no backward compatibility issues, see help file
# When pressing the Translate button the simulated time is printed
# 24-07-2002 - various bug fixes (ncsim bus slice notation using () instead of [] to
# avoid confusing the ncsim TCL interpreter,when using the ncsim source
# command )
# 23-08-2002 - in ncsim format comments are printed on translated file to indicate the
# beginning of an alias
# 28-10-2002 - optional index delimiters in buswidth declaration: ex: buswidth add 4 < >
# --> add<3> add<2> add<1> add<0>
# 28-10-2002 - create_eldo_bus keyword can be specified to force bus creation for xelga
# plots even when the eldo_simple option is used
# 30-10-2002 - Optional 4th parameter on set command specifies series resistance:
# set vxp 8.0 20000 ==> 20K resistance
# 29-10-2003 - New keyword "ground" to specify low voltage level (Vil), similarly to "voltage" for Vih
# 08-09-2005 - New ground_node keyword for specifying different gnd node for sources
# 20100301 - new syntax for set instruction,
# set <signal> <sigval> [res=<resval>] [vhi=<hival>] [vlo=<lowval>] [slope=<slopeval>]
# all values can be parametrs and simple arithmetic expressions with parameters
# - added simple expression parser on params, supported operators : +, -, *, /, expressions
# evaluated frol left to right, no parenthesis, and no operator priority..
# examples:
# param tck 2500
# param tck_2 tck/2
# param tds 300
# param vx 5.5
# set a vx-0.3
# s tck-tds
#
#
#
# sample input:
# time 0
# slope 0.002
# unit u
# voltage 1.8
# bus apad apad8 apad7 apad6 apad5 apad4 apad3 apad2 apad1 apad0
#
# set vneg_h 1 ; set initial state
# set vnegon 1
# set vxws_off 1
# set arrpwh 1
# set split_negv 0
# set sw_to_neg 1
# set vxh 0
# set apad 000
#
# s 110
#
# set apad 1ff
# set arrpwh 0
# s 8
# set vxh 1
# s 0.04
# set vnegon 0
# s 7
#
# usage:
# expand_alias.awk stimuli3 | clock.awk |stimuli.awk
BEGIN{
OFMT="%.9g" # better precision
filename= ARGV[1]
ARGC=1
invert=0 # used for invert bus flag (tilde prefix)
origin=0
format="relative_powermill"
roff=1e9
ron=0.001
time=0
slope=0.002
voltage=1.8
ground=0
unit="u"
gndnode="0"
signals=0
powmill_statement=0
halfvoltageset=0 # 20160412
file="stimuli.ace"
for(i=0;i<=127;i++)
{
val[sprintf("%c",i)]=i # value of char: val["0"]=45
char[i]=sprintf("%c",i) # char[48]="0"
}
}
/^[ \t]*beginfile[ \t]+/{
reset_all();file=$2
next
}
/<<<alias>>>/{
if(format != "ncsim") next
$0 = $1 " " $2 " " $3 " " $4 # 20100212
}
/^[ \t]*(eldo|spice)[ \t]+/{$1="";$0=substr($0,2);dump[++dumpline]=$0;next}
# 20170419 added {time} to be replaced with actual time value in dump string
/^[ \t]*dump[ \t]+/{$1="";gsub(/{time}/,time); $0=substr($0,2);print $0 >file ;next}
/^[ \t]*origin[ \t]+/{ origin=$2; time=-origin}
/^[ \t]*time[ \t]+/{ time=$2-origin}
/^[ \t]*release[ \t]*/{ if(NF==1) powmill_statement=1}
/^[ \t]*create_eldo_bus/{ create_eldo_bus=1}
/^[ \t]*slope[ \t]+/{ slope=$2}
/^[ \t]*roff[ \t]+/{ roff=$2} # 20160412
/^[ \t]*ron[ \t]+/{ ron=$2} # 20170227
/^[ \t]*halfvoltage[ \t]+/{ halfvoltage=$2; halfvoltageset=1} # 20160412
/^[ \t]*unit[ \t]+/{ unit=$2}
/^[ \t]*ground_node[ \t]+/{ gndnode=$2}
/^[ \t]*format[ \t]+/{
if($2=="hspice") {
format="eldo"
variant="hspice"
}
else if($2=="hspice_simple") {
format="eldo_simple"
variant="hspice"
}
else format=$2
}
/^[ \t]*ground[ \t]+/{
ground=$2
if(!halfvoltageset) { # 20170405
if(is_number(voltage) && is_number(ground)) {
halfvoltage=(voltage+ground) / 2
} else {
halfvoltage = "'(" voltage "+" ground ")/2)'"
}
}
}
/^[ \t]*voltage[ \t]+/{
voltage = $2
if(!halfvoltageset) { # 20170405
if(is_number(voltage) && is_number(ground)) {
halfvoltage=(voltage+ground) / 2
} else {
halfvoltage = "'(" voltage "+" ground ")/2'"
}
}
}
/^[ \t]*reset_sim[ \t]*/{if(format=="ncsim") print "reset" >file} # usefull in ncsim
/^[ \t]*s[ \t]+/{
time+=$2
if(format=="ncsim" && time >=0 )
{
print "run " $2 " " unit "s" >file
}
if(format=="relative_powermill" && time >=0)
{
if(powmill_statement>0)
{
for(i in set_list)
print "rel_node_v no=" i>file
print "\ncont " slope unit "\n">file
}
for(i in set_list)
{
v=set_list[i]
if(v ~ /^[10]$/) {vv=(v==1 ? voltage:ground)}
else if(v ~ /^[zZ]$/) {vv=halfvoltage}
else {vv = v}
if(v !~ /[zZ]/) print "force_node_v no=" i " v=" vv>file
}
print "\ncont " $2 unit "\n">file
print "; time= " time > file
powmill_statement++
delete set_list
}
}
/^[ \t]*buswidth[ \t]+/{
openbracket= $4 != "" ? $4 : "["
closebracket= $5 != "" ? $5 : ( $4 !="" ? "": "]" )
buswidth[$2]=$3
for(i=($3); i>=1;i--)
bus[$2,i]=$2 openbracket $3-i closebracket
}
/^[ \t]*bus[ \t]+/{
buswidth[$2]=NF-2
for(i=3;i<=NF;i++)
{
bus[$2 , i-2]=$i
}
}
{ if(file=="") next}
/^[ \t]*endfile[ \t]*$/{ end_file();next }
/^[ \t]*endfile[ \t]*;.*$/{ end_file();next }
/^[ \t]*set[ \t]+/{
# 20100301
res = ron
vhi = voltage
vlo = ground
slp=slope
sub(/[\t ]*;.*/,"")
for(i=4; i<=NF; i++) {
if($i ~ /^;/) break
#20150918 delete $i after using it
if((i==4) && ($i+0>0) && NF==4 ) { res=$i;$i=""; break}
if(tolower($i) ~ /^r(es)?=/) { res=$i; sub(/^.*=/,"",res); $i="" }
if(tolower($i) ~ /^vhi(gh)?=/) { vhi=$i; sub(/^.*=/,"",vhi); $i="" }
if(tolower($i) ~ /^vlow?=/) { vlo=$i; sub(/^.*=/,"",vlo); $i="" }
if(tolower($i) ~ /^slo(pe)?=/) { slp=$i; sub(/^.*=/,"",slp); $i="" }
}
$0 = $0 # 20150918
if(!halfvoltageset) { # 20170405
if(is_number(vhi) && is_number(vlo)) {
halfvoltage=(vhi+vlo) / 2
} else {
halfvoltage = "'(" vhi "+" vlo ")/2'"
}
}
if($2 in buswidth)
{
if($3 ~ /^~/) # inversion flag on bus assignment
{
sub(/^~/,"",$3)
invert=1
}
else invert=0
binstring=tobinary($3,buswidth[$2],invert)
if(format=="ncsim" && time >=0)
{
sig= "." $2
gsub(/\./,":",sig)
sub(/^x+/,"",binstring)
num = length(binstring)
quote="\""
w=buswidth[$2]
low=s_i(bus[$2,w]) # LSB bit of the bus
high=s_i(bus[$2,w-num+1]) # MSB bit of the bus
if(num < w && num >1 )
{
sig=sig "(" high ":" low ")" ; quote="\""
}
if(num < w && num ==1)
{
sig=sig "(" low ")" ; quote="'"
}
if($3 !~ /[zZxX]/)
{
print "force " sig " = {" quote binstring quote "}" >file
}
else if($3 ~ /^[zZ]+$/)
{
print "release " sig >file
}
else
{
sig= "." $2
gsub(/\./,":",sig)
for(idx=1; idx<=num;idx++)
{
current_bit=substr(binstring,num - idx+1,1)
if(current_bit ~ /[zZ]/)
{
print "release " sig "(" s_i(bus[$2, w-idx+1]) ")" >file
}
else if(current_bit !~ /[xX]/)
{
print "force " sig "(" s_i(bus[$2, w-idx+1]) ") = {'" current_bit "'}" >file
}
}
}
}
for(i=1;i<=buswidth[$2];i++)
{
s=bus[$2,i]
v=substr(binstring,i,1)
if(v !~ /[xX]/)
{
set_list[s]=v # used to build the set of signals forced between
# successive s lines
}
if(v ~ /[01zZ]/) write_pwl_pair(s,v,res,vhi,vlo,slp)
}
}
else ## not a bus
{
if($3 ~ /^~1/) # inversion flag on signal assignment 20140623
{
$3=0
}
if($3 ~ /^~0/) # inversion flag on signal assignment 20140623
{
$3=1
}
if($3 !~ /^[xX]$/)
{
$3=$0
sub(/^[\t ]*set[\t ]*[^ \t ]+[ \t]*/,"",$3) #20150918
sub(/[ \t]*$/,"",$3)
set_list[$2]=$3 # used to build the set of signals forced between
# successive s lines
write_pwl_pair($2, $3, res, vhi, vlo,slp)
}
if(format=="ncsim" && time >=0)
{
sig= "." $2
gsub(/\./,":",sig)
if($3 !~ /[zZ]/)
{
if($3 ~ /[0-9]*\.[0-9]+/)
{
print "force " sig " = {" $3 "}" >file
}
else if($3 ~ /[0-9]+%/)
{
sub(/%/,"",$3)
print "force " sig " = {" $3 "}" >file
}
else
{
print "force " sig " = {'" $3 "'}" >file
}
}
else
{
print "release " sig >file
}
}
}
}
END{
print total_time unit "s"> "inutile.simulationtime"
}
function end_file(){
if(time > total_time) total_time=time
if(format ~ /^eldo/)
{
print "**************************************" > file
print "* SPICE STIMULI FILE">file
print "* generated from " filename > file
print "**************************************\n" > file
for(i in signalname)
{
use_z = ( (format !~ /_simple/) && signalz[i] )
ix=i
gsub(/\./,"_",ix)
if(!use_z)
printf simplesignalname[i]>file
else
printf signalname[i]>file
for(j=1;j<=signal[i,"n"];j++)
printf "%.9g%c %s ",signal[i,"time",j],unit,signal[i,"value",j] >file
printf "\n">file
if(use_z)
{
if(variant!="hspice")
# 20100224 quotes instead of parenthesis used for value=....
# as per new eldo syntax. this makes it compatible w eldo and hspice
print "R" ix " XX" ix " " i " value='v(VR" ix ")'">file
else
print "R" ix " XX" ix " " i " 'v(VR" ix ")'">file
printf "%s",signalres[i]>file
for(j=1;j<=signal[i,"n"];j++)
printf "%.9g%c %s ",signal[i,"time",j],unit,signalres[i,"value",j] >file
printf "\n">file
}
}
if(use_z || create_eldo_bus )
for(i in buswidth)
{
if( variant != "hspice") {
printf ".setbus " i " " >file
for(j=1;j<=buswidth[i];j++) printf bus[i,j] " " >file;printf "\n">file
print ".plotbus " i " vth=" halfvoltage >file
}
}
}
else if(format ~ /^pow.*mill/)
{
if(unit=="u") mult=1000
else if(unit=="n") mult=1
else {mult=1; print "ERROR: UNKNOWN UNIT">file}
print "; POWERMILL VECTOR FILE">file
print "type vec">file
printf "signal ">file
for(i=1;i<=signals;i++)
printf signal_list[i] " " >file
printf "\n" >file
print "slope " slope*mult>file
print "high " voltage>file
print "low " ground >file
printf "radix ">file
for(i=1;i<=signals;i++) printf "1">file
printf "\n" >file
for(k=1;k<=signals;k++)
{
i=signal_list[k]
n=signal[i,"n"]
signal[i,"time",1]=0
for(j=1;j<=n;j+=2)
{
x=signal[i,"time",j]
if(j>1) x-=slp
v=signal[i,"value",j]
if(v>halfvoltage) vv="1"
if(v==halfvoltage) vv="z"
if(v<halfvoltage) vv="0"
if(output[x]=="") output[x]=chars(signals,"_")
output[x]=setbit(output[x],vv,signals-k)
}
}
lines=0
for(i in output)
{
lines++
line[lines]=output[i]
key[lines]=i*mult
}
hsort(line,key,lines)
powmillstate=chars(signals,"z")
for(i=1;i<=lines;i++)
{
line[i]=preserve_state(line[i],powmillstate,signals)
print key[i],line[i]>file
powmillstate=line[i]
}
}
else if(format=="new_powermill")
{
print "; POWERMILL STIMULI FILE">file
for(k=1;k<=signals;k++)
{
i=signal_list[k]
n=signal[i,"n"]
for(j=1;j<=n;j+=2)
{
x=signal[i,"time",j]
if(j>1) x-=slope
v=signal[i,"value",j]
imped=signalres[i,"value",j]
if(j>=3 && signalres[i,"value",j-2]!=roff) print "rel_node_v no=" i " ti=" x unit>file
else if(j==1 ) print "rel_node_v no=" i " ti=" x unit>file
# <<<<< powermill 5.3 bug: release and force cannot be at same time and release is mandatory before force
# ||
# \/
if(imped!=roff) print "force_node_v no=" i " v=" v " ti=" x+slope unit>file
}
}
}
else if(format=="relative_powermill")
{
if(powmill_statement>0)
{
for(i in set_list)
print "rel_node_v no=" i>file
print "\ncont " slope unit "\n">file
}
for(i in set_list)
{
v=set_list[i]
if(v ~ /^[10]$/) { vv=(v==1? voltage:ground ) }
else if(v ~ /^[zZ]$/) {vv=halfvoltage}
else {vv = v}
if(v !~ /[zZ]/) print "force_node_v no=" i " v=" vv>file
}
}
powmill_statement++
break_lines(file)
print_dump(file)
}
# 20100301 added vhi, vlo
function write_pwl_pair( name, value,res, vhi, vlo,slope, timex, namex,vv,vv1,vv2,tt2,tt1,halfvoltageloc,i,v,n,pwlres,pwltmpres,pwltmp2 )
{
if(!halfvoltageset) { # 20170405
if(is_number(vhi) && is_number(vlo)) {
halfvoltageloc=(vhi+vlo) / 2
} else {
halfvoltageloc = "'(" vhi "+" vlo ")/2'"
}
} else {
halfvoltageloc = halfvoltage
}
if(res != ron) signalz[name] = 1
if(value ~ /^[10]$/) {v= ( value==1 ? vhi : vlo ) ; pwlres=res}
else if(value ~ /^[zZ]$/) {signalz[name] = 1; v=halfvoltageloc; pwlres=roff}
else {v = value; pwlres=res}
namex=name
gsub(/\./,"_",namex)
if(!(name in signalname) )
{
timex=time < 0 ? 0: time
signal_list[++signals]=name
signalname[name]="V" namex " XX" namex " " gndnode " PWL "
simplesignalname[name]="V" namex " " name " " gndnode " PWL "
signal[name,"time",1]= timex
signal[name,"value",1]= v
signal[name,"n"]= 1
# 20170810 0 instead of gndnode
# |
signalres[name]="VR" namex " VR" namex " " 0 " PWL "
signalres[name,"value",1]= pwlres
}
if(signal[name,"value", signal[name,"n"] ]!=v || signalres[name,"value", signal[name,"n"] ]!=pwlres)
{
timex=time < 0 ? 0: time
if(timex==0)
{
n = signal[name,"n"]=1
signal[name,"value",n]= v
signal[name,"time",n]=0
signalres[name,"value",n]= pwlres
}
## 20151112
else if(timex+slope == signal[name,"time",signal[name,"n"]] ) {
n = signal[name,"n"]
signal[name,"value",n]= v
signalres[name,"value",n]= pwlres
}
else
{
if( timex > signal[name,"time",signal[name,"n"]] )
{
n = (signal[name,"n"] += 1)
signal[name,"time",n]=timex
signal[name,"value",n]= signal[name,"value",n-1]
signalres[name,"value",n]= signalres[name,"value",n-1]
}
## 20100302 interpolation if signal change occurs before conpleting previous transaction
else if(timex < signal[name,"time",signal[name,"n"]] ){
n = signal[name,"n"]
vv1 = signal[name,"value",n-1]
vv2 = signal[name,"value",n]
tt1 = signal[name,"time",n-1]
tt2 = signal[name,"time",n]
vv = vv1 + (vv2-vv1)/(tt2-tt1) * (timex-tt1)
signal[name,"time",n]=timex
signal[name,"value",n]= vv
}
## /20100302
if( timex+slope > signal[name,"time",signal[name,"n"]] )
{
n = (signal[name,"n"] += 1)
signal[name,"time",n]=timex+slope
signal[name,"value",n]= v
signalres[name,"value",n]= pwlres
}
}
}
}
function hex(n, i,dec,ch)
{
dec=0
for(i=1;i<=length(n);i++)
{
ch=toupper(substr(n,i,1))
if(val[ch]>=val["A"]) ch=val[ch]-val["A"]+10
else if(val[ch]>=val["0"]) ch=val[ch]-val["0"]
dec=dec*16+ch
}
return dec
}
function bin_invert(s ,a,i,ch )
{
a=""
for(i=1;i<=length(s);i++)
{
ch=substr(s,i,1)
if(ch=="1") ch="0"
else if(ch=="0") ch="1"
a=a ch
}
return a
}
function tobinary(n,width,invert, bin,i,ch,binbegin)
# transform an input numeric string in the allowed format (see help)
# to a binary string, using only 1,0,z, x
{
bin=""
binbegin=0
for(i=1;i<=length(n);i++)
{
ch=substr(n,i,1)
if(ch =="'") # since awk program is quoted, quotes must be escaped
{
binbegin=!binbegin;continue
}
else if(binbegin && ch ~/[01zZ]/)
bin=bin tolower(ch)
else if(binbegin && ch ~/[xX]/)
bin=bin "x"
else if(ch ~ /[0-9a-fA-F]/)
bin=bin binary(hex(ch),4)
else if(ch ~ /[zZ]/)
bin=bin "zzzz"
else if(ch ~ /[xX]/)
bin=bin "xxxx"
else continue
}
bin=substr(bin,1+length(bin)-width)
if(invert) return bin_invert( chars(width-length(bin),"x") bin )
else return chars(width-length(bin),"x") bin
}
function binary( n, width, a,i,str)
# builds a <width> digit binary representation of <n> encoded in a string
{
for(;;)
{
a[i++]=(n%2 ? "1" : "0")
n=int(n/2)
if(!n) break
}
for(i=width-1;i>=0;i--)
{
str = str (a[i] ? a[i]:"0")
}
return str
}
function binval(str, i,n)
# returns the decimal value of the binary number encoded in "str"
{
for(i=1;i<=length(str);i++) n=2*n + substr(str,i,1)
return n
}
# heap sort, this is a N*log2(N) routine
function hsort(array,ra,n, rarray,l,j,ir,i,rra)
{
if(n<=1) return # bug fix: if only one element in array never returns
l=int(n/2)+1
ir=n
for(;;)
{
if(l>1)
{
rra=ra[--l]
rarray=array[l]
}
else
{
rra=ra[ir]
rarray=array[ir]
ra[ir]=ra[1]
array[ir]=array[1]
if(--ir==1)
{
array[1]=rarray
ra[1]=rra
return
}
}
i=l
j=l*2
while(j<=ir)
{
if(j<ir && ra[j] <ra[j+1]) ++j
if(rra<ra[j])
{
array[i]=array[j]
ra[i]=ra[j]
j+=(i=j)
}
else j=ir+1
}
ra[i]=rra
array[i]=rarray
}
}
function setbit( string, replace, pos, reversepos,len)
# returns <string> with bits starting at position <pos>
# set to <replace>, position 0 being relative to the rightmost bit
{
reversepos=length(string)-pos
len = length(replace)
return substr(string,1,reversepos-len) replace substr(string,reversepos+1)
}
function chars(n,c, i,str)
{
str=""
for(i=1;i<=n;i++) str=str c
return str
}
function preserve_state(new,old,n, nn,oo,i,str)
{
str=""
for(i=1;i<=n;i++)
{
nn=substr(new,i,1)
oo=substr(old,i,1)
if(nn=="_") str=str oo
else str=str nn
}
return str
}
function reset_all()
{
signals=0
file=""
dumpline=0
powmill_statement=0
delete signal_list
delete signalname
delete simplesignalname
delete signal
delete signalres
delete output
delete line
delete key
delete dump
time=0
origin=0
}
function break_lines(filename, quote, j, lines, line, l, i, count, style )
{
lines=0
style="+"
close(filename)
while ((getline line[++lines] < filename) > 0);
close(filename)
# 20120410
lines = lines + 0 # do NOT remove, solves a problem with gawk 3.0.5 where a variable used as
# array index is "magically" converted to string
quote=0
for(l=1;l<=lines;l++)
{
$0=line[l]
if($0 ~ /^\* ELDO/) {style="+"}
if($0 ~ /^; POWERMILL/) {style="\\"}
count=0
if(NF==0) print "">filename
# 20150918 dont break quoted expressions
for(i=1;i<=NF;i++)
{
for(j=1; j<=length($i); j++) {
if(substr($i,j,1)=="'") quote = !quote
}
# print "+++ " quote, $i, count
printf "%s ", $i>filename
count++
if(( count>=15 && !quote) || i==NF)
{
# print "break", quote, count, NF
if(style=="+")
{
printf "\n">filename
if(i < NF) printf "+">filename
count=0
}
else if(style=="\\")
{
if(i < NF) printf "\\">filename
printf "\n">filename
count=0
}
}
}
}
}
function is_number(i) # 20170405
{
return i+0==i
}
function s_i(s)
{
sub(/^.*\[/,"",s)
sub(/\].*$/,"",s)
return s
}
function print_dump(filename, i)
{
for(i=1;i<=dumpline;i++) print dump[i] >filename
}