Пример #1
0
    def scan_or_adjust_delay_random(self,
                                    low_delay,
                                    high_delay,
                                    use_dq,
                                    use_odelay,
                                    ends_dist,
                                    min_diff,
                                    adjust,
                                    verbose):
        """
        Scan or adjust delays using random data write+read
        <low_delay>   Low delay value to tru
        <high_delay>  high delay value to try
        <use_dq>      0 - scan dqs, 1 - scan dq (common value, post-adjustment)
        <use_odelay>  0 - use input delays, 1 - use output delays
        <ends_dist>   do not process if one of the primary interval ends is within this from 0.0 or 1.0
        <min_diff>    minimal difference between primary delay steps to process 
        <adjust>      0 - scan, 1 - adjust
        <verbose>:    verbose mode (more prints) 
        Returns list of calculated delay values
        """
        checkIntArgs(('low_delay','high_delay'),locals())
        brc=(5,        # 3'h5,     # bank
             0x1234,   # 15'h1234, # row address
             0x100)     # 10'h100   # column address
           
#        global BASEADDR_PORT1_WR,VERBOSE;
#        saved_verbose=VERBOSE;
#        VERBOSE=False;
        low = split_delay(low_delay)
        high = split_delay(high_delay)
        rand16=[]
        for i in range(512):
            rand16.append(random.randint(0,65535))
        wdata=convert_mem16_to_w32(rand16)
        if (verbose and not adjust): print("rand16:")
        for i in range(len(rand16)):
            if (i & 0x1f) == 0:
                if (verbose and not adjust): print("\n%03x:"%i,end=" ")
            if (verbose and not adjust): print("%04x"%rand16[i],end=" ")
        if (verbose and not adjust): print("\n")        
        if (verbose and not adjust): print("wdata:")
        for i in range(len(wdata)):
            if (i & 0xf) == 0:
                if (verbose and not adjust): print("\n%03x:"%i,end=" ")
            if (verbose and not adjust): print("%08x"%wdata[i],end=" ")
        if (verbose and not adjust): print("\n")        
        bit_type=[] # does not include first and last elements
        for i in range(1,511):
            types=[]
            for j in range(16):
                types.append((((rand16[i-1]>>j) & 1)<<2) | (((rand16[i  ]>>j) & 1)<<1) |  (((rand16[i+1]>>j) & 1)))
            bit_type.append(types)
    #        if (verbose and not adjust): print ("i=%d",i)
    #        if (verbose and not adjust): print(types)
    #    total_types=[[0]*8]*16 # number of times each type occurred in the block for each DQ bit (separate for DG up/down?)
        total_types=[] # number of times each type occurred in the block for each DQ bit (separate for DG up/down?)
        for i in range(16): total_types.append([0]*8) 
        for typ in bit_type:
    #        if (verbose and not adjust): print(typ)
            for j in range(16):
    #            total_types[j][typ[j]]+=1
                total_types[j][typ[j]]=total_types[j][typ[j]]+1
        if (verbose and not adjust): print("\ntotal_types:")        
        if (verbose and not adjust): print (total_types)
        
        avg_types=[0.0]*8
        N=0
        for t in total_types:
            for j,n in enumerate(t):
                avg_types[j]+=n
                N+=n
        for i in range(len(avg_types)):
            avg_types[i]/=N
        if (verbose and not adjust): print("\avg_types:")        
        if (verbose and not adjust): print (avg_types)
        #write blok buffer with 256x32bit data
                
        self.x393_mcntrl_buffers.write_block_buf_chn(0,0,wdata); # fill block memory (channel, page, number)

        self.x393_pio_sequences.set_write_block(*brc) #64 8-bursts, 1 extra DQ/DQS/ active cycle
        self.x393_pio_sequences.set_read_block(*brc)
        
        if (use_odelay==0) :
            self.x393_pio_sequences.write_block(0,1) # Wait for operation to complete
            if verbose: print("++++++++ block written once")
    #now scanning - first DQS, then try with DQ (post-adjustment - best fit) 
        results = []
        if verbose: print("******** use_odelay=%d use_dq=%d"%(use_odelay,use_dq))
        alreadyWarned=False
        for dly in range (low, high+1):
            enc_dly=combine_delay(dly)
            if (use_odelay!=0):
                if (use_dq!=0):
                    if verbose: print("******** axi_set_dq_odelay(0x%x)"%enc_dly)
                    self.x393_mcntrl_timing.axi_set_dq_odelay(enc_dly) #  set the same odelay for all DQ bits
                else:
                    if verbose: print("******** axi_set_dqs_odelay(0x%x)"%enc_dly)
                    self.x393_mcntrl_timing.axi_set_dqs_odelay(enc_dly)
                self.x393_pio_sequences.write_block(0,1) # Wait for operation to complete
                if verbose: print("-------- block written AGAIN")
            else:
                if (use_dq!=0):
                    if verbose: print("******** axi_set_dq_idelay(0x%x)"%enc_dly)
                    self.x393_mcntrl_timing.axi_set_dq_idelay(enc_dly)#  set the same idelay for all DQ bits
                else:
                    if verbose: print("******** axi_set_dqs_idelay(0x%x)"%enc_dly)
                    self.x393_mcntrl_timing.axi_set_dqs_idelay(enc_dly)
            buf32=self.x393_pio_sequences.read_block(
                                                     256,    # num,
                                                     0,      # show_rslt,
                                                     1)      # Wait for operation to complete
            if self.bad_data(buf32):
                results.append([])
            else:
                # Warn about possible missing DQS pulses during writes
                alreadyWarned |= self.missing_dqs(buf32, alreadyWarned) 
                read16=convert_w32_to_mem16(buf32) # 512x16 bit, same as DDR3 DQ over time
                if verbose and (dly==low):   
                    if (verbose and not adjust): print("buf32:")
                    for i in range(len(buf32)):
                        if (i & 0xf) == 0:
                            if (verbose and not adjust): print("\n%03x:"%i,end=" ")
                        if (verbose and not adjust): print("%08x"%buf32[i],end=" ")
                    if (verbose and not adjust): print("\n")        
    
    
                    if (verbose and not adjust): print("read16:")
                    for i in range(len(read16)):
                        if (i & 0x1f) == 0:
                            if (verbose and not adjust): print("\n%03x:"%i,end=" ")
                        if (verbose and not adjust): print("%04x"%read16[i],end=" ")
                    if (verbose and not adjust): print("\n")
                data=[] # number of times each type occurred in the block for each DQ bit (separate for DG up/down?)
                for i in range(16):
                    data.append([0]*8) 
                
                for i in range (1,511):
                    w= read16[i]
                    typ=bit_type[i-1] # first and last words are not used, no type was calculated
                    for j in range(16):
                        if (w & (1<<j)) !=0:
                            data[j][typ[j]]+=1
                for i in range(16):
                    for t in range(8):
                        if (total_types[i][t] >0 ):
                            data[i][t]*=1.0/total_types[i][t]
                results.append(data)
                if (verbose and not adjust): print ("%3d (0x%02x): "%(dly,enc_dly),end="")
                for i in range(16):
                    if (verbose and not adjust): print("[",end="")
                    for j in range(8):
                        if (verbose and not adjust): print("%3d"%(round(100.0*data[i][j])),end=" ")
                    if (verbose and not adjust): print("]",end=" ")
                if (verbose and not adjust): print()    
        titles=["'000","'001","'010", "'011","'100","'101","'110","'111"]
        #calculate weighted averages
        #TODO: for DQ scan shift individual bits for the best match
        if  use_dq:
            if (verbose and not adjust): print("TODO: shift individual bits for the best match before averaging")
    
        res_avg=[]
        for dly in range (len(results)):
            if (len(results[dly])>0):
                data=results[dly]
                avg=[0.0]*8
                for t in range(8):
                    weight=0;
                    d=0.0
                    for i in range(16):
                        weight+=total_types[i][t]
                        d+=total_types[i][t]*data[i][t]
                    if (weight>0):
                        d/=weight
                    avg[t] = d
                res_avg.append(avg)
            else:
                res_avg.append([])
        corr_fine=self.calibrate_finedelay(
                low,         # absolute delay value of start scan
                avg_types,   # weights of weach of the 8  bit sequences
                res_avg,     # averaged eye data tablle, each line has 8 elements, or [] for bad measurements
                ends_dist/256.0, # ends_dist,   # do not process if one of the primary interval ends is within this from 0.0 or 1.0
                min_diff/256.0) #min_diff):   # minimal difference between primary delay steps to process
        period=len(corr_fine)
    
        if (not adjust):
            print("\n\n\n========== Copy below to the spreadsheet,  use columns from corr_delay ==========")
            print("========== First are individual results for each bit, then averaged eye pattern ==========")
            print ("delay corr_delay",end=" ")
            for t in range(8):
                for i in range(16):
                    if (not adjust): print("%02d:%s"%(i,titles[t]),end=" ")
            print()
            for index in range (len(results)):
                if (len(results[index])>0):
                    dly=index+low
                    corr_dly=dly+corr_fine[dly%period]
                    print ("%d %.2f"%(dly,corr_dly),end=" ")
                    for t in range(8):
                        for i in range(16):
                            try:
                                print("%.4f"%(results[dly][i][t]),end=" ") #IndexError: list index out of range
                            except:
                                print(".????",end="")
                    print()
                            
            print("\n\n\n========== Copy below to the spreadsheet,  use columns from corr_delay ==========")
            print("========== data above can be used for the individual bits eye patterns ==========")            
            print ("delay corr_delay",end=" ")
            for t in range(8):
                print(titles[t],end=" ")
            print()
            for index in range (len(res_avg)):
                if (len(res_avg[index])>0):
                    dly=index+low
                    corr_dly=dly+corr_fine[dly%period]
                    print ("%d %.2f"%(dly,corr_dly),end=" ")
                    for t in range(8):
                        try:
                            print("%.4f"%(res_avg[dly][t]),end=" ")
                        except:
                            print(".????",end=" ")
                    print()
        dly_corr=None
        if adjust:        
            dly_corr=self.corr_delays(
                low,         # absolute delay value of start scan
                avg_types,   # weights of weach of the 8  bit sequences
                results,    #individual per-bit results
                res_avg,     # averaged eye data tablle, each line has 8 elements, or [] for bad measurements
                corr_fine,    # fine delay correction
                ends_dist/256.0,   # find where all bits are above/below that distance from 0.0/1.0margin
                verbose)
