Commit a7004146 authored by Andrey Filippov's avatar Andrey Filippov

some cleanup, added command that runs full set of measurement/adjustment functions

parent 4a9e4b55
...@@ -914,7 +914,8 @@ def get_wlev_data(): ...@@ -914,7 +914,8 @@ def get_wlev_data():
{'ldly': 68, 'period': 0, 'err': 0.032233890055650249}, {'ldly': 67, 'period': 0, 'err': 0.45716638330499393}, {'ldly': 64, 'period': 0, 'err': -0.23339414538470038}, {'ldly': 68, 'period': 0, 'err': 0.032233890055650249}, {'ldly': 67, 'period': 0, 'err': 0.45716638330499393}, {'ldly': 64, 'period': 0, 'err': -0.23339414538470038},
{'ldly': 63, 'period': 0, 'err': -0.42992632596594405}, {'ldly': 62, 'period': 0, 'err': -0.004993832716600366}, {'ldly': 59, 'period': 0, 'err': -0.69555436140630178}, {'ldly': 63, 'period': 0, 'err': -0.42992632596594405}, {'ldly': 62, 'period': 0, 'err': -0.004993832716600366}, {'ldly': 59, 'period': 0, 'err': -0.69555436140630178},
{'ldly': 59, 'period': 0, 'err': 0.81705889991982161}, {'ldly': 56, 'period': 0, 'err': -0.030778077807781301}, {'ldly': 57, 'period': 0, 'err': 1.0454592125879216}, {'ldly': 59, 'period': 0, 'err': 0.81705889991982161}, {'ldly': 56, 'period': 0, 'err': -0.030778077807781301}, {'ldly': 57, 'period': 0, 'err': 1.0454592125879216},
{'ldly': 54, 'period': 0, 'err': 0.35489868389822021}], [{'ldly': 50, 'period': -1, 'err': 0.90683082593974973}, {'ldly': 49, 'period': -1, 'err': 0.52528052805281789}, {'ldly': 54, 'period': 0, 'err': 0.35489868389822021}],
[{'ldly': 50, 'period': -1, 'err': 0.90683082593974973}, {'ldly': 49, 'period': -1, 'err': 0.52528052805281789},
{'ldly': 46, 'period': -1, 'err': -0.10166902404525047}, {'ldly': 45, 'period': -1, 'err': 0.38526466932408709}, {'ldly': 44, 'period': -1, 'err': 0.0037143714371552505}, {'ldly': 46, 'period': -1, 'err': -0.10166902404525047}, {'ldly': 45, 'period': -1, 'err': 0.38526466932408709}, {'ldly': 44, 'period': -1, 'err': 0.0037143714371552505},
{'ldly': 42, 'period': -1, 'err': 0.1118091809181081}, {'ldly': 40, 'period': -1, 'err': -0.13630148729157554}, {'ldly': 39, 'period': -1, 'err': -0.51785178517850738}, {'ldly': 42, 'period': -1, 'err': 0.1118091809181081}, {'ldly': 40, 'period': -1, 'err': -0.13630148729157554}, {'ldly': 39, 'period': -1, 'err': -0.51785178517850738},
{'ldly': 37, 'period': -1, 'err': -0.40975697569755454}, {'ldly': 36, 'period': -1, 'err': 0.34800994385153672}, {'ldly': 35, 'period': -1, 'err': 0.83494363722087428}, {'ldly': 37, 'period': -1, 'err': -0.40975697569755454}, {'ldly': 36, 'period': -1, 'err': 0.34800994385153672}, {'ldly': 35, 'period': -1, 'err': 0.83494363722087428},
...@@ -1025,6 +1026,27 @@ def get_dqsi_vs_phase(variant): ...@@ -1025,6 +1026,27 @@ def get_dqsi_vs_phase(variant):
[(None, None, 'e'), (150, 0.75, 'e')], None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, [(None, None, 'e'), (150, 0.75, 'e')], None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
[(20, None, 'n'), (7, -0.25, 'n')], [(29, 0.25, 'n'), (5, None, 'n')], [(25, None, 'n'), (10, 0.75, 'n')], [(25, None, 'n'), (14, 0.25, 'n')], [(20, None, 'n'), (7, -0.25, 'n')], [(29, 0.25, 'n'), (5, None, 'n')], [(25, None, 'n'), (10, 0.75, 'n')], [(25, None, 'n'), (14, 0.25, 'n')],
[(31, 0.75, 'n'), (10, None, 'n')], [(34, 0.0, 'n'), (16, -0.25, 'n')], [(30, None, 'n'), (17, 0.0, 'n')], [(30, None, 'n'), (19, -0.75, 'n')]] [(31, 0.75, 'n'), (10, None, 'n')], [(34, 0.0, 'n'), (16, -0.25, 'n')], [(30, None, 'n'), (17, 0.0, 'n')], [(30, None, 'n'), (19, -0.75, 'n')]]
elif variant ==1:
return [[(36, 0.5, 'n'), (15, None, 'n')], [(39, 0.25, 'n'), (22, 0.5, 'n')], [(35, None, 'n'), (24, 0.0, 'n')], [(35, None, 'n'), (20, None, 'n')],
[(38, None, 'n'), (26, 0.75, 'n')], [(44, 0.0, 'n'), (28, -0.25, 'n')], [(40, None, 'n'), (29, -0.5, 'n')], [(45, 0.0, 'n'), (30, 0.5, 'n')],
[(46, 0.25, 'n'), (32, 0.25, 'n')], [(45, None, 'n'), (33, -0.25, 'n')], [(45, None, 'n'), (30, None, 'n')], [(45, None, 'n'), (35, 0.75, 'n')],
[(53, 0.75, 'n'), (38, -0.25, 'n')], [(50, None, 'n'), (39, -0.75, 'n')], [(50, None, 'n'), (41, 0.5, 'n')], [(56, 0.75, 'n'), (44, 0.5, 'n')],
[(55, None, 'n'), (40, None, 'n')], [(55, None, 'n'), (40, None, 'n')], [(56, None, 'n'), (47, -0.25, 'n')], [(63, 0.25, 'n'), (45, None, 'n')],
[(60, None, 'n'), (45, None, 'n')], [(65, 0.25, 'n'), (54, 0.25, 'n')], [(66, 0.0, 'n'), (54, -0.25, 'n')], [(65, None, 'n'), (50, None, 'n')],
[(65, None, 'n'), (56, 0.0, 'n')], [(70, 0.5, 'n'), (59, -0.5, 'n')], [(71, 0.25, 'n'), (55, None, 'n')], [(70, None, 'n'), (55, None, 'n')],
[(70, None, 'n'), (64, 0.25, 'n')], [(76, 0.5, 'n'), (60, None, 'n')], [(75, None, 'n'), (60, None, 'n')], [(75, None, 'n'), (65, -0.5, 'n')],
None, [(84, 0.0, 'n'), (65, None, 'n')], [(80, None, 'n'), (71, -0.25, 'n')], [(None, None, 'n'), (73, -0.75, 'n')], None, None, None, None,
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
[(127, 0.5, 'e'), (116, -0.75, 'e')], [(125, None, 'e'), (115, None, 'e')], [(125, None, 'e'), (120, 0.5, 'e')], [(130, 0.5, 'e'), (123, 0.0, 'e')],
[(131, 0.0, 'e'), (119, None, 'e')], [(134, 0.0, 'e'), (120, None, 'e')], [(130, None, 'e'), (120, None, 'e')], [(131, None, 'e'), (127, 0.0, 'e')],
[(135, None, 'e'), (124, None, 'e')], [(135, None, 'e'), (125, None, 'e')], [(140, 0.25, 'e'), (131, 0.25, 'e')], [(141, 0.25, 'e'), (134, 0.0, 'e')],
[(140, None, 'e'), (130, None, 'e')], [(140, None, 'e'), (130, None, 'e')], [(140, None, 'e'), (135, -0.5, 'e')], [(149, 0.25, 'e'), (135, None, 'e')],
[(145, None, 'e'), (135, None, 'e')], [(145, None, 'e'), (135, None, 'e')], [(151, 0.75, 'e'), (141, 0.0, 'e')], [(150, None, 'e'), (140, None, 'e')],
[(150, None, 'e'), (145, 0.75, 'e')], [(155, 0.0, 'e'), (145, 0.25, 'e')], [(158, 0.0, 'e'), (149, -0.5, 'e')], None, None, None, None,
None, None, None, None, None, None, None, None, None, None, None, None, None, [(26, 0.25, 'n'), (9, -0.5, 'n')], [(29, 0.25, 'n'), (10, 0.0, 'n')],
[(25, None, 'n'), (13, 0.5, 'n')], [(25, None, 'n'), (10, None, 'n')], [(33, 0.25, 'n'), (10, None, 'n')], [(30, None, 'n'), (17, -0.25, 'n')],
[(30, None, 'n'), (18, -0.5, 'n')]]
def get_dqsi_vs_phase_prim_steps(variant=0): def get_dqsi_vs_phase_prim_steps(variant=0):
# while scanning, compare this delay with 1 less by primary(not fine) step, # while scanning, compare this delay with 1 less by primary(not fine) step,
# save None for fraction in unknown (previous -0.5, next +0.5) # save None for fraction in unknown (previous -0.5, next +0.5)
......
...@@ -311,9 +311,12 @@ class X393LMA(object): ...@@ -311,9 +311,12 @@ class X393LMA(object):
except: except:
pass pass
if not numBits: if not numBits:
# print("showENLresults(): No no-None data provided")
# print("DQvDQS=",DQvDQS)
# return
raise Exception("showENLresults(): No no-None data provided") raise Exception("showENLresults(): No no-None data provided")
numLanes=numBits//8 numLanes=numBits//8
# print ("numBits=%d"%(numBits)) # print ("****numBits=%d"%(numBits))
enl_list=[] enl_list=[]
for k in rslt_names: for k in rslt_names:
if DQvDQS[k]: if DQvDQS[k]:
...@@ -1036,7 +1039,7 @@ class X393LMA(object): ...@@ -1036,7 +1039,7 @@ class X393LMA(object):
if quiet < 2: if quiet < 2:
print ("parameters=%s"%(str(parameters))) print ("parameters=%s"%(str(parameters)))
self.normalizeParameters(parameters) #isMask=False) self.normalizeParameters(parameters) #isMask=False)
if quiet < 4: if quiet < 3:
print ("normalized parameters=%s"%(str(parameters))) print ("normalized parameters=%s"%(str(parameters)))
""" """
both ways work: both ways work:
...@@ -1069,12 +1072,13 @@ class X393LMA(object): ...@@ -1069,12 +1072,13 @@ class X393LMA(object):
print("\nfx (filtered):") print("\nfx (filtered):")
self.showYOrVector(ywp,True,fx) self.showYOrVector(ywp,True,fx)
if quiet < 4: if quiet < 5:
arms = self.getParAvgRMS(parameters, arms = self.getParAvgRMS(parameters,
ywp, ywp,
primary_set, # prima primary_set, # prima
quiet+1) quiet+1)
print ("average(fx)= %fps, rms(fx)=%fps"%(arms['avg'],arms['rms'])) print ("Before LMA (DQ lane %d): average(fx)= %fps, rms(fx)=%fps"%(lane,arms['avg'],arms['rms']))
if quiet < 3: if quiet < 3:
jByJT=np.dot(fxj['jacob'],np.transpose(fxj['jacob'])) jByJT=np.dot(fxj['jacob'],np.transpose(fxj['jacob']))
print("\njByJT:") print("\njByJT:")
...@@ -1092,7 +1096,7 @@ class X393LMA(object): ...@@ -1092,7 +1096,7 @@ class X393LMA(object):
self.lambdas, self.lambdas,
self.finalDiffRMS, self.finalDiffRMS,
quiet) quiet)
if (quiet < 4) or ((quiet < 5) and finished): if (quiet < 5) or ((quiet < 6) and finished):
arms = self.getParAvgRMS(parameters, arms = self.getParAvgRMS(parameters,
ywp, ywp,
primary_set, # prima primary_set, # prima
...@@ -1126,36 +1130,6 @@ class X393LMA(object): ...@@ -1126,36 +1130,6 @@ class X393LMA(object):
DQvDQS= DQvDQS_withErr['dqForDqs'] DQvDQS= DQvDQS_withErr['dqForDqs']
DQvDQS_ERR=DQvDQS_withErr['maxErrDqs'] DQvDQS_ERR=DQvDQS_withErr['maxErrDqs']
if quiet < 4:
# print ("DQvDQS_ERR=",DQvDQS_ERR)
enl_list=[]
for i in range(3):
if not DQvDQS[i] is None:
enl_list.append(i)
print("DQS", end=" ")
for enl in enl_list:
for b in range(8):
print("%s%d"%(('E','N','L')[enl],b),end=" ")
for enl in enl_list:
print("%s-Err"%(('E','N','L')[enl]),end=" ")
print()
for dly in range(DLY_STEPS):
print ("%d"%(dly),end=" ")
for enl in enl_list:
if DQvDQS[enl][dly] is None:
print ("? "*8,end="")
else:
for b in range(8):
if DQvDQS[enl][dly][b] is None:
print("?",end=" ")
else:
print("%d"%(DQvDQS[enl][dly][b]),end=" ")
for enl in enl_list:
if DQvDQS_ERR[enl][dly] is None:
print ("? ",end="")
else:
print ("%f"%(DQvDQS_ERR[enl][dly]), end=" ")
print()
rslt={} rslt={}
rslt_names=("early","nominal","late") rslt_names=("early","nominal","late")
for i, d in enumerate(DQvDQS): for i, d in enumerate(DQvDQS):
...@@ -1165,15 +1139,13 @@ class X393LMA(object): ...@@ -1165,15 +1139,13 @@ class X393LMA(object):
rslt['maxErrDqs']={} # {enl}[dly] rslt['maxErrDqs']={} # {enl}[dly]
for i, d in enumerate(DQvDQS_ERR): for i, d in enumerate(DQvDQS_ERR):
rslt['maxErrDqs'][rslt_names[i]] = d rslt['maxErrDqs'][rslt_names[i]] = d
if quiet < 4: if quiet < 3:
self.showDQDQSValues(parameters) self.showDQDQSValues(parameters)
# print ("DQvDQS_ERR=",DQvDQS_ERR) if quiet < 3:
# print ("rslt['maxErrDqs']=",rslt['maxErrDqs']) print ("*** quiet=",quiet)
self.showENLresults(rslt) # here DQvDQS already contain the needed data
return rslt return rslt
# return DQvDQS
# Returns 3-element dictionary of ('early','nominal','late'), each being None or a 160-element list,
# each element being either None, or a list of 3 best DQ delay values for the DQS delay (some mey be None too)
def getBestDQforDQS(self, def getBestDQforDQS(self,
...@@ -1204,7 +1176,8 @@ class X393LMA(object): ...@@ -1204,7 +1176,8 @@ class X393LMA(object):
asym_err=[] asym_err=[]
for i in range(8): for i in range(8):
asym_err.append(0.25*(abs(tDQSHL)+abs(tDQHL[i]))) asym_err.append(0.25*(abs(tDQSHL)+abs(tDQHL[i])))
print("asym_err=",asym_err) if quiet < 3:
print("asym_err=",asym_err)
dqForDqs=[] dqForDqs=[]
maxErrDqs=[] maxErrDqs=[]
for enl in (0,1,2): for enl in (0,1,2):
...@@ -1617,15 +1590,13 @@ class X393LMA(object): ...@@ -1617,15 +1590,13 @@ class X393LMA(object):
lane, # byte lane lane, # byte lane
bin_size_ps, bin_size_ps,
clk_period, clk_period,
# phase_step, # ~22ps dqsi_dqi_parameters,
# dly_step_ds, data_set,
# primary_set, compare_prim_steps,
dqsi_dqi_parameters, scale_w,
data_set, numPhaseSteps,
compare_prim_steps, quiet=1):
scale_w, # print("++++++lma_fit_dqsi_phase(), quiet=",quiet)
numPhaseSteps,
quiet=1):
def show_input_data(filtered): def show_input_data(filtered):
print(('unfiltered','filtered')[filtered]) print(('unfiltered','filtered')[filtered])
for phase,d in enumerate(data_set): for phase,d in enumerate(data_set):
...@@ -1668,7 +1639,8 @@ class X393LMA(object): ...@@ -1668,7 +1639,8 @@ class X393LMA(object):
SX+=binArr[i]*i SX+=binArr[i]*i
if S0>0: if S0>0:
SX/=S0 SX/=S0
print ("SX=",SX) if quiet < 3:
print ("SX=",SX)
return minVal+bin_size_ps*(SX+0.5) # ps return minVal+bin_size_ps*(SX+0.5) # ps
if not isinstance(lane,(int, long)): # ignore content, process both lanes if not isinstance(lane,(int, long)): # ignore content, process both lanes
...@@ -1686,7 +1658,7 @@ class X393LMA(object): ...@@ -1686,7 +1658,7 @@ class X393LMA(object):
compare_prim_steps, compare_prim_steps,
scale_w, scale_w,
numPhaseSteps, numPhaseSteps,
quiet=1) quiet)
for name in rslt_names: for name in rslt_names:
rslt[name].append(rslt_lane[name]) rslt[name].append(rslt_lane[name])
if quiet<3: if quiet<3:
...@@ -1713,8 +1685,9 @@ class X393LMA(object): ...@@ -1713,8 +1685,9 @@ class X393LMA(object):
dbg_tSDQS=(dqsi_dqi_parameters[0]['tSDQS'],dqsi_dqi_parameters[1]['tSDQS']) dbg_tSDQS=(dqsi_dqi_parameters[0]['tSDQS'],dqsi_dqi_parameters[1]['tSDQS'])
halfStep=0.5*(1,compare_prim_steps)[compare_prim_steps] halfStep=0.5*(1,compare_prim_steps)[compare_prim_steps]
#phase_step/tSDQS #phase_step/tSDQS
print (phase_step,dbg_tSDQS) # print("lma_fit_dqsi_phase(): quiet=",quiet)
if quiet < 2: if quiet < 2:
print (phase_step,dbg_tSDQS)
for filtered in range(2): for filtered in range(2):
show_input_data(filtered) show_input_data(filtered)
...@@ -1723,12 +1696,14 @@ class X393LMA(object): ...@@ -1723,12 +1696,14 @@ class X393LMA(object):
minVal= -clk_period minVal= -clk_period
num_bins=int((maxVal-minVal)/bin_size_ps)+1 num_bins=int((maxVal-minVal)/bin_size_ps)+1
binArr=[0]*num_bins binArr=[0]*num_bins
print("minVal=",minVal) if quiet < 2:
print("maxVal=",maxVal) print("minVal=",minVal)
print("num_bins=",num_bins) print("maxVal=",maxVal)
print("num_bins=",num_bins)
#find main max #find main max
dly_max0=get_shift_by_hist() # delay in ps, corresponding to largest maximum dly_max0=get_shift_by_hist() # delay in ps, corresponding to largest maximum
print("max0=%f, (%f)"%(dly_max0,dly_max0/tSDQS)) if quiet < 2:
print("max0=%f, (%f)"%(dly_max0,dly_max0/tSDQS))
periods=[None]*len(data_set) periods=[None]*len(data_set)
for phase,d in enumerate(data_set): for phase,d in enumerate(data_set):
if not d is None: if not d is None:
...@@ -1751,19 +1726,19 @@ class X393LMA(object): ...@@ -1751,19 +1726,19 @@ class X393LMA(object):
dl=d[lane] dl=d[lane]
if (not dl is None) and (not dl[0] is None): if (not dl is None) and (not dl[0] is None):
dly = dl[0] dly = dl[0]
w[i]=1.0 w[phase]=1.0
if dl[1] is None: if dl[1] is None:
dly+=halfStep dly+=halfStep
w[i]=scale_w w[phase]=scale_w
d=dly*tSDQS-periods[phase]*clk_period-tFDQS[dl[0] % FINE_STEPS] d=dly*tSDQS-periods[phase]*clk_period-tFDQS[dl[0] % FINE_STEPS]
y=d-phase*phase_step y=d-phase*phase_step
S0+=w[i] S0+=w[phase]
SY+=w[i]*y SY+=w[phase]*y
if S0 > 0.0: if S0 > 0.0:
SY /= S0 SY /= S0
print ("shift=",SY," ps")
if quiet < 2: if quiet < 2:
print ("shift=",SY," ps")
for phase,d in enumerate(data_set): for phase,d in enumerate(data_set):
print ("%d"%(phase),end=" ") print ("%d"%(phase),end=" ")
if not d is None: if not d is None:
......
...@@ -48,7 +48,7 @@ from verilog_utils import checkIntArgs,smooth2d ...@@ -48,7 +48,7 @@ from verilog_utils import checkIntArgs,smooth2d
import get_test_dq_dqs_data # temporary to test processing import get_test_dq_dqs_data # temporary to test processing
import x393_lma import x393_lma
import time
#import vrlg #import vrlg
NUM_FINE_STEPS= 5 NUM_FINE_STEPS= 5
NUM_DLY_STEPS =NUM_FINE_STEPS * 32 # =160 NUM_DLY_STEPS =NUM_FINE_STEPS * 32 # =160
...@@ -211,7 +211,7 @@ class X393McntrlAdjust(object): ...@@ -211,7 +211,7 @@ class X393McntrlAdjust(object):
def set_phase_with_refresh(self, # check result for not None def set_phase_with_refresh(self, # check result for not None
phase, phase,
quiet=2): quiet=1):
""" """
Set specified phase and matching cmda_odelay while temporarily turning off refresh Set specified phase and matching cmda_odelay while temporarily turning off refresh
@param phase phase to set, signed short @param phase phase to set, signed short
...@@ -231,7 +231,170 @@ class X393McntrlAdjust(object): ...@@ -231,7 +231,170 @@ class X393McntrlAdjust(object):
self.x393_mcntrl_timing.axi_set_cmda_odelay(self.combine_delay(cmda_odly_lin),quiet=quiet) self.x393_mcntrl_timing.axi_set_cmda_odelay(self.combine_delay(cmda_odly_lin),quiet=quiet)
self.x393_axi_tasks.enable_refresh(1) self.x393_axi_tasks.enable_refresh(1)
return cmda_odly_lin return cmda_odly_lin
def set_phase_delays(self,
phase,
inp_period='A',
out_period='A',
refresh=True,
quiet=1):
"""
Set clock phase and all I/O delays optimal for this phase
@param phase value to set
@param inp_period - period branch for DQ inputs: E<arly>, N<ominal>, L<ate> or A<ny>
@param out_period - period branch for DQ outputs: E<arly>, N<ominal>, L<ate> or A<ny>
@param refresh - turn refresh OFF before and ON after changing the delays and phase
@param quiet - reduce output
@return True on success, False on invalid phase
"""
rslt_names=("early","nominal","late")
enl_in=None
enl_out=None
enl_in_used=None
enl_out_used=None
try:
inp=str(inp_period)[0].upper()
except:
print ("Invalid parameter <inp_period>=%s"%(str(inp_period)))
return False
try:
outp=str(out_period)[0].upper()
except:
print ("Invalid parameter <out_period>=%s"%(str(out_period)))
return False
if inp == 'A':
enl_in=rslt_names
else:
for k in rslt_names:
if inp == k[0].upper():
enl_in=(k,)
break
else:
print ("Unrecognized parameter <inp_period>=%s"%(str(inp_period)))
return False
if outp == 'A':
enl_out=rslt_names
else:
for k in rslt_names:
if outp == k[0].upper():
enl_out=(k,)
break
else:
print ("Unrecognized parameter <out_period>=%s"%(str(out_period)))
return False
dly_steps=self.x393_mcntrl_timing.get_dly_steps()
numPhaseSteps= int(dly_steps['SDCLK_PERIOD']/dly_steps['PHASE_STEP']+0.5)
phase= phase % numPhaseSteps # valid for negative also, numPhaseSteps should be <=128 (now it is 112)
try:
delays_phase=self.adjustment_state['delays_phase']
except:
print("Delays for phases (self.adjustment_state['delays_phase']) are not set, running 'get_delays_vs_phase' command ")
try:
delays_phase=self.get_delays_vs_phase(filter_dqo=2,
filter_dqi=2,
filter_dqso=2,
filter_dqsi=2,
filter_cmda=2,
keep_all=False,
set_table=True,
quiet=quiet+2)
self.adjustment_state['delays_phase']=delays_phase
except:
print ("Failed to execute get_'delays_vs_phase' command")
return False
try:
delays=delays_phase[phase]
except:
print("No valid delay data for phase %d is available"%(phase))
return False
try:
cmda_odly=delays['cmda']
except:
print("No valid CMDA output delay data for phase %d is available, it is required"%(phase))
return False
try:
dqs_idelays=delays['dqsi']
except:
dqs_idelays=None
if quiet < 2:
print ("No valid DQS input delay data for phase %d is available, it will not be set"%(phase))
try:
dqs_odelays=delays['dqso']
except:
dqs_odelays=None
if quiet < 2:
print ("No valid DQS output delay data for phase %d is available, it will not be set"%(phase))
for k in enl_in:
try:
dq_idelays=delays['dqi'][k]
enl_in_used=k
break
except:
pass
else:
dq_idelays=None
if quiet < 2:
print ("No valid DQ input delay data for phase %d (period(s)=%s) is available, it will not be set"%(phase,str(enl_in)))
for k in enl_out:
try:
dq_odelays=delays['dqo'][k]
enl_out_used=k
break
except:
pass
else:
dq_odelays=None
if quiet < 2:
print ("No valid DQ output delay data for phase %d (period(s)=%s) is available, it will not be set"%(phase,str(enl_out)))
if quiet < 2:
print ("Going to set:")
print ("phase=",phase)
print ('cmda_odly=',cmda_odly)
print ('dqs_idelays=',dqs_idelays)
print ('dqs_odelays=',dqs_odelays)
print ('dq_idelays=',dq_idelays,' (',enl_in_used,')')
print ('dq_odelays=',dq_odelays,' (',enl_out_used,')')
print ('Memory refresh will %sbe controlled'%(('NOT ','')[refresh]))
if refresh:
self.x393_axi_tasks.enable_refresh(0)
self.x393_mcntrl_timing.axi_set_phase(phase,quiet=quiet)
self.x393_mcntrl_timing.axi_set_cmda_odelay(self.combine_delay(cmda_odly),quiet=quiet)
if refresh:
self.x393_axi_tasks.enable_refresh(1)
if not dqs_idelays is None:
self.x393_mcntrl_timing.axi_set_dqs_idelay(self.combine_delay(dqs_idelays),quiet=quiet)
if not dq_idelays is None:
self.x393_mcntrl_timing.axi_set_dq_idelay(self.combine_delay(dq_idelays),quiet=quiet)
if not dqs_odelays is None:
self.x393_mcntrl_timing.axi_set_dqs_odelay(self.combine_delay(dqs_odelays),quiet=quiet)
if not dq_odelays is None:
self.x393_mcntrl_timing.axi_set_dq_odelay(self.combine_delay(dq_odelays),quiet=quiet)
if refresh:
self.x393_axi_tasks.enable_refresh(1)
return True
"""
{
'dqsi':[110, 100]
'dqo':{'nominal': [95, 94, 99, 93, 99, 95, 94, 94, 93, 94, 100, 94, 93, 93, 90, 92]}
'dqi':{'early': [1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]}
'cmda':48
'dqso':[57, 52]
},
"""
pass
def scan_dqs(self, def scan_dqs(self,
low_delay, low_delay,
high_delay, high_delay,
...@@ -1041,8 +1204,15 @@ class X393McntrlAdjust(object): ...@@ -1041,8 +1204,15 @@ class X393McntrlAdjust(object):
quiet=1 quiet=1
): ):
""" """
<max_phase_err> maximal phase error for command and address line Find CMDA output delay for each phase value using linear interpolation for available results
as a fraction of SDCLK period to consider Use write levelling mode (refresh off) and A7 (that makes it write levelling or not).
Only A7 is subject to marginal timing, other signals are kept safe. But accidentally it still can hit
wrong timing - in that case memory is reset and re-initialized
Sets global parameters, including self.adjustment_state['cmda_bspe']
@param start_phase initial phase to start measuremts (non-0 only for debugging dependencies)
@param reinits higher the number - more re-inits are used (0 - only where absolutely necessary)
@param max_phase_err maximal phase error for command and address line as a fraction of SDCLK period to consider
@param quiet reduce output
""" """
start_phase &= 0xff start_phase &= 0xff
if start_phase >=128: if start_phase >=128:
...@@ -1131,6 +1301,9 @@ class X393McntrlAdjust(object): ...@@ -1131,6 +1301,9 @@ class X393McntrlAdjust(object):
if quiet <3: if quiet <3:
print ("%d:"%(phase),end=" ") print ("%d:"%(phase),end=" ")
sys.stdout.flush() sys.stdout.flush()
elif quiet < 5:
print (".",end="")
sys.stdout.flush()
phase_mod=phase % numPhaseSteps phase_mod=phase % numPhaseSteps
dlys= phase_step(phase,cmda_dly) dlys= phase_step(phase,cmda_dly)
cmda_marg_dly[phase_mod]=dlys # [1] # Marginal delay or -1 cmda_marg_dly[phase_mod]=dlys # [1] # Marginal delay or -1
...@@ -1140,6 +1313,9 @@ class X393McntrlAdjust(object): ...@@ -1140,6 +1313,9 @@ class X393McntrlAdjust(object):
if quiet <3: if quiet <3:
print ("X",end=" ") print ("X",end=" ")
sys.stdout.flush() sys.stdout.flush()
elif quiet < 5:
print (".",end="")
sys.stdout.flush()
if reinits > 1: #re-init each time failed to find delay if reinits > 1: #re-init each time failed to find delay
if quiet <3: if quiet <3:
print ("\nFailed to find marginal odelay for A7 - re-initializing DDR3 with odelay=0x%x",cmda_dly) print ("\nFailed to find marginal odelay for A7 - re-initializing DDR3 with odelay=0x%x",cmda_dly)
...@@ -1149,6 +1325,9 @@ class X393McntrlAdjust(object): ...@@ -1149,6 +1325,9 @@ class X393McntrlAdjust(object):
if quiet <3: if quiet <3:
print ("%d"%dlys[1],end=" ") print ("%d"%dlys[1],end=" ")
sys.stdout.flush() sys.stdout.flush()
elif quiet < 5:
print (".",end="")
sys.stdout.flush()
lin_dly=self.split_delay(cmda_dly) lin_dly=self.split_delay(cmda_dly)
if (dlys[1]-lin_dly) < safe_early: if (dlys[1]-lin_dly) < safe_early:
if (lin_dly > 0): if (lin_dly > 0):
...@@ -1168,6 +1347,8 @@ class X393McntrlAdjust(object): ...@@ -1168,6 +1347,8 @@ class X393McntrlAdjust(object):
if quiet <2: if quiet <2:
for i,d in enumerate(cmda_marg_dly): for i,d in enumerate(cmda_marg_dly):
print ("%d %d %d"%(i, d[0], d[1])) print ("%d %d %d"%(i, d[0], d[1]))
elif quiet < 5:
print ()
#find the largest positive step of cmda_marg_dly while cyclically increasing phase #find the largest positive step of cmda_marg_dly while cyclically increasing phase
numValid=0 numValid=0
for i,d in enumerate(cmda_marg_dly): for i,d in enumerate(cmda_marg_dly):
...@@ -1469,12 +1650,18 @@ class X393McntrlAdjust(object): ...@@ -1469,12 +1650,18 @@ class X393McntrlAdjust(object):
if quiet <3: if quiet <3:
print ("%d(%d):"%(phase,phase_mod),end=" ") print ("%d(%d):"%(phase,phase_mod),end=" ")
sys.stdout.flush() sys.stdout.flush()
elif quiet < 5:
print (".",end="")
sys.stdout.flush()
dlys=wlev_phase_step(phase) dlys=wlev_phase_step(phase)
wlev_dqs_delays[phase_mod]=dlys wlev_dqs_delays[phase_mod]=dlys
if quiet <3: if quiet <3:
print ("%s"%str(dlys),end=" ") print ("%s"%str(dlys),end=" ")
sys.stdout.flush() sys.stdout.flush()
if quiet <2: elif quiet < 5:
print (".",end="")
sys.stdout.flush()
if quiet< 2:
print() print()
if quiet <2: if quiet <2:
...@@ -1483,6 +1670,8 @@ class X393McntrlAdjust(object): ...@@ -1483,6 +1670,8 @@ class X393McntrlAdjust(object):
print ("%d %d %d"%(i, d[0], d[1])) print ("%d %d %d"%(i, d[0], d[1]))
else: else:
print ("%d"%(i)) print ("%d"%(i))
elif quiet < 5:
print ()
#find the largest positive step of cmda_marg_dly while cyclically increasing phase #find the largest positive step of cmda_marg_dly while cyclically increasing phase
numValid=0 numValid=0
...@@ -1700,6 +1889,8 @@ class X393McntrlAdjust(object): ...@@ -1700,6 +1889,8 @@ class X393McntrlAdjust(object):
then use them to find finedelay for each of the DQS and DQ, then use them to find finedelay for each of the DQS and DQ,
linear coefficients (a,b) for each DQ vs DQS and asymmetry linear coefficients (a,b) for each DQ vs DQS and asymmetry
(late 0->1, early 1->0) for each of the DQ and DQS (late 0->1, early 1->0) for each of the DQ and DQS
@param quiet reduce output
""" """
nrep=8 nrep=8
max_lin_dly=NUM_DLY_STEPS-1#159 max_lin_dly=NUM_DLY_STEPS-1#159
...@@ -1956,8 +2147,11 @@ class X393McntrlAdjust(object): ...@@ -1956,8 +2147,11 @@ class X393McntrlAdjust(object):
if quiet <3: if quiet <3:
print ("%d(0x%x):"%(ldly,self.combine_delay(ldly)),end=" ") print ("%d(0x%x):"%(ldly,self.combine_delay(ldly)),end=" ")
sys.stdout.flush() sys.stdout.flush()
elif quiet < 5:
print (".",end="")
sys.stdout.flush()
meas_data[ldly] = patt_dqs_step(ldly) meas_data[ldly] = patt_dqs_step(ldly)
if quiet <3: if quiet < 5:
print () print ()
if quiet < 3: if quiet < 3:
...@@ -2066,12 +2260,9 @@ class X393McntrlAdjust(object): ...@@ -2066,12 +2260,9 @@ class X393McntrlAdjust(object):
to system-synchronous one to system-synchronous one
cmda_odelay should be already calibrated, refresh will be turned on. cmda_odelay should be already calibrated, refresh will be turned on.
Uses random/previously written pattern in one memory block (should have some varying data Uses random/previously written pattern in one memory block (should have some varying data
@param quiet reduce output
""" """
"""
TODO: write block of data: 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, ...(dqs_odelay set by wlev)
All bits will alternate, even if the DQ_ODELAY vs DQS_ODELAY will be wrong
"""
try: try:
dqi_dqsi=self.adjustment_state['dqi_dqsi'] dqi_dqsi=self.adjustment_state['dqi_dqsi']
except: except:
...@@ -2133,8 +2324,34 @@ class X393McntrlAdjust(object): ...@@ -2133,8 +2324,34 @@ class X393McntrlAdjust(object):
if quiet<2: if quiet<2:
print ("timing)=%s, dly_step=%d step180=%d"%(str(timing),dly_step,step180)) print ("timing)=%s, dly_step=%d step180=%d"%(str(timing),dly_step,step180))
self.x393_pio_sequences.set_read_block(*(brc+(nrep+3,sel))) # set sequence once self.x393_pio_sequences.set_read_block(*(brc+(nrep+3,sel))) # set sequence once
# def read_blk(): #return array of 16-bit words to compare for bit diffs #prepare writing block:
# pass wdata16=(0,0,0xffff,0xffff)*(2*(nrep+3)) # Data will have o/1 transitions in every bit, even if DQ_OPDELAY to DQS_OPDELAY is not yet adjusted
wdata32=self.convert_mem16_to_w32(wdata16)
self.x393_mcntrl_buffers.write_block_buf_chn(0,0,wdata32,quiet) # fill block memory (channel, page, number)
self.x393_pio_sequences.set_write_block(*(brc+(nrep+3,0,sel))) # set sequence once
cmda_bspe=self.adjustment_state['cmda_bspe']
wlev_dqs_bspe=self.adjustment_state['wlev_dqs_bspe']
for phase in range(numPhaseSteps):
try:
dqs_odelay=[wlev_dqs_bspe[lane][phase]['ldly'] for lane in range(len(wlev_dqs_bspe))]
cmda_odelay=cmda_bspe[phase]['ldly']
if (not None in dqs_odelay) and (not cmda_odelay is None):
break
except:
pass
else:
raise Exception("BUG: could not find phase that has valid cmda_odelay and dqs_odelay")
phase_ok=self.set_phase_with_refresh( # check result for not None
phase,
quiet)
if not phase_ok:
raise Exception("BUG: Failed set_phase_with_refresh(%s)"%(str(phase)))
self.x393_mcntrl_timing.axi_set_dqs_odelay(self.combine_delay(dqs_odelay),quiet=quiet)
self.x393_pio_sequences.write_block() #page= 0, wait_complete=1)
def dqsi_phase_step (phase): def dqsi_phase_step (phase):
dqsi_cache=[None]*NUM_DLY_STEPS # cache for holding already measured delays. None - not measured, 0 - no data, [[]..[]] dqsi_cache=[None]*NUM_DLY_STEPS # cache for holding already measured delays. None - not measured, 0 - no data, [[]..[]]
...@@ -2304,15 +2521,18 @@ class X393McntrlAdjust(object): ...@@ -2304,15 +2521,18 @@ class X393McntrlAdjust(object):
# body of the measure_dqs_idly_phase() # body of the measure_dqs_idly_phase()
dqsi_vs_phase=[] dqsi_vs_phase=[]
for phase in range (numPhaseSteps): for phase in range (numPhaseSteps):
if quiet <3: if quiet <2:
print ("====== PHASE=%d ======"%(phase)) print ("====== PHASE=%d ======"%(phase))
elif quiet <4: elif quiet < 3:
print ("%d:"%(phase),end=" ") print ("%d:"%(phase),end=" ")
sys.stdout.flush() sys.stdout.flush()
elif quiet < 5:
print (".",end="")
sys.stdout.flush()
dqsi_vs_phase.append(dqsi_phase_step (phase)) dqsi_vs_phase.append(dqsi_phase_step (phase))
if quiet < 4 : if quiet < 3 :
print ("dqsi_vs_phase=%s"%(str(dqsi_vs_phase))) print ("dqsi_vs_phase=%s"%(str(dqsi_vs_phase)))
print("Phase DQSI0 DQSI1 diff0 diff1 branch0 branch1") print("Phase DQSI0 DQSI1 diff0 diff1 branch0 branch1")
for phase,v in enumerate(dqsi_vs_phase): for phase,v in enumerate(dqsi_vs_phase):
...@@ -2321,6 +2541,8 @@ class X393McntrlAdjust(object): ...@@ -2321,6 +2541,8 @@ class X393McntrlAdjust(object):
print ("%s %s %s %s %s %s"%(str(v[0][0]),str(v[1][0]),str(v[0][1]),str(v[1][1]), v[0][2], v[1][2])) print ("%s %s %s %s %s %s"%(str(v[0][0]),str(v[1][0]),str(v[0][1]),str(v[1][1]), v[0][2], v[1][2]))
else: else:
print() print()
elif quiet < 5:
print ()
self.adjustment_state['dqsi_vs_phase']= dqsi_vs_phase self.adjustment_state['dqsi_vs_phase']= dqsi_vs_phase
self.adjustment_state['dqsi_vs_phase_steps']=compare_prim_steps self.adjustment_state['dqsi_vs_phase_steps']=compare_prim_steps
return dqsi_vs_phase return dqsi_vs_phase
...@@ -2340,8 +2562,9 @@ class X393McntrlAdjust(object): ...@@ -2340,8 +2562,9 @@ class X393McntrlAdjust(object):
Measure 4 different transitions for each data bit (rising DQS/rising DQ, falling DQS/falling DQ, Measure 4 different transitions for each data bit (rising DQS/rising DQ, falling DQS/falling DQ,
rising DQS/falling DQ and falling DQS/rising DQ (that allows to measure duty cycles fro both rising DQS/falling DQ and falling DQS/rising DQ (that allows to measure duty cycles fro both
DQS and DQ lines DQS and DQ lines
@param quiet reduce output
""" """
self.load_hardcoded_data() # TODO: REMOVE LATER # self.load_hardcoded_data() # TODO: REMOVE LATER
try: try:
dqi_dqsi=self.adjustment_state['dqi_dqsi'] dqi_dqsi=self.adjustment_state['dqi_dqsi']
except: except:
...@@ -2361,32 +2584,6 @@ class X393McntrlAdjust(object): ...@@ -2361,32 +2584,6 @@ class X393McntrlAdjust(object):
numPhaseSteps= int(timing['SDCLK_PERIOD']/timing['PHASE_STEP']+0.5) numPhaseSteps= int(timing['SDCLK_PERIOD']/timing['PHASE_STEP']+0.5)
step180= int(NUM_FINE_STEPS*0.5* timing['SDCLK_PERIOD'] / timing['DLY_STEP'] +0.5) step180= int(NUM_FINE_STEPS*0.5* timing['SDCLK_PERIOD'] / timing['DLY_STEP'] +0.5)
"""
dqsi_valid={} #[None]*NUM_DLY_STEPS
for k,v in dqi_dqsi.items():
if v:
dqsi_valid[k]=[False]*NUM_DLY_STEPS
for dly in range(NUM_DLY_STEPS):
if v[dly]:
for d in v[dly]:
if d is None:
break
else: # All values are not None
dqsi_valid[k][dly]=True
if not dqsi_valid:
print ("No Valid DQ IDELAY vs. DQS IDELAY data is available, exiting")
return
if quiet <1:
print ('dqi_dqsi=%s'%(str(dqi_dqsi)))
print("\n\n")
if quiet <2:
print ('dqsi_valid=%s'%(str(dqsi_valid)))
"""
#Calculate phase for the best match for the DQS output delay (for both lanes - use average). If #Calculate phase for the best match for the DQS output delay (for both lanes - use average). If
# solution for different lanes point to the opposite ends of the phase range - keep previous # solution for different lanes point to the opposite ends of the phase range - keep previous
...@@ -2781,7 +2978,7 @@ class X393McntrlAdjust(object): ...@@ -2781,7 +2978,7 @@ class X393McntrlAdjust(object):
if self.DRY_MODE: if self.DRY_MODE:
return return
self.x393_mcntrl_buffers.write_block_buf_chn(0,0,wdata32); # fill block memory (channel, page, number) self.x393_mcntrl_buffers.write_block_buf_chn(0,0,wdata32,quiet); # fill block memory (channel, page, number)
self.x393_pio_sequences.set_write_block(*(brc+(nrep+3,extraTgl,sel))) # set sequence once self.x393_pio_sequences.set_write_block(*(brc+(nrep+3,extraTgl,sel))) # set sequence once
self.x393_pio_sequences.set_read_block(*(brc+(nrep+3,sel))) # set sequence once self.x393_pio_sequences.set_read_block(*(brc+(nrep+3,sel))) # set sequence once
#With the data to write being the same as pattern data, try using the same measurements as for the pattern #With the data to write being the same as pattern data, try using the same measurements as for the pattern
...@@ -2794,8 +2991,11 @@ class X393McntrlAdjust(object): ...@@ -2794,8 +2991,11 @@ class X393McntrlAdjust(object):
if quiet <3: if quiet <3:
print ("%d(0x%x):"%(ldly,self.combine_delay(ldly)),end=" ") print ("%d(0x%x):"%(ldly,self.combine_delay(ldly)),end=" ")
sys.stdout.flush() sys.stdout.flush()
elif quiet < 5:
print (".",end="")
sys.stdout.flush()
meas_data[ldly] = dqs_step(ldly) meas_data[ldly] = dqs_step(ldly)
if quiet <3: if quiet < 5:
print () print ()
if quiet < 3: if quiet < 3:
...@@ -2899,6 +3099,131 @@ class X393McntrlAdjust(object): ...@@ -2899,6 +3099,131 @@ class X393McntrlAdjust(object):
adjust_write_levelling 0 1 0 .1 3 adjust_write_levelling 0 1 0 .1 3
adjust_pattern 0.125 0.1 1 adjust_pattern 0.125 0.1 1
''' '''
def measure_all(self,
tasks="CWRPOZ",
prim_steps=1,
primary_set_in=2,
primary_set_out=2,
quiet=3):
"""
@param tasks - "C" cmda, "W' - write levelling, "R" - read levelling (DQI-DQSI), "P" - dqs input phase (DQSI-PHASE),
"O" - output timing (DQ odelay vs DQS odelay) "Z" - print results
@param prim_steps - compare measurement with current delay with one lower by 1 primary step (5 fine delay steps), 0 -
compare with one fine step lower
@param quiet reduce output
"""
max_phase_err=0.1
frac_step=0.125
# read_sel=1 # set DDR3 command in the second cycle of two (0 - during the first omne)
read_bin_size=5 # dealy counts
write_bin_size=5 # dealy counts
read_scale_w=0.0 # weight of the "binary" results relative to "analog"
write_scale_w=0.0 # weight of the "binary" results relative to "analog"
idly_phase_sel=1
bin_size_ps=50.0
read_phase_scale_w=0.0
prim_steps_in=prim_steps
prim_steps_out=prim_steps
# primary_set_in=2
# primary_set_out=2
write_sel=1 # set DDR3 command in the second cycle of two (0 - during the first omne)
task_data=[{'key':'C',
'func':self.adjust_cmda_odelay,
'comment':'Measuring CMDA output delay for each clock phase',
'params':{'start_phase':0,
'reinits':1,
'max_phase_err':max_phase_err,
'quiet':quiet+1}},
{'key':'W',
'func':self.adjust_write_levelling,
'comment':'Write levelling - measuring optimal DQS output delay for each phase',
'params':{'start_phase':0,
'reinits':1,
'invert':0,
'max_phase_err':max_phase_err,
'quiet':quiet+1}},
{'key':'R',
'func':self.measure_pattern,
'comment':'Read levelling - measuring predefined pattern to determine DQ input delays relative to DQS ones',
'params':{'compare_prim_steps':prim_steps_in,
'limit_step':frac_step,
'max_phase_err':max_phase_err,
'quiet':quiet+1}},
{'key':'R',
'func':self.proc_dqi_dqsi,
'comment':'Processing read levelling results using Levenberg-Marquardt algorithm to determine delay model parameters and optimal delay values',
'params':{'lane':'All',
'bin_size':read_bin_size,
'primary_set':primary_set_in,
'data_set_number':-1, # use measured data
'scale_w':read_scale_w,
'quiet':quiet+1}},
{'key':'P',
'func':self.measure_dqs_idly_phase,
'comment':'Measure optimal DQS input delays for clock phases (clock boundary crossing from DQS in to internal)',
'params':{'compare_prim_steps':prim_steps_in,
'frac_step':frac_step,
'sel':idly_phase_sel,
'quiet':quiet+1}},
{'key':'P',
'func':self.proc_dqsi_phase, # compare_prim_steps???
'comment':'Calculate optimal DQS input delays vs. clock phase',
'params':{'lane':'All',
'bin_size_ps':bin_size_ps,
'data_set_number':-1, # use measured data
'scale_w':read_phase_scale_w,
'quiet':quiet+1}},
{'key':'O',
'func':self.measure_dqo_dqso,
'comment':'Measure write mode output delays on DQ lines relative to DQS output delays',
'params':{'compare_prim_steps':prim_steps_out,
'frac_step':frac_step,
'sel': write_sel,
'quiet':quiet+1}},
{'key':'O',
'func':self.proc_dqo_dqso,
'comment':'Processing DQ output delays to DQS output data results using Levenberg-Marquardt algorithm to determine optimal delays',
'params':{'lane':'All',
'bin_size':write_bin_size,
'primary_set':primary_set_out,
'data_set_number':-1, # use measured data
'scale_w':write_scale_w,
'quiet':quiet+1}},
{'key':'Z',
'func':self.show_all_vs_phase,
'comment':'Printing results table (delays and errors vs. phase)- all, including invalid phases',
'params':{'keep_all':True,
'load_hardcoded':False}},
{'key':'Z',
'func':self.show_all_vs_phase,
'comment':'Printing results table (delays and errors vs. phase)- only for valid clock phase values',
'params':{'keep_all':False,
'load_hardcoded':False}},
]
start_time=time.time()
last_task_start_time=start_time
for task_item in task_data: # execute tasks in predefined sequence, if their keys are enabled through arguments (several tasks may be needed for 1 key)
if task_item['key'] in tasks.upper():
tim=time.time()
if quiet < 5:
print ("[%.3f/+%.3f] %s"%(tim-start_time,tim-last_task_start_time,task_item['comment']))
print (" %s("%(task_item['func'].__name__),end="")
# print ("task_item=",task_item)
# print ("task_item['params']=",task_item['params'])
for k,v in task_item['params'].items():
print ("%s=%s, "%(k,str(v)),end="")
print(")")
# TODO: print function name and used arguments
task_item['func'](**task_item['params'])
last_task_start_time=tim
tim=time.time()
if quiet < 5:
print ("[%.3f/+%.3f] %s"%(tim-start_time,tim-last_task_start_time,"All Done"))
def load_hardcoded_data(self): def load_hardcoded_data(self):
""" """
Debug feature - load hard-coded previously acquired/processed data Debug feature - load hard-coded previously acquired/processed data
...@@ -2933,6 +3258,7 @@ class X393McntrlAdjust(object): ...@@ -2933,6 +3258,7 @@ class X393McntrlAdjust(object):
set #2 (default) used measurement with previous primary step measurement (will not suffer from set #2 (default) used measurement with previous primary step measurement (will not suffer from
fine range wider than on primary step) fine range wider than on primary step)
If not number or <0 - use measured data If not number or <0 - use measured data
@param quiet reduce output
@param scale_w weight for "uncertain" values (where samples change from all 0 to all 1 in one step) @param scale_w weight for "uncertain" values (where samples change from all 0 to all 1 in one step)
For sufficient data 0.0 is OK (and seems to work better)- only "analog" samples are considered For sufficient data 0.0 is OK (and seems to work better)- only "analog" samples are considered
@return 3-element dictionary of ('early','nominal','late'), each being None or a 160-element list, @return 3-element dictionary of ('early','nominal','late'), each being None or a 160-element list,
...@@ -2979,18 +3305,13 @@ class X393McntrlAdjust(object): ...@@ -2979,18 +3305,13 @@ class X393McntrlAdjust(object):
compare_prim_steps, compare_prim_steps,
scale_w, scale_w,
quiet) quiet)
if quiet<5: if quiet < 4:
lma.showENLresults(rslt) lma.showENLresults(rslt)
if quiet<5:
print ("dqi_dqsi={")
for k,v in rslt.items():
print ("'%s':%s,"%(k,str(v)))
print ("}")
self.adjustment_state["dqi_dqsi_parameters"]=rslt.pop('parameters') self.adjustment_state["dqi_dqsi_parameters"]=rslt.pop('parameters')
try: try:
self.adjustment_state["maxErrDqsi"]=rslt.pop('maxErrDqs') self.adjustment_state["maxErrDqsi"]=rslt.pop('maxErrDqs')
if quiet<5: if quiet < 4:
print("maxErrDqsi={") print("maxErrDqsi={")
for k,v in self.adjustment_state["maxErrDqsi"].items(): for k,v in self.adjustment_state["maxErrDqsi"].items():
print ("'%s':%s,"%(k,str(v))) print ("'%s':%s,"%(k,str(v)))
...@@ -2998,6 +3319,12 @@ class X393McntrlAdjust(object): ...@@ -2998,6 +3319,12 @@ class X393McntrlAdjust(object):
except: except:
print ("maxErrDqs does not exist") print ("maxErrDqs does not exist")
if quiet < 4:
print ("dqi_dqsi={")
for k,v in rslt.items():
print ("'%s':%s,"%(k,str(v)))
print ("}")
self.adjustment_state["dqi_dqsi"]=rslt self.adjustment_state["dqi_dqsi"]=rslt
return rslt return rslt
...@@ -3006,7 +3333,6 @@ class X393McntrlAdjust(object): ...@@ -3006,7 +3333,6 @@ class X393McntrlAdjust(object):
bin_size_ps=50, bin_size_ps=50,
data_set_number=0, # not number - use measured data data_set_number=0, # not number - use measured data
scale_w=0.1, # weight for "uncertain" values (where samples chane from all 0 to all 1 in one step) scale_w=0.1, # weight for "uncertain" values (where samples chane from all 0 to all 1 in one step)
quiet=1): quiet=1):
""" """
Run DQSI vs PHASE fitting for one data lane (0 or 1) using earlier acquired hard-coded data Run DQSI vs PHASE fitting for one data lane (0 or 1) using earlier acquired hard-coded data
...@@ -3018,6 +3344,7 @@ class X393McntrlAdjust(object): ...@@ -3018,6 +3344,7 @@ class X393McntrlAdjust(object):
If not number or <0 - use measured data If not number or <0 - use measured data
@param scale_w weight for "uncertain" values (where samples change from all 0 to all 1 in one step) @param scale_w weight for "uncertain" values (where samples change from all 0 to all 1 in one step)
For sufficient data 0.0 is OK (and seems to work better)- only "analog" samples are considered For sufficient data 0.0 is OK (and seems to work better)- only "analog" samples are considered
@param quiet reduce output
@return 3-element dictionary of ('early','nominal','late'), each being None or a 160-element list, @return 3-element dictionary of ('early','nominal','late'), each being None or a 160-element list,
each element being either None, or a list of 3 best DQ delay values for the DQS delay (some mey be None too) each element being either None, or a list of 3 best DQ delay values for the DQS delay (some mey be None too)
""" """
...@@ -3043,19 +3370,18 @@ class X393McntrlAdjust(object): ...@@ -3043,19 +3370,18 @@ class X393McntrlAdjust(object):
timing=self.x393_mcntrl_timing.get_dly_steps() timing=self.x393_mcntrl_timing.get_dly_steps()
numPhaseSteps= int(timing['SDCLK_PERIOD']/timing['PHASE_STEP']+0.5) numPhaseSteps= int(timing['SDCLK_PERIOD']/timing['PHASE_STEP']+0.5)
lma=x393_lma.X393LMA() # use persistent one? lma=x393_lma.X393LMA() # use persistent one?
# print("++++++proc_dqsi_phase(), quiet=",quiet)
dqsi_phase=lma.lma_fit_dqsi_phase(lane, # byte lane dqsi_phase=lma.lma_fit_dqsi_phase(lane, # byte lane
bin_size_ps, bin_size_ps,
1000.0*self.x393_mcntrl_timing.get_dly_steps()['SDCLK_PERIOD'], # 2500.0, # clk_period, 1000.0*self.x393_mcntrl_timing.get_dly_steps()['SDCLK_PERIOD'], # 2500.0, # clk_period,
# 1000.0*self.x393_mcntrl_timing.get_dly_steps()['PHASE_STEP'],# phase_step,
# dly_step_ds,
# primary_set,
dqsi_dqi_parameters, dqsi_dqi_parameters,
dqsi_phase_data, # data_set, dqsi_phase_data, # data_set,
compare_prim_steps, compare_prim_steps,
scale_w, scale_w,
numPhaseSteps, numPhaseSteps,
quiet=1) quiet)
self.adjustment_state.update(dqsi_phase) self.adjustment_state.update(dqsi_phase)
return dqsi_phase return dqsi_phase
...@@ -3080,6 +3406,7 @@ class X393McntrlAdjust(object): ...@@ -3080,6 +3406,7 @@ class X393McntrlAdjust(object):
If not number or <0 - use measured data If not number or <0 - use measured data
@param scale_w weight for "uncertain" values (where samples change from all 0 to all 1 in one step) @param scale_w weight for "uncertain" values (where samples change from all 0 to all 1 in one step)
For sufficient data 0.0 is OK (and seems to work better)- only "analog" samples are considered For sufficient data 0.0 is OK (and seems to work better)- only "analog" samples are considered
@param quiet reduce output
@return 3-element dictionary of ('early','nominal','late'), each being None or a 160-element list, @return 3-element dictionary of ('early','nominal','late'), each being None or a 160-element list,
each element being either None, or a list of 3 best DQ delay values for the DQS delay (some mey be None too) each element being either None, or a list of 3 best DQ delay values for the DQS delay (some mey be None too)
""" """
...@@ -3094,7 +3421,7 @@ class X393McntrlAdjust(object): ...@@ -3094,7 +3421,7 @@ class X393McntrlAdjust(object):
if quiet < 4: if quiet < 4:
print("Using measured data set") print("Using measured data set")
try: try:
compare_prim_steps=self.adjustment_state["wtite_prim_steps"] compare_prim_steps=self.adjustment_state["write_prim_steps"]
meas_data= self.adjustment_state["write_meas_data"] meas_data= self.adjustment_state["write_meas_data"]
except: except:
print ("Pattern-measured data is not available, exiting") print ("Pattern-measured data is not available, exiting")
...@@ -3124,18 +3451,13 @@ class X393McntrlAdjust(object): ...@@ -3124,18 +3451,13 @@ class X393McntrlAdjust(object):
compare_prim_steps, compare_prim_steps,
scale_w, scale_w,
quiet) quiet)
if quiet<5: if quiet < 4:
lma.showENLresults(rslt) lma.showENLresults(rslt)
if quiet<5:
print ("dqi_dqsi={")
for k,v in rslt.items():
print ("'%s':%s,"%(k,str(v)))
print ("}")
self.adjustment_state["dqi_dqsi_parameters"]=rslt.pop('parameters') self.adjustment_state["dqi_dqsi_parameters"]=rslt.pop('parameters')
try: try:
self.adjustment_state["maxErrDqso"]=rslt.pop('maxErrDqs') self.adjustment_state["maxErrDqso"]=rslt.pop('maxErrDqs')
if quiet<5: if quiet < 4:
print("maxErrDqso={") print("maxErrDqso={")
for k,v in self.adjustment_state["maxErrDqso"].items(): for k,v in self.adjustment_state["maxErrDqso"].items():
print ("'%s':%s,"%(k,str(v))) print ("'%s':%s,"%(k,str(v)))
...@@ -3143,114 +3465,353 @@ class X393McntrlAdjust(object): ...@@ -3143,114 +3465,353 @@ class X393McntrlAdjust(object):
except: except:
print ("maxErrDqs does not exist") print ("maxErrDqs does not exist")
if quiet < 4:
print ("dqi_dqsi={")
for k,v in rslt.items():
print ("'%s':%s,"%(k,str(v)))
print ("}")
self.adjustment_state["dqo_dqso"]=rslt self.adjustment_state["dqo_dqso"]=rslt
return rslt return rslt
def get_delays_vs_phase(self,
def show_all_vs_phase(self, load_hardcoded=False): filter_dqo=2,
if load_hardcoded: filter_dqi=2,
self.load_hardcoded_data() filter_dqso=2,
filter_dqsi=2,
filter_cmda=2,
keep_all=False,
set_table=True,
quiet=2):
"""
Create list of valid "phases", after applying several filters. Each filter parameter can be
one of 3 values: 0 - do not apply filter, 1 - OK if each of multiple bits fit for at least one
early/nominal/late branch and 2 - all of the bits should fit the same branch
@param filter_dqo for DQ output delays
@param filter_dqi for DQ input delays
@param filter_dqso for DQS output delays
@param filter_dqsi for DQS input delays
@param filter_cmda for command and address output delays
@param keep_all Keep phases where some delays do not have valid values, just mark them as None
remove just items that do not have any non-None elements
@param set_table store results to the global table (used to simultaneously set all pahse-derived
delays in hardware
@param quiet reduce output
@return per-phase value list, each being none or a dictionary with optional fields "in" and "out"
having values early/nominal/late
"""
# self.load_hardcoded_data() # TODO: REMOVE LATER
rslt_names=("early","nominal","late") rslt_names=("early","nominal","late")
DQIvDQSI=self.adjustment_state["dqi_dqsi"] timing=self.x393_mcntrl_timing.get_dly_steps()
DQOvDQSO=self.adjustment_state["dqo_dqso"] numPhaseSteps= int(timing['SDCLK_PERIOD']/timing['PHASE_STEP']+0.5)
cmda_bspe=self.adjustment_state['cmda_bspe'] step180= int(NUM_FINE_STEPS*0.5* timing['SDCLK_PERIOD'] / timing['DLY_STEP'] +0.5)
dqsi_phase=self.adjustment_state['dqsi_phase'] halfDlyRange=min(NUM_DLY_STEPS//2, step180) # minimum of half adjustment range of the delay and half SDCLK period
wlev_dqs_bspe=self.adjustment_state['wlev_dqs_bspe'] if quiet <1:
numBits=0 print ("halfDlyRange=",halfDlyRange)
for n in DQIvDQSI: delays_phase=[]
if filter_dqo:
try:
DQOvDQSO=self.adjustment_state["dqo_dqso"]
except:
print ('Data for filter_dqo is not available (self.adjustment_state["dqo_dqso"]')
filter_dqo=0
try:
wlev_dqs_bspe=self.adjustment_state['wlev_dqs_bspe']
except:
print ('Data for filter_dqo requires data for filter_dqso and it is not available (self.adjustment_state["wlev_dqs_bspe"]')
filter_dqo=0
if filter_dqi:
try:
DQIvDQSI=self.adjustment_state["dqi_dqsi"]
except:
print ('Data for filter_dqi is not available (self.adjustment_state["dqi_dqsi"]')
filter_dqi=0
try:
dqsi_phase=self.adjustment_state['dqsi_phase']
except:
print ('Data for filter_dqi requires data for filter_dqsi and it is not available (self.adjustment_state["dqsi_phase"]')
filter_dqi=0
if filter_dqso:
try:
wlev_dqs_bspe=self.adjustment_state['wlev_dqs_bspe']
except:
print ('Data for filter_dqso is not available (self.adjustment_state["wlev_dqs_bspe"]')
filter_dqso=0
if filter_dqsi:
try:
dqsi_phase=self.adjustment_state['dqsi_phase']
except:
print ('Data for filter_dqsi is not available (self.adjustment_state["dqsi_phase"]')
filter_dqsi=0
if filter_cmda:
try: try:
for d in DQIvDQSI[n]: cmda_bspe=self.adjustment_state['cmda_bspe']
except:
print ('Data for filter_cmda is not available (self.adjustment_state["cmda_bspe"]')
filter_cmda=0
for phase in range(numPhaseSteps):
delays_phase.append({})
if filter_cmda:
if (cmda_bspe[phase]['ldly'] is None) and (not keep_all):
delays_phase[phase]=None
continue # next phase
else:
if not cmda_bspe[phase]['ldly'] is None:
delays_phase[phase]['cmda']=cmda_bspe[phase]['ldly']
#all(v is None for v in l)
if filter_dqsi:
dqsi=[dqsi_lane[phase] for dqsi_lane in dqsi_phase]
if None in dqsi:
if keep_all:
if not all(v is None for v in dqsi):
delays_phase[phase]['dqsi']=dqsi
else:
delays_phase[phase]=None
continue # next phase
elif (filter_dqsi == 2) and ((max(dqsi) - min(dqsi)) > halfDlyRange):
delays_phase[phase]=None
continue # next phase
else:
delays_phase[phase]['dqsi']=dqsi
if filter_dqso:
dqso=[None if wlev_lane[phase] is None else wlev_lane[phase]['ldly'] for wlev_lane in wlev_dqs_bspe]
if None in dqso:
if keep_all:
if not all(v is None for v in dqso):
delays_phase[phase]['dqso']=dqso
else:
delays_phase[phase]=None
continue # next phase
elif (filter_dqsi == 2) and ((max(dqso) - min(dqso)) > halfDlyRange):
delays_phase[phase]=None
continue # next phase
else:
delays_phase[phase]['dqso']=dqso
if filter_dqi:
dqsi=[dqsi_lane[phase] for dqsi_lane in dqsi_phase]
if (None in dqsi) and (not keep_all):
delays_phase[phase]=None # phase for at least one of the DQSI is invalid
continue # next phase
else:
dqi_options={}
for k in rslt_names:
if (k in DQIvDQSI) and (not DQIvDQSI[k] is None):
dqi= sum([[None]*8 if (dqs is None) or (DQIvDQSI[k][dqs] is None) else DQIvDQSI[k][dqs][8*lane:8*(lane+1)] for lane,dqs in enumerate(dqsi)], [])
if keep_all:
if not all(v is None for v in dqi):
dqi_options[k]=dqi
else:
if None in dqi:
continue # not this branch
elif (filter_dqi == 2) and ((max(dqi) - min(dqi)) > halfDlyRange):
continue # failed filter, continue to the next branch
dqi_options[k]=dqi
if dqi_options:
delays_phase[phase]['dqi']=dqi_options
elif not keep_all:
delays_phase[phase]=None
continue # next phase
"""
delays_phase[phase]['in']=k # found solution
delays_phase[phase]['dqi']=dqi
break
else:
delays_phase[phase]=None # phase for at least one of the DQSI is invalid
continue # next phase
"""
if filter_dqo:
dqso=[None if wlev_lane[phase] is None else wlev_lane[phase]['ldly'] for wlev_lane in wlev_dqs_bspe]
if (None in dqso) and (not keep_all):
delays_phase[phase]=None # phase for at least one of the DQSI is invalid
continue # next phase
else:
dqo_options={}
for k in rslt_names:
if (k in DQOvDQSO) and (not DQOvDQSO[k] is None):
dqo= sum([[None]*8 if (dqs is None) or (DQOvDQSO[k][dqs] is None) else DQOvDQSO[k][dqs][8*lane:8*(lane+1)] for lane,dqs in enumerate(dqso)], [])
if keep_all:
if not all(v is None for v in dqo):
dqo_options[k]=dqo
else:
if None in dqo:
continue # not this branch
elif (filter_dqi == 2) and ((max(dqo) - min(dqo)) > halfDlyRange):
continue # failed filter, continue to the next branch
dqo_options[k]=dqo
if dqo_options:
delays_phase[phase]['dqo']=dqo_options
elif not keep_all:
delays_phase[phase]=None
continue # next phase
"""
delays_phase[phase]['out']=k # found solution
delays_phase[phase]['dqo']=dqo
break
else:
delays_phase[phase]=None # phase for at least one of the DQSI is invalid
continue # next phase
"""
if quiet <1:
print("delays_phase=",delays_phase)
if quiet < 2:
print ("delays_phase=[")
prev_none=False
for phase_data in delays_phase:
if phase_data is None:
if not prev_none:
print("\n ",end="")
print ("None,",end=" ")
prev_none=True
else:
if prev_none:
print()
print(" {")
for k,v in phase_data.items():
if isinstance(v,str):
v="'"+v+"'"
print (" '%s':%s"%(k, str(v)))
print (" },")
prev_none=False
print("]")
if quiet < 3:
enl_list_in=[]
enl_list_out=[]
numBits=None
for k in rslt_names:
for phase_data in delays_phase:
try:
if k in phase_data["dqi"]:
enl_list_in.append(k)
break
except:
pass
for phase_data in delays_phase:
try:
if k in phase_data["dqo"]:
enl_list_out.append(k)
break
except:
pass
for phase_data in delays_phase:
try:
numBits=len(phase_data["dqi"].values()[0])
break
except:
pass
try: try:
numBits=len(d) numBits=len(phase_data["dqo"].values()[0])
break break
except: except:
pass pass
break numLanes=numBits//8
try:
maxErrDqsi=self.adjustment_state["maxErrDqsi"]
except: except:
pass maxErrDqsi=None
if not numBits: try:
raise Exception("showENLresults(): No no-None data provided") maxErrDqso=self.adjustment_state["maxErrDqso"]
numLanes=numBits//8 except:
enl_list_in=[] maxErrDqso=None
for k in rslt_names:
if DQIvDQSI[k]: #print header
enl_list_in.append(k) print("Phase CMDA",end=" ")
enl_list_out=[]
for k in rslt_names:
if DQOvDQSO[k]:
enl_list_out.append(k)
timing=self.x393_mcntrl_timing.get_dly_steps()
numPhaseSteps= int(timing['SDCLK_PERIOD']/timing['PHASE_STEP']+0.5)
print("Phase CMDA",end=" ")
for lane in range(numLanes):
print("DQS%di"%(lane),end=" ")
for k in enl_list_in:
for b in range(numBits):
print("%s-DQ%di"%(k.upper()[0], b),end=" ")
for lane in range(numLanes):
print("DQS%d0"%(lane),end=" ")
#TODO: add DQ%do
for k in enl_list_out:
for b in range(numBits):
print("%s-DQ%do"%(k.upper()[0], b),end=" ")
print()
for phase in range(numPhaseSteps):
print("%d"%(phase),end=" ")
#CMDA_ODEALY
if not cmda_bspe[phase]['ldly'] is None:
print("%d"%(cmda_bspe[phase]['ldly']),end=" ")
else:
print ("?",end=" ")
#DQS_IDEALY
# print ('\n\ndqsi_phase=',dqsi_phase)
for lane in range(numLanes): for lane in range(numLanes):
if not dqsi_phase[lane][phase] is None: print("DQS%di"%(lane),end=" ")
print("%d"%(dqsi_phase[lane][phase]),end=" ")
else:
print ("?",end=" ")
#DQ_IDELAY, with half/clock variants
for k in enl_list_in: for k in enl_list_in:
for b in range(numBits): for b in range(numBits):
lane=b//8 print("%s-DQ%di"%(k.upper()[0], b),end=" ")
dqs_dly=dqsi_phase[lane][phase]
valid = not dqs_dly is None
valid = valid and not DQIvDQSI[k] is None
valid = valid and not DQIvDQSI[k][dqs_dly] is None
valid = valid and not DQIvDQSI[k][dqs_dly][b] is None
if valid:
print("%d"%(DQIvDQSI[k][dqs_dly][b]),end=" ")
else:
print ("?",end=" ")
#DQS_ODELAY
for lane in range(numLanes): for lane in range(numLanes):
if (not wlev_dqs_bspe[lane][phase] is None) and (not wlev_dqs_bspe[lane][phase]['ldly'] is None): print("DQS%d0"%(lane),end=" ")
print("%d"%(wlev_dqs_bspe[lane][phase]['ldly']),end=" ") #TODO: add DQ%do
else:
print ("?",end=" ")
#DQ_IDELAY, with half/clock variants
for k in enl_list_out: for k in enl_list_out:
for b in range(numBits): for b in range(numBits):
lane=b//8 print("%s-DQ%do"%(k.upper()[0], b),end=" ")
if (not wlev_dqs_bspe[lane][phase] is None): for k in enl_list_in:
dqs_dly=wlev_dqs_bspe[lane][phase]['ldly'] print("%s-in-err"%(k.upper()[0]),end=" ")
else: for k in enl_list_out:
dqs_dly=None print("%s-out-err"%(k.upper()[0]),end=" ")
valid = not dqs_dly is None print()
valid = valid and not DQOvDQSO[k] is None #print table rows
valid = valid and not DQOvDQSO[k][dqs_dly] is None for phase, phase_data in enumerate(delays_phase):
valid = valid and not DQOvDQSO[k][dqs_dly][b] is None print ("%d"%(phase),end=" ")
if valid: if not phase_data is None:
print("%d"%(DQOvDQSO[k][dqs_dly][b]),end=" ") try:
else: print ("%d"%(phase_data['cmda']),end=" ")
except:
print ("?",end=" ") print ("?",end=" ")
print() for lane in range(numLanes):
try:
print ("%d"%(phase_data['dqsi'][lane]),end=" ")
except:
print ("?",end=" ")
for k in enl_list_in:
for b in range(numBits):
try:
print ("%d"%(phase_data['dqi'][k][b]),end=" ")
except:
print ("?",end=" ")
for lane in range(numLanes):
try:
print ("%d"%(phase_data['dqso'][lane]),end=" ")
except:
print ("?",end=" ")
for k in enl_list_out:
for b in range(numBits):
try:
print ("%d"%(phase_data['dqo'][k][b]),end=" ")
except:
print ("?",end=" ")
for k in enl_list_in:
try:
if not None in phase_data['dqsi']:
max_err=max(maxErrDqsi[k][dly][lane] for lane,dly in enumerate(phase_data['dqsi']))
# for dly in phase_data['dqsi']:
# err=maxErrDqsi[k][dly]
# print("%.1f"%(err),end=" ")
print("%.1f"%(max_err),end=" ")
else:
print ("X",end=" ")
except:
print ("?",end=" ")
for k in enl_list_out:
try:
if not None in phase_data['dqso']:
max_err=max(maxErrDqso[k][dly][lane] for lane,dly in enumerate(phase_data['dqso']))
print("%.1f"%(max_err),end=" ")
else:
print ("x",end=" ")
except:
print ("?",end=" ")
print()
if set_table:
\ No newline at end of file self.adjustment_state['delays_phase'] = delays_phase
return delays_phase
def show_all_vs_phase(self,
keep_all=False,
load_hardcoded=False):
'''
Show table (to be copied to a spreadsheet) with all delay settings for each
DDR3 memory clock phase value
@param keep_all - show incomplete data (some of the delays may not have valid values
for selected clock phase, false - show only data for valid phases
@param load_hardcoded - get hard-coded data (false - use current)
'''
if load_hardcoded:
self.load_hardcoded_data()
self.get_delays_vs_phase(
filter_dqo=2,
filter_dqi=2,
filter_dqso=2,
filter_dqsi=2,
filter_cmda=2,
keep_all=keep_all,
set_table=False,
quiet=2)
...@@ -132,20 +132,23 @@ class X393McntrlBuffers(object): ...@@ -132,20 +132,23 @@ class X393McntrlBuffers(object):
def write_block_buf_chn(self, # def write_block_buf_chn(self, #
chn, # input integer chn; # buffer channel chn, # input integer chn; # buffer channel
page, # input [1:0] page; page, # input [1:0] page;
num_words_or_data_list): # input integer num_words; # number of words to write (will be rounded up to multiple of 16) num_words_or_data_list, # input integer num_words; # number of words to write (will be rounded up to multiple of 16)
quiet = 1):
""" """
Fill specified buffer with the pattern data Fill specified buffer with the pattern data
@param chn 4-bit buffer channel (0..4) to write data to @param chn 4-bit buffer channel (0..4) to write data to
@param page 2-bit buffer page to write to @param page 2-bit buffer page to write to
@param num_words_or_data_list> number of 32-bit words to generate/write or a list with integer data @param num_words_or_data_list> number of 32-bit words to generate/write or a list with integer data
@param quiet reduce output
""" """
print("===write_block_buf_chn() chn=0x%x, page=0x%x"%(chn,page), end=" ") if quiet < 2:
if isinstance (num_words_or_data_list,list): print("===write_block_buf_chn() chn=0x%x, page=0x%x"%(chn,page), end=" ")
try: if isinstance (num_words_or_data_list,list):
print("=== [0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,...]"%tuple(num_words_or_data_list[:8]),end="") try:
except: print("=== [0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,...]"%tuple(num_words_or_data_list[:8]),end="")
print("=== [%s]"%str(num_words_or_data_list)) except:
print("===") print("=== [%s]"%str(num_words_or_data_list))
print("===")
start_addr=-1 start_addr=-1
if chn==0:start_addr=vrlg.MCONTR_BUF0_WR_ADDR + (page << 8) if chn==0:start_addr=vrlg.MCONTR_BUF0_WR_ADDR + (page << 8)
elif chn==1:start_addr=vrlg.MCONTR_BUF1_WR_ADDR + (page << 8) elif chn==1:start_addr=vrlg.MCONTR_BUF1_WR_ADDR + (page << 8)
......
...@@ -185,6 +185,7 @@ class X393McntrlTiming(object): ...@@ -185,6 +185,7 @@ class X393McntrlTiming(object):
@param delay 8-bit (5+3) delay value to use or a tuple/list with a pair for (lane0, lane1) @param delay 8-bit (5+3) delay value to use or a tuple/list with a pair for (lane0, lane1)
Each of the two elements in the delay tuple/list may be a a common integer or a list/tuple itself Each of the two elements in the delay tuple/list may be a a common integer or a list/tuple itself
if delay is None will restore default values if delay is None will restore default values
Alternatively it can be a one-level list/tuple covering all (16) delays
@param quiet reduce output @param quiet reduce output
""" """
# print("====axi_set_dq_idelay %s"%str(delay)) # print("====axi_set_dq_idelay %s"%str(delay))
...@@ -196,6 +197,11 @@ class X393McntrlTiming(object): ...@@ -196,6 +197,11 @@ class X393McntrlTiming(object):
delay[1].append(vrlg.get_default_field("DLY_LANE1_IDELAY",i)) delay[1].append(vrlg.get_default_field("DLY_LANE1_IDELAY",i))
if isinstance(delay,(int,long)): if isinstance(delay,(int,long)):
delay=(delay,delay) delay=(delay,delay)
elif len(delay) % 8 == 0 :
delay2=[]
for lane in range(len(delay)//8):
delay2.append(delay[8*lane:8*(lane+1)])
delay=delay2
if quiet < 2: if quiet < 2:
print("SET DQ IDELAY="+hexMultiple(delay)) # hexMultiple print("SET DQ IDELAY="+hexMultiple(delay)) # hexMultiple
self.axi_set_multiple_delays(vrlg.LD_DLY_LANE0_IDELAY, 0, 8, delay[0], "DLY_LANE0_IDELAY") self.axi_set_multiple_delays(vrlg.LD_DLY_LANE0_IDELAY, 0, 8, delay[0], "DLY_LANE0_IDELAY")
...@@ -211,6 +217,7 @@ class X393McntrlTiming(object): ...@@ -211,6 +217,7 @@ class X393McntrlTiming(object):
@param delay 8-bit (5+3) delay value to use or a tuple/list with a pair for (lane0, lane1) @param delay 8-bit (5+3) delay value to use or a tuple/list with a pair for (lane0, lane1)
Each of the two elements in the delay tuple/list may be a a common integer or a list/tuple itself Each of the two elements in the delay tuple/list may be a a common integer or a list/tuple itself
if delay is None will restore default values if delay is None will restore default values
Alternatively it can be a one-level list/tuple covering all (16) delays
@param quiet reduce output @param quiet reduce output
""" """
if delay is None: if delay is None:
...@@ -220,6 +227,11 @@ class X393McntrlTiming(object): ...@@ -220,6 +227,11 @@ class X393McntrlTiming(object):
delay[1].append(vrlg.get_default_field("DLY_LANE1_ODELAY",i)) delay[1].append(vrlg.get_default_field("DLY_LANE1_ODELAY",i))
if isinstance(delay,(int,long)): if isinstance(delay,(int,long)):
delay=(delay,delay) delay=(delay,delay)
elif len(delay) % 8 == 0 :
delay2=[]
for lane in range(len(delay)//8):
delay2.append(delay[8*lane:8*(lane+1)])
delay=delay2
if quiet < 2: if quiet < 2:
print("SET DQ ODELAY="+hexMultiple(delay)) # hexMultiple print("SET DQ ODELAY="+hexMultiple(delay)) # hexMultiple
self.axi_set_multiple_delays(vrlg.LD_DLY_LANE0_ODELAY, 0, 8, delay[0], "DLY_LANE0_ODELAY"); self.axi_set_multiple_delays(vrlg.LD_DLY_LANE0_ODELAY, 0, 8, delay[0], "DLY_LANE0_ODELAY");
......
...@@ -532,7 +532,8 @@ class X393PIOSequences(object): ...@@ -532,7 +532,8 @@ class X393PIOSequences(object):
@sel - 0 - early, 1 - late read command @sel - 0 - early, 1 - late read command
@verbose print data being written (default: False) @verbose print data being written (default: False)
""" """
print("===set_write_block ba=0x%x, ra=0x%x, ca=0x%x, num8=%d extraTgl=%d, sel=%d, verbose=%d"%(ba,ra,ca,num8,extraTgl,sel, verbose)) if verbose > 0:
print("===set_write_block ba=0x%x, ra=0x%x, ca=0x%x, num8=%d extraTgl=%d, sel=%d, verbose=%d"%(ba,ra,ca,num8,extraTgl,sel, verbose))
cmd_addr = vrlg.MCONTR_CMD_WR_ADDR + vrlg.WRITE_BLOCK_OFFSET cmd_addr = vrlg.MCONTR_CMD_WR_ADDR + vrlg.WRITE_BLOCK_OFFSET
# activate # activate
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST # addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
...@@ -790,7 +791,7 @@ class X393PIOSequences(object): ...@@ -790,7 +791,7 @@ class X393PIOSequences(object):
<en_refresh> enable refresh immediately <en_refresh> enable refresh immediately
<verbose> print data being written (default: False) <verbose> print data being written (default: False)
""" """
print("SET REFRESH: tRFC=%d, tREFI=%d"%(t_rfc,t_refi)) print("**** SET REFRESH: tRFC=%d, tREFI=%d"%(t_rfc,t_refi))
cmd_addr = vrlg.MCONTR_CMD_WR_ADDR + vrlg.REFRESH_OFFSET cmd_addr = vrlg.MCONTR_CMD_WR_ADDR + vrlg.REFRESH_OFFSET
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST # addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data=self.func_encode_cmd( 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) data=self.func_encode_cmd( 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment