xschem/src/utile/clock.awk

171 lines
3.9 KiB
Awk
Executable File

#!/usr/bin/awk -f
# File: clock.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
#
# plugin for clock expansion
#
# clock <signal> <pulse> <period> [invert] [high value] [low value]
#
# _______ _______
#___________________| |____________| |__________
# | | |
# |<pulse>| |
# |<----- period ----->|
# |
# clock_start
# Stefan, 04122001
BEGIN {
OFMT="%.14g" # better precision
CONVFMT="%.14g"
old_event=-1
}
## stefan fix 20100630: reset absolute time if multiple beginfile--endfile given
/^[ \t]*beginfile[ \t]+/{
time=0
}
/^[ \t]*clock[ \t]+/{
sub(/[ \t]*;.*/,"")
clock_name = $2
clock_start[clock_name]=time
clock_pulse[clock_name] = $3 + time
clock_period[clock_name] = $4
clock_state[clock_name] = ($5 == "invert") ? 0 : 1
if($5=="invert") {
if($6!="") clock_high[clock_name]=$6
else clock_high[clock_name]=1
if($7!="") clock_low[clock_name]=$7
else clock_low[clock_name]=0
} else {
if($5!="") clock_high[clock_name]=$5
else clock_high[clock_name]=1
if($6!="") clock_low[clock_name]=$6
else clock_low[clock_name]=0
}
print "set " clock_name " " value(clock_name, clock_state[clock_name])
next
}
/[ \t]*stop_clock[ \t]+/{
delete clock_start[$2]
delete clock_pulse[$2]
delete clock_period[$2]
delete clock_state[$2]
delete clock_high[$2]
delete clock_low[$2]
k=0; for(i in clock_start) {k=1}
if(!k) clock_name=""
next
}
/^[ \t]*s[ \t]+/{
go_to_time($2+time)
next
}
/^[ \t]*time[ \t]+/{
go_to_time($2)
next
}
{ print }
function go_to_time(to_time)
{
if(clock_name)
{
while((a=next_event()) <= to_time)
{
if(a>time) print "s " a - time " ;" a
m=split(current_clock, tmp)
for(i=1;i<=m;i++)
{
clock_state[tmp[i]]=!clock_state[tmp[i]]
print "set " tmp[i] " " value(tmp[i], clock_state[tmp[i]]) " ;" a
time =a
}
}
}
if(to_time > time)
{
print "s " to_time - time " ;" to_time
time=to_time
}
}
function next_event( k, i, clock_event1, clock_event2)
{
k=0
for(i in clock_start)
{
clock_event1 = int( (time-clock_start[i])/clock_period[i])*clock_period[i] + clock_start[i]
while(clock_event1 <= time) {
clock_event1+=clock_period[i]
}
clock_event2 = int( (time-clock_pulse[i])/clock_period[i])*clock_period[i] + clock_pulse[i]
while(clock_event2 <= time) {
clock_event2+=clock_period[i]
}
if(clock_event1 < clock_event2)
clock_event = clock_event1+0
else
clock_event = clock_event2+0
if(!k) { event=clock_event ; current_clock=i; k=1}
else if(clock_event < event)
{
event = clock_event
current_clock=i
}
else if( abs(clock_event - event)<1e-12 )
{
current_clock = current_clock " " i
}
print "; time= " time " next event = " clock_event " " i " event=" event
}
return event
}
function value(clock_name, i) {
if(i==1) return clock_high[clock_name]
else return clock_low[clock_name]
}
function abs(x)
{
return x<0? -x : x
}