#            VERBOSE=verbose
#            print ("VERBOSE=",VERBOSE)
            print ("dly_corr=",dly_corr)
            print ("use_dq=",use_dq)
            if dly_corr and use_dq: # only adjusting DQ delays, not DQS
                dly_comb=combine_delay(dly_corr)
                if use_odelay:
                    self.x393_mcntrl_timing.axi_set_dq_odelay((dly_comb[0:8],dly_comb[8:16]))
                    """
                    for i in range (8):
                        axi_set_dly_single(0,i,combine_delay(dly_corr[i]))    
                    for i in range (8):
                        axi_set_dly_single(2,i,combine_delay(dly_corr[i+8]))
                    """
                else: 
                    self.x393_mcntrl_timing.axi_set_dq_idelay((dly_comb[0:8],dly_comb[8:16]))
                    """
                    for i in range (8):
                        axi_set_dly_single(1,i,combine_delay(dly_corr[i]))    
                    for i in range (8):
                        axi_set_dly_single(3,i,combine_delay(dly_corr[i+8]))
                    """
    #          use_dq, # 0 - scan dqs, 1 - scan dq (common valuwe, post-adjustment)
    #      use_odelay,
            
#        VEBOSE=saved_verbose
        return dly_corr
Пример #2
0
    def adjust_dq_idelay(self,
                         low_delay,
                         high_delay,
                         num=8,
                         sel=1, # 0 - early, 1 - late read command (shift by a SDCLK period) 
                         falling=0, # 0 - use rising as delay increases, 1 - use falling
                         smooth=10,
                         quiet=2):
        """
        Adjust individual per-line DQ delays using read pattern mode
        DQS idelay(s) should be set 90-degrees from the final values
        <low_delay>   low delay value (in 'hardware' format, sparse)
        <high_delay>  high delay value (in 'hardware' format, sparse)
        <num>         number of 64-bit words to process
        <sel>         0 - early, 1 - late read command (shift by a SDCLK period) 
        <falling>     0 - use rising edge as delay increases, 1 - use falling one
                      In 'falling' mode results are the longest DQ idelay
                      when bits switch from correct to incorrect,
                      In 'rising' mode (falling==0) - the shortest one
        <smooth>      number of times to run LPF
        <quiet>       less output
        Returns:      list of 16 per-line delay values (sequential, not 'hardware')
        """
        checkIntArgs(('low_delay','high_delay','num'),locals())
        low = split_delay(low_delay)
        data_raw=self.scan_dq_idelay(low_delay,high_delay,num,sel,quiet)
        data=[]
        delays=[]
        for i,d in enumerate(data_raw):
            if len(d)>0:
                data.append(d)
                delays.append(i+low)
        if (quiet<2):
            print(delays)
        
        centerRaw=num*2.0# center value
        uncert=[] #"uncertanty of read for each bit and even/odd words. list of 32-element lists, each positive in the [0,1] interval
        rate=[]   # data change rate
        lm1=len(data)-1
        for i in range (0,len(data)):
            im1=(0,  i-1)[i>0]
            ip1=(lm1,i+1)[i<lm1]
            r_uncert=[]
            r_rate=[]
            for j in range (32):
                d=0.5*data[i][j]+0.25*(data[ip1][j]+data[im1][j])
                r=data[im1][j]-data[ip1][j]
                if (j>=16):
                    r=-r
                r_uncert.append(1.0-((d-centerRaw)/centerRaw)**2) #0 and max -> 0, center ->1.0
                r_rate.append(r/(2.0*centerRaw))
            uncert.append(r_uncert)
            rate.append(r_rate)
#            print ("%d %s"%(i,str(r_uncert)))
        for _ in range(smooth):
            uncert=smooth2d(uncert)
        for _ in range(smooth):
            rate= smooth2d(rate)
        val=[] # list of 16-element rows of composite uncert*rate values, multiplied for odd/even values, hoping not to have
        #         any bumps causes by asymmetry 0->1 and 1-->0
        for i in range (0,len(data)):
            r_val=[]
            for j in range(16):
                sign=(-1,1)[rate[i][j]>0]
                rr=rate[i][j]*rate[i][j+16]
#                if falling:
#                    sign=-sign
                if rr<0:
                    sign=0 # different slope direction - ignore                
                r_val.append(sign * rr * uncert[i][j] * uncert[i][j+16])
            val.append(r_val)
        best_dlys=[None]*16
        best_diffs=[None]*16
        for i in range (len(val)):
            for j in range (16):
                v=val[i][j]
                if falling:
                    v=-v
                if (best_dlys[j] is None) or (v>best_diffs[j]):
                    best_dlys[j]=  i+1
                    best_diffs[j]= v
        if quiet <2:
            for i in range (len(data)):
                print("%d "%(i),end="")
                for j in range (32):
                    print("%f "%uncert[i][j],end="")
                for j in range (32):
                    print("%f "%rate[i][j],end="")
                for j in range (16):
                    print("%f "%(val[i][j]),end="")
                print()
        
        for i in range (16):
            print("%2d: %3d (0x%02x)"%(i,best_dlys[i],combine_delay(best_dlys[i])))
        comb_delays=combine_delay(best_dlys)
        self.x393_mcntrl_timing.axi_set_dq_idelay((comb_delays[0:8],comb_delays[8:16]))
        return best_dlys       
Пример #3
0
 def scan_dq_idelay(self,
                    low_delay,
                    high_delay,
                    num=8,
                    sel=1,#  0 - early, 1 - late read command (shift by a SDCLK period) 
                    quiet=2 ):
     """
     Scan DQ input delay values using pattern read mode
     <low_delay>   low delay value (in 'hardware' format, sparse)
     <high_delay>  high delay value (in 'hardware' format, sparse)
     <num>         number of 64-bit words to process
     <sel>         0 - early, 1 - late read command (shift by a SDCLK period) 
     <quiet>       less output
     """
     checkIntArgs(('low_delay','high_delay','num'),locals())
     self.x393_pio_sequences.set_read_pattern(num+1,sel) # do not use first/last pair of the 32 bit words
     low = split_delay(low_delay)
     high = split_delay(high_delay)
     results = []
     for dly in range (low, high+1):
         enc_dly=combine_delay(dly)
         self.x393_mcntrl_timing.axi_set_dq_idelay(enc_dly) # same value to all DQ lines
         buf= self.x393_pio_sequences.read_pattern(
                  (4*num+2),     # num,
                  0,             # show_rslt,
                  1) # Wait for operation to complete
         if not quiet:
             hbuf=[]
             for dd in buf:
                 hbuf.append(hex(dd))
             print(hbuf)
         # with "good" data each word in buf should be 0xff00ff00
         if self.bad_data(buf):
             results.append([])
         else:    
             data=[0]*32 # for each bit - even, then for all - odd
             for w in range (4*num):    # read 32-bit word number
                 lane=w%2               # even words - lane 0, odd - lane 1
                 for wb in range(32):
                     g=(wb/8)%2
                     b=wb%8+lane*8+16*g
                     if (buf[w+2] & (1<<wb) != 0):# buf[w+2] - skip first 2 words
                         data[b]+=1
             results.append(data)
             #When all correct, data[:16] should be all 0, data[16:] - maximal, (with num=8  - 32)
             if not quiet: 
                 print ("%3d (0x%02x): "%(dly,enc_dly),end="")
                 for i in range(32):
                     print("%5x"%data[i],end="")
                 print()
     if quiet <2:                
         for index in range (len(results)):
             dly=index+low
             enc_dly=combine_delay(dly)
             if (len (results[index])>0):
                 print ("%3d (0x%02x): "%(dly,enc_dly),end="")
                 for i in range(32):
                     print("%5x"%results[index][i],end="")
                 print()    
         print()
     if quiet <3:                
         print()
         print ("Delay",end=" ")
         for i in range(16):
             print ("Bit%dP"%i,end=" ")
         for i in range(16):
             print ("Bit%dM"%i,end=" ")
         print()
         for index in range (len(results)):
             dly=index+low
             enc_dly=combine_delay(dly)
             if (len (results[index])>0):
                 print ("%d"%(dly),end=" ")
                 for i in range(32):
                     print("%d"%results[index][i],end=" ")
                 print()    
         print()
     return results                                  
Пример #4
0
    def scan_or_adjust_delay_random(self, low_delay, high_delay, use_dq,
                                    use_odelay, ends_dist, min_diff, adjust,
                                    verbose):
        """
        Scan or adjust delays using random data write+read
        <low_delay>   Low delay value to tru
        <high_delay>  high delay value to try
        <use_dq>      0 - scan dqs, 1 - scan dq (common value, post-adjustment)
        <use_odelay>  0 - use input delays, 1 - use output delays
        <ends_dist>   do not process if one of the primary interval ends is within this from 0.0 or 1.0
        <min_diff>    minimal difference between primary delay steps to process 
        <adjust>      0 - scan, 1 - adjust
        <verbose>:    verbose mode (more prints) 
        Returns list of calculated delay values
        """
        checkIntArgs(('low_delay', 'high_delay'), locals())
        brc = (
            5,  # 3'h5,     # bank
            0x1234,  # 15'h1234, # row address
            0x100)  # 10'h100   # column address

        #        global BASEADDR_PORT1_WR,VERBOSE;
        #        saved_verbose=VERBOSE;
        #        VERBOSE=False;
        low = split_delay(low_delay)
        high = split_delay(high_delay)
        rand16 = []
        for i in range(512):
            rand16.append(random.randint(0, 65535))
        wdata = convert_mem16_to_w32(rand16)
        if (verbose and not adjust): print("rand16:")
        for i in range(len(rand16)):
            if (i & 0x1f) == 0:
                if (verbose and not adjust): print("\n%03x:" % i, end=" ")
            if (verbose and not adjust): print("%04x" % rand16[i], end=" ")
        if (verbose and not adjust): print("\n")
        if (verbose and not adjust): print("wdata:")
        for i in range(len(wdata)):
            if (i & 0xf) == 0:
                if (verbose and not adjust): print("\n%03x:" % i, end=" ")
            if (verbose and not adjust): print("%08x" % wdata[i], end=" ")
        if (verbose and not adjust): print("\n")
        bit_type = []  # does not include first and last elements
        for i in range(1, 511):
            types = []
            for j in range(16):
                types.append((((rand16[i - 1] >> j) & 1) << 2)
                             | (((rand16[i] >> j) & 1) << 1)
                             | (((rand16[i + 1] >> j) & 1)))
            bit_type.append(types)
    #        if (verbose and not adjust): print ("i=%d",i)
    #        if (verbose and not adjust): print(types)
    #    total_types=[[0]*8]*16 # number of times each type occurred in the block for each DQ bit (separate for DG up/down?)
        total_types = [
        ]  # number of times each type occurred in the block for each DQ bit (separate for DG up/down?)
        for i in range(16):
            total_types.append([0] * 8)
        for typ in bit_type:
            #        if (verbose and not adjust): print(typ)
            for j in range(16):
                #            total_types[j][typ[j]]+=1
                total_types[j][typ[j]] = total_types[j][typ[j]] + 1
        if (verbose and not adjust): print("\ntotal_types:")
        if (verbose and not adjust): print(total_types)

        avg_types = [0.0] * 8
        N = 0
        for t in total_types:
            for j, n in enumerate(t):
                avg_types[j] += n
                N += n
        for i in range(len(avg_types)):
            avg_types[i] /= N
        if (verbose and not adjust): print("\avg_types:")
        if (verbose and not adjust): print(avg_types)
        #write blok buffer with 256x32bit data

        self.x393_mcntrl_buffers.write_block_buf_chn(0, 0, wdata)
        # fill block memory (channel, page, number)

        self.x393_pio_sequences.set_write_block(
            *brc)  #64 8-bursts, 1 extra DQ/DQS/ active cycle
        self.x393_pio_sequences.set_read_block(*brc)

        if (use_odelay == 0):
            self.x393_pio_sequences.write_block(
                0, 1)  # Wait for operation to complete
            if verbose: print("++++++++ block written once")
    #now scanning - first DQS, then try with DQ (post-adjustment - best fit)
        results = []
        if verbose:
            print("******** use_odelay=%d use_dq=%d" % (use_odelay, use_dq))
        alreadyWarned = False
        for dly in range(low, high + 1):
            enc_dly = combine_delay(dly)
            if (use_odelay != 0):
                if (use_dq != 0):
                    if verbose:
                        print("******** axi_set_dq_odelay(0x%x)" % enc_dly)
                    self.x393_mcntrl_timing.axi_set_dq_odelay(
                        enc_dly)  #  set the same odelay for all DQ bits
                else:
                    if verbose:
                        print("******** axi_set_dqs_odelay(0x%x)" % enc_dly)
                    self.x393_mcntrl_timing.axi_set_dqs_odelay(enc_dly)
                self.x393_pio_sequences.write_block(
                    0, 1)  # Wait for operation to complete
                if verbose: print("-------- block written AGAIN")
            else:
                if (use_dq != 0):
                    if verbose:
                        print("******** axi_set_dq_idelay(0x%x)" % enc_dly)
                    self.x393_mcntrl_timing.axi_set_dq_idelay(
                        enc_dly)  #  set the same idelay for all DQ bits
                else:
                    if verbose:
                        print("******** axi_set_dqs_idelay(0x%x)" % enc_dly)
                    self.x393_mcntrl_timing.axi_set_dqs_idelay(enc_dly)
            buf32 = self.x393_pio_sequences.read_block(
                256,  # num,
                0,  # show_rslt,
                1)  # Wait for operation to complete
            if self.bad_data(buf32):
                results.append([])
            else:
                # Warn about possible missing DQS pulses during writes
                alreadyWarned |= self.missing_dqs(buf32, alreadyWarned)
                read16 = convert_w32_to_mem16(
                    buf32)  # 512x16 bit, same as DDR3 DQ over time
                if verbose and (dly == low):
                    if (verbose and not adjust): print("buf32:")
                    for i in range(len(buf32)):
                        if (i & 0xf) == 0:
                            if (verbose and not adjust):
                                print("\n%03x:" % i, end=" ")
                        if (verbose and not adjust):
                            print("%08x" % buf32[i], end=" ")
                    if (verbose and not adjust): print("\n")

                    if (verbose and not adjust): print("read16:")
                    for i in range(len(read16)):
                        if (i & 0x1f) == 0:
                            if (verbose and not adjust):
                                print("\n%03x:" % i, end=" ")
                        if (verbose and not adjust):
                            print("%04x" % read16[i], end=" ")
                    if (verbose and not adjust): print("\n")
                data = [
                ]  # number of times each type occurred in the block for each DQ bit (separate for DG up/down?)
                for i in range(16):
                    data.append([0] * 8)

                for i in range(1, 511):
                    w = read16[i]
                    typ = bit_type[
                        i -
                        1]  # first and last words are not used, no type was calculated
                    for j in range(16):
                        if (w & (1 << j)) != 0:
                            data[j][typ[j]] += 1
                for i in range(16):
                    for t in range(8):
                        if (total_types[i][t] > 0):
                            data[i][t] *= 1.0 / total_types[i][t]
                results.append(data)
                if (verbose and not adjust):
                    print("%3d (0x%02x): " % (dly, enc_dly), end="")
                for i in range(16):
                    if (verbose and not adjust): print("[", end="")
                    for j in range(8):
                        if (verbose and not adjust):
                            print("%3d" % (round(100.0 * data[i][j])), end=" ")
                    if (verbose and not adjust): print("]", end=" ")
                if (verbose and not adjust): print()
        titles = [
            "'000", "'001", "'010", "'011", "'100", "'101", "'110", "'111"
        ]
        #calculate weighted averages
        #TODO: for DQ scan shift individual bits for the best match
        if use_dq:
            if (verbose and not adjust):
                print(
                    "TODO: shift individual bits for the best match before averaging"
                )

        res_avg = []
        for dly in range(len(results)):
            if (len(results[dly]) > 0):
                data = results[dly]
                avg = [0.0] * 8
                for t in range(8):
                    weight = 0
                    d = 0.0
                    for i in range(16):
                        weight += total_types[i][t]
                        d += total_types[i][t] * data[i][t]
                    if (weight > 0):
                        d /= weight
                    avg[t] = d
                res_avg.append(avg)
            else:
                res_avg.append([])
        corr_fine = self.calibrate_finedelay(
            low,  # absolute delay value of start scan
            avg_types,  # weights of weach of the 8  bit sequences
            res_avg,  # averaged eye data tablle, each line has 8 elements, or [] for bad measurements
            ends_dist /
            256.0,  # ends_dist,   # do not process if one of the primary interval ends is within this from 0.0 or 1.0
            min_diff / 256.0
        )  #min_diff):   # minimal difference between primary delay steps to process
        period = len(corr_fine)

        if (not adjust):
            print(
                "\n\n\n========== Copy below to the spreadsheet,  use columns from corr_delay =========="
            )
            print(
                "========== First are individual results for each bit, then averaged eye pattern =========="
            )
            print("delay corr_delay", end=" ")
            for t in range(8):
                for i in range(16):
                    if (not adjust): print("%02d:%s" % (i, titles[t]), end=" ")
            print()
            for index in range(len(results)):
                if (len(results[index]) > 0):
                    dly = index + low
                    corr_dly = dly + corr_fine[dly % period]
                    print("%d %.2f" % (dly, corr_dly), end=" ")
                    for t in range(8):
                        for i in range(16):
                            try:
                                print("%.4f" % (results[dly][i][t]), end=" "
                                      )  #IndexError: list index out of range
                            except:
                                print(".????", end="")
                    print()

            print(
                "\n\n\n========== Copy below to the spreadsheet,  use columns from corr_delay =========="
            )
            print(
                "========== data above can be used for the individual bits eye patterns =========="
            )
            print("delay corr_delay", end=" ")
            for t in range(8):
                print(titles[t], end=" ")
            print()
            for index in range(len(res_avg)):
                if (len(res_avg[index]) > 0):
                    dly = index + low
                    corr_dly = dly + corr_fine[dly % period]
                    print("%d %.2f" % (dly, corr_dly), end=" ")
                    for t in range(8):
                        try:
                            print("%.4f" % (res_avg[dly][t]), end=" ")
                        except:
                            print(".????", end=" ")
                    print()
        dly_corr = None
        if adjust:
            dly_corr = self.corr_delays(
                low,  # absolute delay value of start scan
                avg_types,  # weights of weach of the 8  bit sequences
                results,  #individual per-bit results
                res_avg,  # averaged eye data tablle, each line has 8 elements, or [] for bad measurements
                corr_fine,  # fine delay correction
                ends_dist /
                256.0,  # find where all bits are above/below that distance from 0.0/1.0margin
                verbose)
            #            VERBOSE=verbose
            #            print ("VERBOSE=",VERBOSE)
            print("dly_corr=", dly_corr)
            print("use_dq=", use_dq)
            if dly_corr and use_dq:  # only adjusting DQ delays, not DQS
                dly_comb = combine_delay(dly_corr)
                if use_odelay:
                    self.x393_mcntrl_timing.axi_set_dq_odelay(
                        (dly_comb[0:8], dly_comb[8:16]))
                    """
                    for i in range (8):
                        axi_set_dly_single(0,i,combine_delay(dly_corr[i]))    
                    for i in range (8):
                        axi_set_dly_single(2,i,combine_delay(dly_corr[i+8]))
                    """
                else:
                    self.x393_mcntrl_timing.axi_set_dq_idelay(
                        (dly_comb[0:8], dly_comb[8:16]))
                    """
                    for i in range (8):
                        axi_set_dly_single(1,i,combine_delay(dly_corr[i]))    
                    for i in range (8):
                        axi_set_dly_single(3,i,combine_delay(dly_corr[i+8]))
                    """

    #          use_dq, # 0 - scan dqs, 1 - scan dq (common valuwe, post-adjustment)
    #      use_odelay,

#        VEBOSE=saved_verbose
        return dly_corr
Пример #5
0
    def adjust_dq_idelay(
            self,
            low_delay,
            high_delay,
            num=8,
            sel=1,  # 0 - early, 1 - late read command (shift by a SDCLK period) 
            falling=0,  # 0 - use rising as delay increases, 1 - use falling
            smooth=10,
            quiet=2):
        """
        Adjust individual per-line DQ delays using read pattern mode
        DQS idelay(s) should be set 90-degrees from the final values
        <low_delay>   low delay value (in 'hardware' format, sparse)
        <high_delay>  high delay value (in 'hardware' format, sparse)
        <num>         number of 64-bit words to process
        <sel>         0 - early, 1 - late read command (shift by a SDCLK period) 
        <falling>     0 - use rising edge as delay increases, 1 - use falling one
                      In 'falling' mode results are the longest DQ idelay
                      when bits switch from correct to incorrect,
                      In 'rising' mode (falling==0) - the shortest one
        <smooth>      number of times to run LPF
        <quiet>       less output
        Returns:      list of 16 per-line delay values (sequential, not 'hardware')
        """
        checkIntArgs(('low_delay', 'high_delay', 'num'), locals())
        low = split_delay(low_delay)
        data_raw = self.scan_dq_idelay(low_delay, high_delay, num, sel, quiet)
        data = []
        delays = []
        for i, d in enumerate(data_raw):
            if len(d) > 0:
                data.append(d)
                delays.append(i + low)
        if (quiet < 2):
            print(delays)

        centerRaw = num * 2.0  # center value
        uncert = [
        ]  #"uncertanty of read for each bit and even/odd words. list of 32-element lists, each positive in the [0,1] interval
        rate = []  # data change rate
        lm1 = len(data) - 1
        for i in range(0, len(data)):
            im1 = (0, i - 1)[i > 0]
            ip1 = (lm1, i + 1)[i < lm1]
            r_uncert = []
            r_rate = []
            for j in range(32):
                d = 0.5 * data[i][j] + 0.25 * (data[ip1][j] + data[im1][j])
                r = data[im1][j] - data[ip1][j]
                if (j >= 16):
                    r = -r
                r_uncert.append(1.0 - ((d - centerRaw) / centerRaw)**
                                2)  #0 and max -> 0, center ->1.0
                r_rate.append(r / (2.0 * centerRaw))
            uncert.append(r_uncert)
            rate.append(r_rate)
#            print ("%d %s"%(i,str(r_uncert)))
        for _ in range(smooth):
            uncert = smooth2d(uncert)
        for _ in range(smooth):
            rate = smooth2d(rate)
        val = [
        ]  # list of 16-element rows of composite uncert*rate values, multiplied for odd/even values, hoping not to have
        #         any bumps causes by asymmetry 0->1 and 1-->0
        for i in range(0, len(data)):
            r_val = []
            for j in range(16):
                sign = (-1, 1)[rate[i][j] > 0]
                rr = rate[i][j] * rate[i][j + 16]
                #                if falling:
                #                    sign=-sign
                if rr < 0:
                    sign = 0  # different slope direction - ignore
                r_val.append(sign * rr * uncert[i][j] * uncert[i][j + 16])
            val.append(r_val)
        best_dlys = [None] * 16
        best_diffs = [None] * 16
        for i in range(len(val)):
            for j in range(16):
                v = val[i][j]
                if falling:
                    v = -v
                if (best_dlys[j] is None) or (v > best_diffs[j]):
                    best_dlys[j] = i + 1
                    best_diffs[j] = v
        if quiet < 2:
            for i in range(len(data)):
                print("%d " % (i), end="")
                for j in range(32):
                    print("%f " % uncert[i][j], end="")
                for j in range(32):
                    print("%f " % rate[i][j], end="")
                for j in range(16):
                    print("%f " % (val[i][j]), end="")
                print()

        for i in range(16):
            print("%2d: %3d (0x%02x)" %
                  (i, best_dlys[i], combine_delay(best_dlys[i])))
        comb_delays = combine_delay(best_dlys)
        self.x393_mcntrl_timing.axi_set_dq_idelay(
            (comb_delays[0:8], comb_delays[8:16]))
        return best_dlys
