#!/usr/bin/python # (the shebang above works for Linux) # (in FreeBSD use: ) ##!/usr/local/bin/python # -*- coding: cp1252 -*- """ Calculates the transition times for the XOR with two delays with arbitrary precision """ ### Dec. 2009 from decimal import * import os Prec = 12 # number of decimal places getcontext().prec=Prec max_transitions = 10000 # maximum number of transitions final_time = Decimal("120.0") transient = Decimal("20.0") Verbose_level = 1 # 1 = normal messages, 2 = debug mode, 0 = silent mode tau1 = Decimal(1) tau2 = Decimal(2)/(Decimal(1)+Decimal(5).sqrt()) # Minimum allowed pulse width w_min = Decimal("0.005") # choices of initial conditions: #ic = Decimal(0) ic = -tau2 #tn = [ic-max(tau1,tau2),ic-min(tau1,tau2),ic] tn = [ic] # list of transitions # Parameters for degradation (memory) function w_a1 = Decimal("0.1") w_a2 = Decimal("0.1") w_b1 = Decimal("0.25") w_b2 = Decimal("0.25") A1 = Decimal("0.20") A2 = Decimal("0.20") B1 = A1*(w_min-w_a1)/(w_b1-w_a1) B2 = A2*(w_min-w_a2)/(w_b2-w_a2) #degradation function for delay line 1 def g1(p): if p0: print "output file: ", "xor_degrad_"+str(Prec)+"digits.dat" f.write("#tau1 = %s, tau2 = %s\n" % (str(float(tau1)), str(float(tau2))) ) f.write("#w_min = %s, Prec = %d\n" % (str(float(w_min)), Prec) ) f.write("#w_a1 = %s, w_b1 = %s, A1 = %s, B1 = %s\n" % (str(float(w_a1)), str(float(w_b1)), str(float(A1)), str(float(B1))) ) f.write("#w_a2 = %s, w_b2 = %s, A2 = %s, B2 = %s\n" % (str(float(w_a2)), str(float(w_b2)), str(float(A2)), str(float(B2))) ) # main loop: (stop, i) = (False, 0) while not(stop): collided1 = collided2 = False # calculates the two candidates of future transitions from the first tn next_t_candidate_1 = tn[0] +g1( tn[0] +tau1 -tn[-1] ) next_t_candidate_2 = tn[0] +g2( tn[0] +tau2 -tn[-1] ) if Verbose_level>1: # optionally prints debug information # print "Processing ", min(tn) # print "list = %f " % tn[0], # for t in tn[1:]: # print ", %f" % float(t), # print "\nt1 = %f, t2 = %f" % (next_t_candidate_1, next_t_candidate_2) # if len(tn)>0: # if we have transitions in the list ... for t in tn: # ... checks, for all of them, if they collide ... if (abs(next_t_candidate_1-t) <= w_min): # ... with candidate 1 ... collided1 = True # remembers a collision occurred if Verbose_level>1: print "removing ", float(t) tn.remove(t) # removes colliding transition else: if Verbose_level>0: print "empty list, stopping now" f.close() exit() if len(tn)>0: for t in tn: if (abs(next_t_candidate_2-t) <= w_min): # ... and/or candidate 2 collided2 = True # remembers a collision occurred if Verbose_level>1: print "removing ", float(t) tn.remove(t) # removes colliding transition else: if Verbose_level>0: print "empty list, stopping now" f.close() exit() if not(collided1): # if the first candidate did not collide if len(tn)>1: following_t_1 = tn[1] +g1(tn[1]+tau1-next_t_candidate_1) # calculating next delay else: following_t_1 = tn[0]+tau1 if ((next_t_candidate_1)<=following_t_1)or(len(tn)<2): # to check whether the trailing edge overtakes the leading edge if (tn[0]>transient): if Verbose_level>1: print "saving transition at", float(tn[0]) f.write("%s\n" % str(tn[0])) # saves generating transition as good one tn.append(next_t_candidate_1) # appends the good candidate do the list if not(collided2): # if candidate 2 did not collide if len(tn)>1: following_t_2 = tn[1] +g2(tn[1]+tau2-next_t_candidate_2) # calculating next delay else: following_t_1 = tn[0]+tau2 if ((next_t_candidate_2)<=following_t_2)or(len(tn)<2): tn.append(next_t_candidate_2) # appends the good candidate do the list if collided1: # if candidate 1 collided, we haven't saved the good transition yet if (tn[0]>transient): if Verbose_level>1: print "saving transition at", float(tn[0]) f.write("%s\n" % str(tn[0])) # saves the transition now tn = tn[1:] # removes the processed transition tn.sort() # sorts the list, to make sure of the right ordering #tn.remove(min(tn)) i += 1 if (i>=max_transitions) or (tn[-1]>=final_time) or (len(tn)==0): stop = True # we have finished after the main loop f.close() if Verbose_level>0: print "finished!" # pauses on Windows, to give the user a chance of looking at the error messages, just in case # we can pause (or wait a few seconds) on posix (Linux), too if os.name=="posix": os.system("sleep 1") else: os.system("pause")