771 lines
19 KiB
Awk
Executable File
771 lines
19 KiB
Awk
Executable File
#!/usr/bin/awk -f
|
|
#
|
|
# File: vhdl.awk
|
|
#
|
|
# This file is part of XSCHEM,
|
|
# a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit
|
|
# simulation.
|
|
# Copyright (C) 1998-2021 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
|
|
|
|
|
|
|
|
{ # default is to print the current line if any other rule is not executed.
|
|
no_print=0
|
|
}
|
|
|
|
# 20080213 packages are marked so they will be printed verbatim
|
|
/\/\/\/\/ begin package/, /\/\/\/\/ end package/{
|
|
if($0 ~ /^\/\/\/\//) next
|
|
else print $0
|
|
next
|
|
}
|
|
|
|
/\/\/\/\/ begin user declarations/, /\/\/\/\/ end user declarations/{
|
|
if($0 ~ /^\/\/\/\//) next
|
|
else user_declarations = user_declarations "\n" $0
|
|
next
|
|
}
|
|
|
|
/\/\/\/\/ begin user attributes/, /\/\/\/\/ end user attributes/{
|
|
if($0 ~ /^\/\/\/\//) next
|
|
else user_attributes = user_attributes "\n" $0
|
|
next
|
|
}
|
|
|
|
/---- start primitive/{primitive_line=""; primitive_mult=$4;primitive=1; next} # 20071217
|
|
/---- end primitive/{ # 20071217
|
|
primitive=0
|
|
# print "<<<<" primitive_line ">>>>"
|
|
$0 = primitive_line
|
|
gsub(/----pin\(/, " ----pin(",$0)
|
|
for(j=1;j<= primitive_mult; j++) {
|
|
for(i=1;i<=NF;i++) {
|
|
prim_field=$i
|
|
if($i ~ /^----pin\(.*\)/) {
|
|
sub(/----pin\(/,"",prim_field)
|
|
sub(/\)$/,"",prim_field)
|
|
pport_mult = split(prim_field, prim_field_array,/,/)
|
|
|
|
|
|
# if bussed port connected to primitive and primitive mult==1 print only basename of bus
|
|
if(primitive_mult==1 && pport_mult>1) {
|
|
if(check2(prim_field_array, pport_mult))
|
|
printf "%s(%s downto %s) ", s_b(prim_field_array[1]),
|
|
s_i(prim_field_array[1]), s_i(prim_field_array[pport_mult])
|
|
else {
|
|
printf " ( "
|
|
for(s=1;s<= pport_mult; s++) {
|
|
printf "%s", prim_field_array[s]
|
|
if(s<pport_mult) printf "&"
|
|
}
|
|
printf ") "
|
|
}
|
|
|
|
} else {
|
|
|
|
# printf "%s ", prim_field_array[1]
|
|
## 20170917
|
|
printf "%s ", to_round_brackets(prim_field_array[1+(j-1)%pport_mult])
|
|
}
|
|
}
|
|
else if($i ~ /^----name\(.*\)/) {
|
|
sub(/----name\(/,"",prim_field)
|
|
sub(/\)$/,"",prim_field)
|
|
split(prim_field, prim_field_array,/,/)
|
|
sub(/\[/,"_", prim_field_array[j])
|
|
sub(/\]/,"", prim_field_array[j])
|
|
printf "%s ", prim_field_array[j]
|
|
}
|
|
else printf "%s ", prim_field
|
|
} # end for i
|
|
printf "\n"
|
|
} # end for j
|
|
next
|
|
}
|
|
|
|
primitive==1{primitive_line=primitive_line " " $0; next } # 20071217
|
|
|
|
/^\/\/\/\/ begin user architecture code/{
|
|
begin_entity=0
|
|
next
|
|
}
|
|
|
|
|
|
|
|
##### JUST print things before first entity
|
|
(begin_entity!=1){
|
|
if($0 ~ /^entity .*is$/) begin_entity=1;
|
|
else
|
|
{
|
|
print $0
|
|
next
|
|
}
|
|
}
|
|
|
|
|
|
##### PRINT PROCESSES WITHOUT ANY CHANGES
|
|
/^[ \t]*([A-Za-z_][A-Za-z0-9_]*[ \t]*:)?[ \t]*process/, /^[ \t]*end[ \t]+process/{
|
|
print $0
|
|
next
|
|
}
|
|
|
|
|
|
#### BEGIN PRINT COMPONENT
|
|
/^component /{
|
|
component=1
|
|
component_name=$2
|
|
no_print=1
|
|
}
|
|
|
|
|
|
(component==1){
|
|
if($4==":=") $5=get_number($5)
|
|
if($5==":=") $6=get_number($6)
|
|
if($1 ~ /\[.*:.*\]/)
|
|
{
|
|
arch_sig_name[component_name,$1]=s_b($1) # array used to compare
|
|
# actual ports in instances, if they match
|
|
# avoid indexes (to/downto)
|
|
xx=s_i($1)
|
|
split(xx,xxx,":")
|
|
|
|
## don't add _vector if user defined type
|
|
if($4 ~ /^(boolean|bit|real|std_logic|integer)$/)
|
|
vector_type=$4 "_vector ("
|
|
else
|
|
vector_type=$4 " ("
|
|
|
|
|
|
|
|
if( (xxx[1]+0 > xxx[2]+0) || ( xxx[2]~/[01]/ && xxx[1]!~/^0$/) )
|
|
$4=vector_type xxx[1] " downto " xxx[2] ")"
|
|
else
|
|
$4=vector_type xxx[1] " to " xxx[2] ")"
|
|
$1=s_b($1)
|
|
print " " $0
|
|
}
|
|
else print $0
|
|
if($0 ~ /^end component/) component=0
|
|
no_print=1
|
|
}
|
|
|
|
#### BEGIN PRINT ENTITY
|
|
|
|
/^entity /{
|
|
delete entity_ports
|
|
user_declarations=""
|
|
user_attributes=""
|
|
entity=1
|
|
entity_name=$2
|
|
no_print=1
|
|
}
|
|
|
|
(entity==1){
|
|
if($4==":=") $5=get_number($5)
|
|
if($5==":=") $6=get_number($6)
|
|
if($1 ~ /\[.*:.*\]/)
|
|
{
|
|
xx=s_i($1)
|
|
split(xx,xxx,":")
|
|
|
|
## don't add _vector if user defined type
|
|
if($4 ~ /^(boolean|bit|real|std_logic|integer)$/)
|
|
vector_type=$4 "_vector ("
|
|
else
|
|
vector_type=$4 " ("
|
|
|
|
if( (xxx[1]+0 > xxx[2]+0) || (xxx[2]~/[01]/ && xxx[1] !~ /^0$/) )
|
|
$4=vector_type xxx[1] " downto " xxx[2] ")"
|
|
else
|
|
$4=vector_type xxx[1] " to " xxx[2] ")"
|
|
$1=s_b($1)
|
|
print " " $0
|
|
}
|
|
else print $0
|
|
entity_ports[$1]=1
|
|
if($1=="end" && $2==entity_name) entity=0
|
|
no_print=1
|
|
}
|
|
|
|
|
|
#### BEGIN RESOLVE SIGNALS
|
|
|
|
/^[ \t]*architecture[ \t]+.*[ \t]+is[ \t]*$/{
|
|
arch_rep=$2
|
|
arch=$4
|
|
delete arch_signal_dir
|
|
delete arch_index_array
|
|
delete arch_sig_type_array
|
|
delete arch_value_array
|
|
# omit bit ranges ( CNT => CNT(3 downto 0) --> CNT => CNT )
|
|
print $0
|
|
no_print=1
|
|
}
|
|
|
|
/^[ \t]*(signal|constant|variable)[ \t]+/{ ### dangerous <<< 07062002 added "variable"
|
|
|
|
if( $NF ~ /\[[^:,]+:[^:,]+\]$/) # 09112003, corrected to recognize only XXX[3:1] and not XXX[3:1],AA[3]
|
|
{
|
|
up=$NF
|
|
sub(/^.*\[/,"",up)
|
|
sub(/:.*$/,"",up)
|
|
up=up+0
|
|
low=$NF
|
|
sub(/^.*:/,"",low)
|
|
sub(/\].*$/,"",low)
|
|
low=low+0
|
|
if(up >=low) sig_dir = " downto "
|
|
else sig_dir = " to "
|
|
|
|
}
|
|
else sig_dir = " downto "
|
|
|
|
if( $2 ~ /.*\[[0-9]+\]/)
|
|
{
|
|
sig_basename=s_b($2)
|
|
sig_index=s_i($2)
|
|
# sig_dir not missing, it is set in the previous if-else 09112003
|
|
sig_type=$4
|
|
sig_class=$1
|
|
}
|
|
else
|
|
{
|
|
sig_basename=$2
|
|
sig_index="no_index" #11092003 set no_index to recognize non-buses
|
|
sig_type=$4
|
|
sig_dir=" downto " # just to have a value
|
|
sig_class=$1
|
|
}
|
|
arch_signal_dir[sig_basename]=sig_dir
|
|
arch_signal_class[sig_basename]=sig_class
|
|
arch_sig_type_array[sig_basename]=sig_type
|
|
if($0 ~ /:=/) {
|
|
# arch_value_array[sig_basename]=$(NF-2)
|
|
|
|
tmpval=$0 #04062002 allow spaces in value
|
|
sub(/^.* := /,"",tmpval)
|
|
sub(/ *;.*$/,"",tmpval)
|
|
arch_value_array[sig_basename]=tmpval
|
|
}
|
|
if(!(sig_basename in arch_index_array))
|
|
{
|
|
arch_index_array[sig_basename]= sig_index
|
|
}
|
|
else
|
|
{
|
|
arch_index_array[sig_basename]=arch_index_array[sig_basename] "," sig_index
|
|
}
|
|
no_print=1
|
|
}
|
|
|
|
/^begin$/{
|
|
|
|
if( user_declarations!="") print user_declarations
|
|
|
|
ttt[1]="constant"
|
|
ttt[2]="variable"
|
|
ttt[3]="signal"
|
|
for(tt=1;tt<=3;tt++)
|
|
for(i in arch_signal_dir)
|
|
if(arch_signal_class[i]==ttt[tt])
|
|
{
|
|
## 04062002 don't add _vector if user defined type
|
|
if(arch_sig_type_array[i] ~ /^(boolean|bit|real|std_logic|integer)$/)
|
|
vector_type=arch_sig_type_array[i] "_vector ("
|
|
else
|
|
vector_type=arch_sig_type_array[i] " ("
|
|
|
|
n=split(arch_index_array[i],tmp,",")
|
|
hsort(tmp, n)
|
|
if(n>1 || (arch_index_array[i] !~ /no_index/) ) #11092003 if not no_index treat as a bus
|
|
{
|
|
if(check(tmp,n))
|
|
{
|
|
if(arch_signal_dir[i] == " downto ")
|
|
{
|
|
arch_sig_name[entity_name, i "[" tmp[1] ":" tmp[n] "]"]=i
|
|
printf "%s",arch_signal_class[i] " " i " : " vector_type tmp[1] " downto " tmp[n] ")" #04062002
|
|
}
|
|
else
|
|
{
|
|
arch_sig_name[entity_name, i "[" tmp[n] ":" tmp[1] "]"]=i
|
|
printf "%s",arch_signal_class[i] " " i " : " vector_type tmp[n] " to " tmp[1] ")" #04062002
|
|
}
|
|
}
|
|
else print "\n**** ERROR >>>> " i " non contigous bus ->" n, "|" arch_index_array[i] "|"
|
|
}
|
|
else
|
|
{
|
|
# we do not declare parametrized subranges as normally will result in redeclaration
|
|
# of a port signal
|
|
if( i ~ /\[.*\]/)
|
|
{
|
|
range = s_i(i)
|
|
basename=s_b(i) # on exactly matching ranges
|
|
arch_sig_name[entity_name, basename "[" range "]"]=i # used later in port maps to avoid specifying ranges
|
|
if( !(basename in entity_ports) ) #09112003, eror corrected, basename instead of i in
|
|
{ #arch_sig_name[entity_name,...
|
|
if(range ~ /0:/)
|
|
sub(/:/, " to ", range)
|
|
else
|
|
sub(/:/, " downto ", range)
|
|
range= range ")"
|
|
printf "%s",arch_signal_class[i] " " basename " : " vector_type range #04062002
|
|
}
|
|
else continue
|
|
}
|
|
else
|
|
printf "%s",arch_signal_class[i] " " i " : " arch_sig_type_array[i]
|
|
}
|
|
if(arch_value_array[i] != "") { #08112004 add quotes on values
|
|
if(tolower( arch_sig_type_array[i]) ~ /std_logic/ || # if not present
|
|
tolower(arch_sig_type_array[i]) ~ /bit/ ) { # for verilog/VHDL compatiblity
|
|
|
|
# if(tolower(arch_sig_type_array[i]) ~ /vector/) sep="\""
|
|
if(n>1 || (arch_index_array[i] !~ /no_index/) ) sep="\""
|
|
else sep = "'"
|
|
if( arch_value_array[i] !~ sep)
|
|
arch_value_array[i] = sep arch_value_array[i] sep
|
|
}
|
|
printf "%s"," := " arch_value_array[i]
|
|
}
|
|
printf " ;\n"
|
|
}
|
|
|
|
|
|
if(user_attributes!="") print user_attributes
|
|
print $0
|
|
no_print=1
|
|
}
|
|
|
|
#### END RESOLVE SIGNALS
|
|
|
|
|
|
#### BEGIN RESOLVE INSTANCES
|
|
|
|
(NF==4 && $(NF-1)==":" && $(NF)!=";"){ ### dangerous <<<<<<<
|
|
instance=$2
|
|
gsub(/\[/,"_X_",instance)
|
|
gsub(/\]/,"",instance)
|
|
cell=$4
|
|
no_print=1
|
|
}
|
|
|
|
($1==");" && port_map==1){
|
|
nii=split(instance,ii,",")
|
|
for(j=0;j<p;j++) {
|
|
if(j>=g) { # do not split generics 06042005
|
|
actual_port_mult=split(inst_actual_port[j],actual_port_array,",")
|
|
}
|
|
else {
|
|
actual_port_mult=1
|
|
actual_port_array[1]=inst_actual_port[j]
|
|
}
|
|
ck2[j] = check2(actual_port_array,actual_port_mult)
|
|
}
|
|
for(i=1;i<=nii;i++) {
|
|
print ii[i] " : " cell
|
|
if(g>0)
|
|
print "generic map ("
|
|
else
|
|
print "port map (" # p= pin number of current instance
|
|
for(j=0;j<p;j++) { # g= flag for generic pin assignment
|
|
if(g>0 && j==g) printf "\n)\nport map ("
|
|
|
|
|
|
if(j>=g) { # do not split generics 06042005
|
|
actual_port_mult=split(inst_actual_port[j],actual_port_array,",")
|
|
}
|
|
else {
|
|
actual_port_mult=1
|
|
actual_port_array[1]=inst_actual_port[j]
|
|
}
|
|
|
|
# force to actual multiplicty unresolved (due to params) symbol pin multiplicity
|
|
parametrized_formal_range=0 # 20100408
|
|
if(inst_formal_port_mult[j]<0) {
|
|
parametrized_formal_range=1 # 20100408
|
|
inst_formal_port_mult[j] = actual_port_mult
|
|
inst_formal_up[j] = actual_port_mult -1 # 20100419 assume inst_formal_low=0 in case of parametrized vector port...
|
|
}
|
|
|
|
a=((i-1)*inst_formal_port_mult[j]) % actual_port_mult+1
|
|
b=(-1+i*inst_formal_port_mult[j]) % actual_port_mult+1
|
|
#print "\n-- a=" a " b=" b " formal port mult=" inst_formal_port_mult[j]
|
|
if(j>0 && j!=g) printf " ,\n"
|
|
else if(j>0) printf "\n"
|
|
if(inst_formal_port_mult[j]>1 && actual_port_mult>1 && ck2[j]) {
|
|
if( s_i(actual_port_array[a])+0 > s_i(actual_port_array[b])+0) {
|
|
actual_port= s_b(actual_port_array[a]) "(" s_i(actual_port_array[a]) " downto " s_i(actual_port_array[b]) ")"
|
|
}
|
|
else {
|
|
actual_port= s_b(actual_port_array[a]) "(" s_i(actual_port_array[a]) " to " s_i(actual_port_array[b]) ")"
|
|
}
|
|
}
|
|
else if( ck2[j] || inst_formal_port_mult[j]==1) {
|
|
actual_port = actual_port_array[a]
|
|
sub(/\[/,"(",actual_port)
|
|
sub(/\]/,")",actual_port)
|
|
sub(/:/," downto ",actual_port)
|
|
}
|
|
# these lines avoid specifying bit ranges (to/downto) for
|
|
# actual ports that exactly match declared signals or entity ports
|
|
tmp_port=actual_port
|
|
sub(/ (to|downto) /,":",tmp_port)
|
|
sub(/\(/,"[",tmp_port)
|
|
sub(/\)/,"]",tmp_port)
|
|
if( (entity_name,tmp_port) in arch_sig_name ) {
|
|
actual_port=arch_sig_name[entity_name,tmp_port]
|
|
}
|
|
|
|
if( ck2[j] || (inst_formal_port_mult[j]==1) ) { # contiguous bus or single bit
|
|
|
|
|
|
# 20100408 if formal range contains generic and actual port width is 1 specify formal bit index in assignment
|
|
if( (parametrized_formal_range || (inst_formal_port_mult[j]>1)) && actual_port_mult==1) {
|
|
# patch for single bit actual port
|
|
# assigned on vector formal port 23112002
|
|
|
|
# 20170920
|
|
if( parametrized_formal_range && inst_actual_port[j] ~/\[.*:.*\]/) {
|
|
printf "%s"," " inst_formal_port[j] " => " get_number(actual_port)
|
|
} else
|
|
# /20170920
|
|
for(num=inst_formal_low[j]; ; num+=sign(inst_formal_up[j] - inst_formal_low[j])) {
|
|
if(num !=inst_formal_low[j]) printf " ,\n"
|
|
printf "%s"," " inst_formal_port[j] "(" num ") => " get_number(actual_port)
|
|
if(num==inst_formal_up[j]) break
|
|
}
|
|
}
|
|
else printf "%s"," " inst_formal_port[j] " => " get_number(actual_port) #07062002 aggiunto get_number x generici
|
|
}
|
|
else { # non contiguous bus , specify assignments on single bits
|
|
for(num=a; ; num+= sign(b-a)) {
|
|
formal_index= (inst_formal_up[j] >= inst_formal_low[j]) ? \
|
|
remainder(inst_formal_up[j]-num+1+inst_formal_low[j], inst_formal_port_mult[j]) + inst_formal_low[j]: \
|
|
remainder(inst_formal_up[j]+num-1+inst_formal_up[j] , inst_formal_port_mult[j]) + inst_formal_up[j]
|
|
|
|
if(num !=a) printf " ,\n"
|
|
#07062002 aggiunto get_number x generici
|
|
printf "%s"," " inst_formal_port[j] "(" formal_index ") => " to_round_brackets(get_number(actual_port_array[num]))
|
|
if(num==b) break
|
|
}
|
|
}
|
|
}
|
|
printf "\n);\n"
|
|
}
|
|
port_map=0
|
|
print_arch_definition=1
|
|
no_print=1
|
|
}
|
|
|
|
(port_map==1 && $2=="=>" ){
|
|
inst_actual_port[p] = $0
|
|
sub(/.*=>[ \t]*/,"", inst_actual_port[p])
|
|
sub(/,[ \t]*$/,"", inst_actual_port[p])
|
|
if($1 ~ /\[.*:.*\]/) {
|
|
index_up=$1
|
|
sub(/^.*\[/,"",index_up)
|
|
sub(/:.*$/,"",index_up)
|
|
index_low=$1
|
|
sub(/^.*:/,"",index_low)
|
|
sub(/\].*$/,"",index_low)
|
|
if( (index_up !~/^[0-9]+$/) || (index_low !~/^[0-9]+$/) ) {
|
|
inst_formal_port_mult[p]=-1 # component port index contains parameter, multiplicity cant be resolved
|
|
inst_formal_up[p]=0
|
|
inst_formal_low[p]=0
|
|
}
|
|
else {
|
|
inst_formal_port_mult[p] = abs(index_up - index_low) + 1
|
|
inst_formal_up[p]=index_up
|
|
inst_formal_low[p]=index_low
|
|
#print "--port assignment: port " s_b($1) " formal idx hi=" index_up " lo=" index_low
|
|
}
|
|
}
|
|
else {
|
|
inst_formal_port_mult[p] = 1;
|
|
inst_formal_up[p]=0
|
|
inst_formal_low[p]=0
|
|
}
|
|
# if formal port = a[2:2] translate as a(2)
|
|
if(index_up == index_low && $1 ~ /\[.*:.*\]/)
|
|
inst_formal_port[p] = s_b($1) "(" index_up ")"
|
|
else
|
|
inst_formal_port[p] = s_b($1)
|
|
p++
|
|
no_print=1
|
|
}
|
|
|
|
(port_map==1 && $1~ /^\)/) { no_print=1 }
|
|
|
|
/^generic map/{
|
|
delete inst_actual_port
|
|
delete inst_formal_port
|
|
delete inst_formal_port_mult
|
|
p=0;g=0
|
|
port_map=1
|
|
no_print=1
|
|
}
|
|
|
|
|
|
/^port map/{
|
|
if(!port_map){
|
|
delete inst_actual_port
|
|
delete inst_formal_port
|
|
delete inst_formal_port_mult
|
|
p=0;g=0
|
|
port_map=1
|
|
}
|
|
else g=p
|
|
no_print=1
|
|
}
|
|
|
|
($1~ /^end$/ && $2==arch_rep){
|
|
arch_rep=""
|
|
print $0
|
|
no_print=1
|
|
}
|
|
|
|
|
|
(no_print==0){
|
|
print $0
|
|
}
|
|
|
|
|
|
#### UTILITY FUNCTIONS
|
|
function remainder(n,div, x) {
|
|
x=n%div
|
|
if(x<o) return x+div
|
|
return x
|
|
}
|
|
|
|
function abs(x)
|
|
{
|
|
if(x+0<0) return -x
|
|
else return x
|
|
}
|
|
|
|
function sign(x)
|
|
{
|
|
if(x+0<0) return -1
|
|
else return 1
|
|
}
|
|
|
|
|
|
# heap sort, this is a N*log2(N) routine
|
|
function hsort(ra,n, 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]
|
|
}
|
|
else {
|
|
rra=ra[ir]
|
|
ra[ir]=ra[1]
|
|
if(--ir==1) {
|
|
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]) {
|
|
ra[i]=ra[j]
|
|
j+=(i=j)
|
|
}
|
|
else j=ir+1
|
|
}
|
|
ra[i]=rra
|
|
}
|
|
}
|
|
|
|
# check if an array of numbers arr[1],arr[2]..... is contigous and decreeasing
|
|
function check(arr,n ,i,start,ok)
|
|
{
|
|
start=arr[1]
|
|
for(i=2;i<=n;i++)
|
|
{
|
|
if(arr[i]+1 == start)
|
|
{
|
|
start=arr[i]
|
|
}
|
|
else
|
|
{
|
|
return 0
|
|
}
|
|
}
|
|
return 1
|
|
}
|
|
|
|
# check if an array of indexes (sig[3]) arr[1],arr[2].....
|
|
# is contigous and decreeasing
|
|
function check2(arr,n ,a,name,i,start,ok)
|
|
{
|
|
name=s_b(arr[1])
|
|
start=s_i(arr[1])
|
|
if(arr[1] !~ /[0-9]+/)
|
|
{
|
|
if(n>1) return 0
|
|
else return 1
|
|
}
|
|
for(i=2;i<=n;i++)
|
|
{
|
|
if(s_b(arr[i]) != name) return 0
|
|
if(arr[1] !~ /[0-9]+/) return 0
|
|
a= s_i(arr[i])
|
|
if(a+1 == start)
|
|
{
|
|
start=a
|
|
}
|
|
else
|
|
{
|
|
return 0
|
|
}
|
|
}
|
|
return 1
|
|
}
|
|
|
|
function s_i(a)
|
|
{
|
|
sub(/.*\[/,"",a)
|
|
sub(/\].*$/,"",a)
|
|
return a
|
|
}
|
|
|
|
function s_b(a)
|
|
{
|
|
sub(/\[.*$/,"",a)
|
|
return a
|
|
}
|
|
|
|
function get_number(n) # follows SPICE conventions
|
|
{
|
|
sub(/^[ \t]+/,"",n)
|
|
sub(/[ \t]+$/,"",n)
|
|
if(n !~ /^[-.0-9]/) return n # not a number
|
|
if( n ~ / / ) return n
|
|
n=toupper(n)
|
|
if(n ~ /A/) return vhdl_paranoia(n*1e-18)
|
|
if(n ~ /F/) return vhdl_paranoia(n*1e-15)
|
|
if(n ~ /P/) return vhdl_paranoia(n*1e-12)
|
|
if(n ~ /N/) return vhdl_paranoia(n*1e-9)
|
|
if(n ~ /U/) return vhdl_paranoia(n*1e-6)
|
|
if(n ~ /M[^E][^G]/) return vhdl_paranoia(n*1e-3)
|
|
if(n ~ /K/) return vhdl_paranoia(n*1e3)
|
|
if(n ~ /MEG/) return vhdl_paranoia(n*1e6)
|
|
if(n ~ /G/) return vhdl_paranoia(n*1e9)
|
|
if(n ~ /T/) return vhdl_paranoia(n*1e12)
|
|
return vhdl_paranoia(n)
|
|
}
|
|
|
|
# convert numbers like 4e-7 to 4.0e-7 as VHDL is stupid enough to
|
|
# complain about "integers with negative exponent...."
|
|
function vhdl_paranoia(n)
|
|
{
|
|
if(n ~ /^[0-9]+[eE]/)
|
|
sub(/[eE]/,".0e",n)
|
|
return n
|
|
}
|
|
|
|
function to_round_brackets(s) {
|
|
sub(/\[/,"(",s)
|
|
sub(/\]/,")",s)
|
|
return s
|
|
}
|
|
|
|
|
|
|
|
function compact_pinlist(pin, dir ,i,ii,base,curr,curr_n,np)
|
|
{
|
|
delete pin_ret
|
|
delete net_ret
|
|
delete dir_ret
|
|
|
|
np=pin["n"]
|
|
if(np) {
|
|
ii=1
|
|
for(i=1;i<=np;i++) {
|
|
base =s_b( pin[i] )
|
|
if(i==1) {curr=base; curr_n=i}
|
|
else {
|
|
if(base != curr) {
|
|
pin_ret[ii] = compact_label(pin,curr_n,i-1)
|
|
dir_ret[ii] = dir[i-1]
|
|
ii++
|
|
curr=base;curr_n=i
|
|
}
|
|
}
|
|
}
|
|
pin_ret[ii] = compact_label(pin,curr_n,np)
|
|
dir_ret[ii] = dir[np]
|
|
pin_ret["n"] = dir_ret["n"] = ii
|
|
}
|
|
}
|
|
|
|
# 1 2 3 4 5 6 7 8 9 10 11 12
|
|
# PP A[3] A[2] A[1] B C K[10] K[9] K[5] K[4] K[3] K[1]
|
|
function compact_label(ar,a,b, ret,start,i)
|
|
{
|
|
ret=""
|
|
for(i=a;i<=b;i++) {
|
|
if(i==a) {start=a}
|
|
else {
|
|
if(ar[i-1] !~ /\[/) {
|
|
if(ar[i-1] != ar[i]) {
|
|
if(start < i-1) { ret = ret (i-start) "*" ar[i-1] ","; start=i }
|
|
else {ret = ret ar[i-1] ","; start=i }
|
|
}
|
|
}
|
|
else if(s_b(ar[i])!=s_b(ar[i-1]) ||
|
|
( lab_index(ar[i]) != lab_index(ar[i-1])-1 &&
|
|
lab_index(ar[i]) != lab_index(ar[i-1])+1) ) {
|
|
if(start<i-1)
|
|
ret = ret s_b(ar[start]) "[" lab_index(ar[start]) ":" lab_index(ar[i-1]) "],"
|
|
else
|
|
ret = ret s_b(ar[start]) "[" lab_index(ar[start]) "],"
|
|
start=i
|
|
}
|
|
}
|
|
}
|
|
if(ar[b] !~ /\[/) {
|
|
if(start < b) ret = ret (b-start+1) "*" ar[b]
|
|
else ret = ret ar[b]
|
|
}
|
|
else if(start<b)
|
|
ret = ret s_b(ar[start]) "[" lab_index(ar[start]) ":" lab_index(ar[b]) "]"
|
|
else
|
|
ret = ret s_b(ar[b]) "[" lab_index(ar[b]) "]"
|
|
return ret
|
|
}
|
|
|
|
|
|
|
|
function lab_index(lab)
|
|
{
|
|
sub(/.*\[/,"",lab)
|
|
sub(/\].*/,"",lab)
|
|
return lab+0
|
|
}
|
|
|
|
|
|
|