Пример #6
0
 def scan_dq_idelay(
     self,
     low_delay,
     high_delay,
     num=8,
     sel=1,  #  0 - early, 1 - late read command (shift by a SDCLK period) 
     quiet=2):
     """
     Scan DQ input delay values using pattern read mode
     <low_delay>   low delay value (in 'hardware' format, sparse)
     <high_delay>  high delay value (in 'hardware' format, sparse)
     <num>         number of 64-bit words to process
     <sel>         0 - early, 1 - late read command (shift by a SDCLK period) 
     <quiet>       less output
     """
     checkIntArgs(('low_delay', 'high_delay', 'num'), locals())
     self.x393_pio_sequences.set_read_pattern(
         num + 1, sel)  # do not use first/last pair of the 32 bit words
     low = split_delay(low_delay)
     high = split_delay(high_delay)
     results = []
     for dly in range(low, high + 1):
         enc_dly = combine_delay(dly)
         self.x393_mcntrl_timing.axi_set_dq_idelay(
             enc_dly)  # same value to all DQ lines
         buf = self.x393_pio_sequences.read_pattern(
             (4 * num + 2),  # num,
             0,  # show_rslt,
             1)  # Wait for operation to complete
         if not quiet:
             hbuf = []
             for dd in buf:
                 hbuf.append(hex(dd))
             print(hbuf)
         # with "good" data each word in buf should be 0xff00ff00
         if self.bad_data(buf):
             results.append([])
         else:
             data = [0] * 32  # for each bit - even, then for all - odd
             for w in range(4 * num):  # read 32-bit word number
                 lane = w % 2  # even words - lane 0, odd - lane 1
                 for wb in range(32):
                     g = (wb / 8) % 2
                     b = wb % 8 + lane * 8 + 16 * g
                     if (buf[w + 2] &
                         (1 << wb) != 0):  # buf[w+2] - skip first 2 words
                         data[b] += 1
             results.append(data)
             #When all correct, data[:16] should be all 0, data[16:] - maximal, (with num=8  - 32)
             if not quiet:
                 print("%3d (0x%02x): " % (dly, enc_dly), end="")
                 for i in range(32):
                     print("%5x" % data[i], end="")
                 print()
     if quiet < 2:
         for index in range(len(results)):
             dly = index + low
             enc_dly = combine_delay(dly)
             if (len(results[index]) > 0):
                 print("%3d (0x%02x): " % (dly, enc_dly), end="")
                 for i in range(32):
                     print("%5x" % results[index][i], end="")
                 print()
         print()
     if quiet < 3:
         print()
         print("Delay", end=" ")
         for i in range(16):
             print("Bit%dP" % i, end=" ")
         for i in range(16):
             print("Bit%dM" % i, end=" ")
         print()
         for index in range(len(results)):
             dly = index + low
             enc_dly = combine_delay(dly)
             if (len(results[index]) > 0):
                 print("%d" % (dly), end=" ")
                 for i in range(32):
                     print("%d" % results[index][i], end=" ")
                 print()
         print()
     return results