Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
X
x393
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
x393
Commits
c9bb19f1
Commit
c9bb19f1
authored
Apr 06, 2015
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Split py393/x393_mcntrl_adjust.py
in two files
parent
a7004146
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
870 additions
and
0 deletions
+870
-0
x393_mcntrl_eyepatterns.py
py393/x393_mcntrl_eyepatterns.py
+870
-0
No files found.
py393/x393_mcntrl_eyepatterns.py
0 → 100644
View file @
c9bb19f1
from
__future__
import
print_function
'''
# Copyright (C) 2015, Elphel.inc.
# Class based on earlier code to produce eye patterns
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
@author: Andrey Filippov
@copyright: 2015 Elphel, Inc.
@license: GPLv3.0+
@contact: andrey@elphel.coml
@deffield updated: Updated
'''
__author__
=
"Andrey Filippov"
__copyright__
=
"Copyright 2015, Elphel, Inc."
__license__
=
"GPL"
__version__
=
"3.0+"
__maintainer__
=
"Andrey Filippov"
__email__
=
"andrey@elphel.com"
__status__
=
"Development"
import
random
from
x393_mem
import
X393Mem
import
x393_axi_control_status
from
x393_pio_sequences
import
X393PIOSequences
from
x393_mcntrl_timing
import
X393McntrlTiming
from
x393_mcntrl_buffers
import
X393McntrlBuffers
from
verilog_utils
import
checkIntArgs
,
smooth2d
,
split_delay
,
combine_delay
,
NUM_FINE_STEPS
,
convert_w32_to_mem16
,
convert_mem16_to_w32
import
vrlg
#NUM_FINE_STEPS= 5
NUM_DLY_STEPS
=
NUM_FINE_STEPS
*
32
# =160
class
X393McntrlEyepattern
(
object
):
DRY_MODE
=
True
# True
DEBUG_MODE
=
1
x393_mem
=
None
x393_axi_tasks
=
None
#x393X393AxiControlStatus
x393_pio_sequences
=
None
x393_mcntrl_timing
=
None
x393_mcntrl_buffers
=
None
verbose
=
1
adjustment_state
=
{}
def
__init__
(
self
,
debug_mode
=
1
,
dry_mode
=
True
):
self
.
DEBUG_MODE
=
debug_mode
self
.
DRY_MODE
=
dry_mode
self
.
x393_mem
=
X393Mem
(
debug_mode
,
dry_mode
)
# self.x393_axi_tasks= X393AxiControlStatus(debug_mode,dry_mode)
self
.
x393_axi_tasks
=
x393_axi_control_status
.
X393AxiControlStatus
(
debug_mode
,
dry_mode
)
self
.
x393_pio_sequences
=
X393PIOSequences
(
debug_mode
,
dry_mode
)
self
.
x393_mcntrl_timing
=
X393McntrlTiming
(
debug_mode
,
dry_mode
)
self
.
x393_mcntrl_buffers
=
X393McntrlBuffers
(
debug_mode
,
dry_mode
)
# self.__dict__.update(VerilogParameters.__dict__["_VerilogParameters__shared_state"]) # Add verilog parameters to the class namespace
try
:
self
.
verbose
=
vrlg
.
VERBOSE
except
:
pass
def
bad_data
(
self
,
buf
):
"""
The whole block contains only "bad data" - nothing was read
It can happen if command was not decoded correctly
<buf> - list of the data read
Returns True if the data is bad, False otherwise
"""
for
w
in
buf
:
if
(
w
!=
0xffffffff
):
return
False
return
True
def
missing_dqs
(
self
,
rd_blk
,
quiet
=
False
):
"""
Suspect missing final DQS puls(es) during write if last written burst matches previous one
<rd_blk> - block of 32-bit data read from DDR3 device
<quiet> - no output
Returns True if missing DQS pulse is suspected
"""
if
(
not
rd_blk
)
or
(
len
(
rd_blk
)
<
8
):
return
False
for
i
in
range
(
-
4
,
0
):
if
rd_blk
[
i
]
!=
rd_blk
[
i
-
4
]:
break
else
:
if
not
quiet
:
print
(
"End of the block repeats 2 last 8-bursts, insufficient number of trailing DQS pulses is suspected:"
)
print
(
"
\n
%03
x:"
%
(
len
(
rd_blk
)
-
8
),
end
=
" "
)
for
i
in
range
(
len
(
rd_blk
)
-
8
,
len
(
rd_blk
)):
print
(
"
%08
x"
%
rd_blk
[
i
],
end
=
" "
)
print
(
"
\n
"
)
return
True
return
False
def
scan_dqs
(
self
,
low_delay
,
high_delay
,
num
=
8
,
sel
=
1
,
# 0 - early, 1 - late read command (shift by a SDCLK period)
quiet
=
2
):
"""
Scan DQS 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_dqs_idelay
(
enc_dly
)
buf
=
self
.
x393_pio_sequences
.
read_pattern
(
(
4
*
num
+
2
),
# num,
0
,
# show_rslt,
1
)
# Wait for operation to complete
if
quiet
<
1
:
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
):
lane
=
w
%
2
for
wb
in
range
(
32
):
g
=
(
wb
/
8
)
%
2
b
=
wb
%
8
+
lane
*
8
+
16
*
g
if
(
buf
[
w
+
2
]
&
(
1
<<
wb
)
!=
0
):
data
[
b
]
+=
1
results
.
append
(
data
)
if
quiet
<
2
:
print
(
"
%3
d (0x
%02
x): "
%
(
dly
,
enc_dly
),
end
=
""
)
for
i
in
range
(
32
):
print
(
"
%5
x"
%
data
[
i
],
end
=
""
)
print
()
if
quiet
<
3
:
for
index
in
range
(
len
(
results
)):
dly
=
index
+
low
enc_dly
=
combine_delay
(
dly
)
if
(
len
(
results
[
index
])
>
0
):
print
(
"
%3
d (0x
%02
x): "
%
(
dly
,
enc_dly
),
end
=
""
)
for
i
in
range
(
32
):
print
(
"
%5
x"
%
results
[
index
][
i
],
end
=
""
)
print
()
print
()
if
quiet
<
4
:
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
()
return
results
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
(
"
%3
d (0x
%02
x): "
%
(
dly
,
enc_dly
),
end
=
""
)
for
i
in
range
(
32
):
print
(
"
%5
x"
%
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
(
"
%3
d (0x
%02
x): "
%
(
dly
,
enc_dly
),
end
=
""
)
for
i
in
range
(
32
):
print
(
"
%5
x"
%
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
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
(
"
%2
d:
%3
d (0x
%02
x)"
%
(
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
def
corr_delays
(
self
,
low
,
# absolute delay value of start scan
avg_types
,
# weights of each of the 8 bit sequences
res_bits
,
# individual per-bit results
res_avg
,
# averaged eye data table, each line has 8 elements, or [] for bad measurements
corr_fine
,
# fine delay correction
ends_dist
,
# do not process if one of the primary interval ends is within this from 0.0 or 1.0
verbose
):
"""
Correct delays
<low> absolute delay value of start scan
<avg_types> weights of each of the 8 bit sequences
<res_bits> individual per-bit results
<res_avg> averaged eye data table, each line has 8 elements, or [] for bad measurements
<corr_fine> fine delay correction
<ends_dist> do not process if one of the primary interval ends is within this from 0.0 or 1.0
<verbose>
Returns list of corrected delays
"""
# coarse adjustments - decimate arrays to use the same (0) value of the fine delay
usable_types
=
[]
for
i
,
w
in
enumerate
(
avg_types
):
if
(
w
>
0
)
and
not
i
in
(
0
,
7
)
:
usable_types
.
append
(
i
)
if
(
verbose
):
print
(
"usable_types="
,
usable_types
)
def
thr_sign
(
bit
,
typ
,
limit
,
data
):
# lim_l=limit
# lim_u=1.0-limit
if
data
[
bit
][
typ
]
<=
limit
:
return
-
1
if
data
[
bit
][
typ
]
>=
(
1.0
-
limit
):
return
1
return
0
def
thr_signs
(
typ
,
limit
,
data
):
signs
=
""
for
bit
in
range
(
15
,
-
1
,
-
1
):
signs
+=
(
"-"
,
"0"
,
"+"
)[
thr_sign
(
bit
,
typ
,
limit
,
data
)
+
1
]
def
full_state
(
types
,
limit
,
data
):
#will NOT return None if any is undefined
state
=
""
for
t
in
types
:
for
bit
in
range
(
15
,
-
1
,
-
1
):
state
+=
(
"-"
,
"0"
,
"+"
)[
thr_sign
(
bit
,
t
,
limit
,
data
)
+
1
]
return
state
def
full_same_state
(
types
,
limit
,
data
):
#will return None if any is undefined
state
=
""
for
t
in
types
:
s0
=
thr_sign
(
15
,
t
,
limit
,
data
)
state
+=
(
"-"
,
"0"
,
"+"
)[
s0
+
1
]
for
bit
in
range
(
15
,
-
1
,
-
1
):
s
=
thr_sign
(
bit
,
t
,
limit
,
data
)
if
(
not
s
)
or
(
s
!=
s0
)
:
return
None
return
state
def
diff_state
(
state1
,
state2
):
for
i
,
s
in
enumerate
(
state1
):
if
s
!=
state2
[
i
]:
return
True
return
False
# start_index=0;
# if (low % NUM_FINE_STEPS) != 0:
# start_index=NUM_FINE_STEPS-(low % NUM_FINE_STEPS)
#find the first index where all bits are either above 1.0 -ends_dist or below ends_dist
for
index
in
range
(
len
(
res_avg
)):
print
(
" index=
%
d:
%
s"
%
(
index
,
full_state
(
usable_types
,
ends_dist
,
res_bits
[
index
])))
initial_state
=
full_same_state
(
usable_types
,
ends_dist
,
res_bits
[
index
])
if
initial_state
:
break
else
:
print
(
"Could not find delay value where all bits/types are outside of undefined area (
%
f thershold)"
%
ends_dist
)
return
None
if
(
verbose
):
print
(
"start index=
%
d, start state=
%
s"
%
(
index
,
initial_state
))
#find end of that state
for
index
in
range
(
index
+
1
,
len
(
res_avg
)):
state
=
full_same_state
(
usable_types
,
ends_dist
,
res_bits
[
index
])
if
state
!=
initial_state
:
break
else
:
print
(
"Could not find delay value where initial state changes (
%
f thershold)"
%
ends_dist
)
return
None
last_initial_index
=
index
-
1
if
(
verbose
):
print
(
"last start state index=
%
d, new state=
%
s"
%
(
last_initial_index
,
state
))
#find new defined state for all bits
for
index
in
range
(
last_initial_index
+
1
,
len
(
res_avg
)):
#here repeat last delay
new_state
=
full_same_state
(
usable_types
,
ends_dist
,
res_bits
[
index
])
if
new_state
and
(
new_state
!=
initial_state
):
break
else
:
print
(
"Could not find delay value whith the new defined state (
%
f thershold)"
%
ends_dist
)
return
None
new_state_index
=
index
if
(
verbose
):
print
(
"new defined state index=
%
d, new state=
%
s"
%
(
new_state_index
,
new_state
))
# remove states that do not have a transition
filtered_types
=
[]
for
i
,
t
in
enumerate
(
usable_types
):
if
(
new_state
[
i
]
!=
initial_state
[
i
]):
filtered_types
.
append
(
t
)
if
(
verbose
):
print
(
"filtered_types="
,
filtered_types
)
second_trans
=
1
in
filtered_types
# use second transition, false - use first transition
if
(
verbose
):
print
(
"second_trans="
,
second_trans
)
# signs=((1,1,-1,-1),(1,-1,1,-1))[1 in filtered_types]
signs
=
((
0
,
0
,
1
,
1
,
-
1
,
-
1
,
0
,
0
),(
0
,
1
,
-
1
,
0
,
0
,
1
,
-
1
,
0
))[
1
in
filtered_types
]
if
(
verbose
):
print
(
"signs="
,
signs
)
for
index
in
range
(
last_initial_index
,
new_state_index
+
1
):
if
(
verbose
):
print
(
"index=
%3
d, delay=
%3
d, state=
%
s"
%
(
index
,
index
+
low
,
full_state
(
filtered_types
,
ends_dist
,
res_bits
[
index
])))
#extend range, combine each bit and averages
ext_low_index
=
last_initial_index
-
(
new_state_index
-
last_initial_index
)
if
ext_low_index
<
0
:
ext_low_index
=
0
ext_high_index
=
new_state_index
+
(
new_state_index
-
last_initial_index
)
if
ext_high_index
>=
len
(
res_bits
):
ext_high_index
=
len
(
res_bits
)
-
1
if
(
verbose
):
print
(
"ext_low_index=
%
d ext_high_index=
%
d"
%
(
ext_low_index
,
ext_high_index
))
bit_data
=
[]
for
i
in
range
(
16
):
bit_data
.
append
([])
# [[]]*16 does not work! (shallow copy)
avg_data
=
[]
for
index0
in
range
(
ext_high_index
-
ext_low_index
+
1
):
index
=
index0
+
ext_low_index
# if (verbose): print(res_bits[index])
bit_samples
=
[
0.0
]
*
16
avg_sample
=
0.0
weight
=
0.0
for
t
in
filtered_types
:
w
=
avg_types
[
t
]
weight
+=
w
sw
=
signs
[
t
]
*
w
avg_sample
+=
sw
*
(
2.0
*
res_avg
[
index
][
t
]
-
1.0
)
# if (verbose): print ("%3d %d:"%(index,t),end=" ")
for
bit
in
range
(
16
):
bit_samples
[
bit
]
+=
sw
*
(
2.0
*
res_bits
[
index
][
bit
][
t
]
-
1.0
)
# if (verbose): print ("%.3f"%(res_bits[index][bit][t]),end=" ")
# if (verbose): print()
avg_sample
/=
weight
avg_data
.
append
(
avg_sample
)
for
bit
in
range
(
16
):
bit_samples
[
bit
]
/=
weight
# if (verbose): print ("bit_samples[%d]=%f"%(bit,bit_samples[bit]))
bit_data
[
bit
]
.
append
(
bit_samples
[
bit
])
# if (verbose): print ("bit_samples=",bit_samples)
# if index0 <3:
# if (verbose): print ("bit_data=",bit_data)
# if (verbose): print ("\n\nbit_data=",bit_data)
period_fine
=
len
(
corr_fine
)
for
index
in
range
(
ext_high_index
-
ext_low_index
+
1
):
dly
=
low
+
index
+
ext_low_index
corr_dly
=
dly
+
corr_fine
[
dly
%
period_fine
]
if
(
verbose
):
print
(
"
%
d
%
d
%.2
f
%.3
f"
%
(
index
,
dly
,
corr_dly
,
avg_data
[
index
]),
end
=
" "
)
for
bit
in
range
(
16
):
if
(
verbose
):
print
(
"
%.3
f"
%
(
bit_data
[
bit
][
index
]),
end
=
" "
)
if
(
verbose
):
print
()
# Seems all above was an overkill, just find bit delays that result in most close to 0
delays
=
[]
for
bit
in
range
(
16
):
best_dist
=
1.0
best_index
=
None
for
index
in
range
(
ext_high_index
-
ext_low_index
+
1
):
if
(
abs
(
bit_data
[
bit
][
index
])
<
best_dist
):
best_dist
=
abs
(
bit_data
[
bit
][
index
])
best_index
=
index
delays
.
append
(
best_index
+
low
+
ext_low_index
)
if
(
verbose
):
print
(
delays
)
return
delays
def
calibrate_finedelay
(
self
,
low
,
# absolute delay value of start scan
avg_types
,
# weights of each of the 8 bit sequences
res_avg
,
# averaged eye data tablle, each line has 8 elements, or [] for bad measurements
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
"""
Calibrate fine delay taps
<low> absolute delay value of start scan
<avg_types> weights of each of the 8 bit sequences
<res_avg> averaged eye data tablle, each line has 8 elements, or [] for bad measurements
<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
"""
start_index
=
0
;
if
(
low
%
NUM_FINE_STEPS
)
!=
0
:
start_index
=
NUM_FINE_STEPS
-
(
low
%
NUM_FINE_STEPS
)
weights
=
[
0.0
]
*
(
NUM_FINE_STEPS
)
corr
=
[
0.0
]
*
(
NUM_FINE_STEPS
)
#[0] will stay 0
for
index
in
range
(
start_index
,
len
(
res_avg
)
-
NUM_FINE_STEPS
,
NUM_FINE_STEPS
):
if
(
len
(
res_avg
[
index
])
>
0
)
and
(
len
(
res_avg
[
index
+
NUM_FINE_STEPS
])
>
0
):
for
t
,
w
in
enumerate
(
avg_types
):
if
(
w
>
0
):
f
=
res_avg
[
index
][
t
];
s
=
res_avg
[
index
+
NUM_FINE_STEPS
][
t
];
# print ("index=%d t=%d f=%f s=%s"%(index,t,f,s))
if
((
f
>
ends_dist
)
and
(
s
>
ends_dist
)
and
(
f
<
(
1
-
ends_dist
))
and
(
s
<
(
1
-
ends_dist
))
and
(
abs
(
s
-
f
)
>
min_diff
)):
diff
=
s
-
f
wd
=
w
*
diff
*
diff
# squared? or use abs?
for
j
in
range
(
1
,
NUM_FINE_STEPS
):
if
(
(
len
(
res_avg
[
index
+
j
])
>
0
)):
v
=
res_avg
[
index
+
j
][
t
];
#correction to the initial step==1
d
=
(
v
-
f
)
/
(
s
-
f
)
*
NUM_FINE_STEPS
-
j
#average
corr
[
j
]
+=
wd
*
d
weights
[
j
]
+=
wd
# print ("\n weights:")
# print(weights)
# print ("\n corr:")
# print(corr)
for
i
,
w
in
enumerate
(
weights
):
if
(
w
>
0
)
:
corr
[
i
]
/=
w
# will skip 0
print
(
"
\n
corr:"
)
# print(corr)
for
i
,
c
in
enumerate
(
corr
):
print
(
"
%
i
%
f"
%
(
i
,
c
))
return
corr
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
%03
x:"
%
i
,
end
=
" "
)
if
(
verbose
and
not
adjust
):
print
(
"
%04
x"
%
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
%03
x:"
%
i
,
end
=
" "
)
if
(
verbose
and
not
adjust
):
print
(
"
%08
x"
%
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
(
"
\n
total_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
(
"
\a
vg_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
%03
x:"
%
i
,
end
=
" "
)
if
(
verbose
and
not
adjust
):
print
(
"
%08
x"
%
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
%03
x:"
%
i
,
end
=
" "
)
if
(
verbose
and
not
adjust
):
print
(
"
%04
x"
%
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
(
"
%3
d (0x
%02
x): "
%
(
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
(
"
%3
d"
%
(
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
(
"
%02
d:
%
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
%.2
f"
%
(
dly
,
corr_dly
),
end
=
" "
)
for
t
in
range
(
8
):
for
i
in
range
(
16
):
try
:
print
(
"
%.4
f"
%
(
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
%.2
f"
%
(
dly
,
corr_dly
),
end
=
" "
)
for
t
in
range
(
8
):
try
:
print
(
"
%.4
f"
%
(
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
def
scan_delay_random
(
self
,
low_delay
,
high_delay
,
use_dq
,
# 0 - scan dqs, 1 - scan dq (common valuwe, post-adjustment)
use_odelay
,
# 0 - idelay, 1 - odelay
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
verbose
):
"""
Scan 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
<verbose>: verbose mode (more prints)
"""
checkIntArgs
((
'low_delay'
,
'high_delay'
),
locals
())
self
.
scan_or_adjust_delay_random
(
low_delay
,
high_delay
,
use_dq
,
# 0 - scan dqs, 1 - scan dq (common valuwe, post-adjustment)
use_odelay
,
ends_dist
,
# do not process if one of the primary interval ends is within this from 0.0 or 1.0
min_diff
,
False
,
#scan, not adjust
verbose
)
# minimal difference between primary delay steps to process
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment