#!/usr/bin/awk -f # # File: verilog.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 BEGIN{ net_types["wire"]=1 net_types["tri"]=1 net_types["wor"]=1 net_types["trior"]=1 net_types["wand"]=1 net_types["triand"]=1 net_types["tri0"]=1 net_types["tri1"]=1 net_types["supply1"]=1 net_types["supply0"]=1 net_types["trireg"]=1 net_types["reg"]=1 net_types["integer"]=1 net_types["time"]=1 net_types["real"]=1 net_types["logic"]=1 net_types["bool"]=1 direction["input"]=1 direction["inout"]=1 direction["output"]=1 } /^---- start primitive/{primitive_line=""; primitive_mult=$4;primitive=1; next} /^---- end primitive/{ primitive=0 $0 = primitive_line gsub(/----pin\(/, " ----pin(",$0) gsub(/----name\(/, " ----name(",$0) for(j=1;j<= primitive_mult; j++) { prefix="" # print $0 > "/dev/stderr" for(i=1;i<=NF;i++) { if($i ~/^#[a-zA-Z_]+#$/) { prefix=$i sub(/^#/,"", prefix) sub(/#$/,"", prefix) continue } prim_field=$i if($i ~ /^----pin\(.*\)/) { sub(/----pin\(/,"",prim_field) sub(/\)$/,"",prim_field) pport_mult = split(prim_field, prim_field_array,/,/) # 20060919 BEGIN # 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:%s] ", prefix 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", prefix prim_field_array[s] if(s7) {printf ","} if($j !~ /^\?-?[0-9]+$/) { pin=pin $j # if not a node just print it } else { nmult=$(j++);j++ sub(/\?/,"",nmult) nmult=nmult+0 if(nmult==-1) nmult=arg_num[j] for(l=0;l1? "{" pin "}" : pin) } } printf "\n);\n\n" } previous="" next } # types of in/out/inout ports of module netlist==0 && architecture==0 && ($1 in net_types) && ($2 in net_types) { if($3 ~ /\[.*\]/) {$3= s_b($3) "[" s_i($3) "] "; $1=" " $1 } } netlist==0 && architecture==0 && ($1 in net_types) && !($2 in net_types) { if($2 ~ /\[.*\]/) {$2= "[" s_i($2) "] " s_b($2); $1=" " $1 } } # module port directions NF==3 && netlist==0 && architecture==0 && ($1 in direction) { if($2 ~ /\[.*\]/) {$2= "[" s_i($2) "] " s_b($2); $1=" " $1 } ## 20080412 print range also in port decl as req by standard #### $2= s_b($2); $1=" " $1 } /^---- begin user architecture code/ { netlist=0 architecture=1 next } /^---- end user architecture code/ { architecture=0 next } /^---- start parameters/{ parameters=1 next } /^---- end parameters/{ parameters=0 next } $NF=="," && parameters==1 { if($1 ~ /^[+-]?(([0-9]+\.?)|([0-9]*\.[0-9]+))(([aAfFpPnNuUgGtT])|([mM][eE]][gG]))/){ $1=" " get_number($1) } } # parameters assignments on instance line / *\.[a-zA-Z_0-9]+ \( [^ ]+ \)/ && parameters==1{ $3=get_number($3) } / *\.[a-zA-Z_0-9]+\( [^ ]+ \)/ && parameters==1{ $2=get_number($2) } netlist==1 { previous=previous $0 "\n" next } { print } function get_number(n) # follows SPICE conventions { if(n !~ /^[-.0-9]/) return n # not a number n=toupper(n) if(n ~ /A/) return n*1e-18 if(n ~ /F/) return n*1e-15 if(n ~ /P/) return n*1e-12 if(n ~ /N/) return n*1e-9 if(n ~ /U/) return n*1e-6 if(n ~ /M[^E][^G]/) return n*1e-3 if(n ~ /K/) return n*1e3 if(n ~ /MEG/) return n*1e6 if(n ~ /G/) return n*1e9 if(n ~ /T/) return n*1e12 return n+0.0 # force a numeric ret. value } # 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(jra[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 indexes (sig[3]) arr[1],arr[2]..... # is contigous and decreeasing # 20140409 handle ascending order as well as descending function check2(arr,n ,decreasing,a,name,i,start,ok) { decreasing="" net_ascending=0 # 20140416 must be global var ! 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])+0 if(a+1 == start) { if(decreasing=="") { start=a decreasing=1 } else if(decreasing==1) { start=a } else { return 0 } } else if(a-1 == start) { if(decreasing=="") { start=a decreasing=0 } else if(decreasing==0) { start=a } else { return 0 } } else { return 0 } } if(decreasing==0) net_ascending=1 # net_ascending is global 20140416 else net_ascending=0 # net_ascending is global 20140416 return 1 } # 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 } function s_b(n) { sub(/\[.*/,"",n) return n; } function s_i(n) { if(n ~ /\[/) { sub(/.*\[/,"",n) sub(/\]/,"",n) return n } else return "" } function cleanup() { gsub(/\);/," );") } function on_single_line( i,a,count) { cleanup() count=0 i=1 a="" while(1) { if(i>NF) { getline;cleanup();i=1 } if(count) a=a " " a=a $i count++ if($i==");") break i++ } $0= a }