Commit fad107cb authored by Andrey Filippov's avatar Andrey Filippov

implemented help for task based on functions documentation

parent e6868ded
......@@ -35,7 +35,9 @@ __status__ = "Development"
'''
import sys
import os
import inspect
import re
#import os.path
from argparse import ArgumentParser
#import argparse
from argparse import RawDescriptionHelpFormatter
......@@ -78,8 +80,12 @@ class CLIError(Exception):
def extractTasks(obj,inst):
for name in obj.__dict__:
if hasattr((obj.__dict__[name]), '__call__') and not (name[0]=='_'):
# print (name+" -->"+str(obj.__dict__[name]))
# print (obj.__dict__[name].func_code)
# print ("COMMENTS:"+str(inspect.getcomments(obj.__dict__[name])))
# print ("DOCS:"+str(inspect.getdoc(obj.__dict__[name])))
func_args=obj.__dict__[name].func_code.co_varnames[1:obj.__dict__[name].func_code.co_argcount]
callableTasks[name]={'func':obj.__dict__[name],'args':func_args,'inst':inst}
callableTasks[name]={'func':obj.__dict__[name],'args':func_args,'inst':inst,'docs':inspect.getdoc(obj.__dict__[name])}
def execTask(commandLine):
# result=None
cmdList=commandLine #.split()
......@@ -118,6 +124,17 @@ def hx(obj):
return "0x%x"%obj
except:
return str(obj)
def getFuncArgsString(name):
funcFArgs=callableTasks[name]['args']
sFuncArgs=""
if funcFArgs:
sFuncArgs+='<'+str(funcFArgs[0])+'>'
for a in funcFArgs[1:]:
sFuncArgs+=' <'+str(a)+'>'
return sFuncArgs
def main(argv=None): # IGNORE:C0111
'''Command line options.'''
......@@ -163,9 +180,14 @@ USAGE
parser.add_argument("-p", "--parameter", dest="parameters", action="append", default=[], help="Define parameter(s) as name=value" , nargs='*' )
parser.add_argument("-c", "--command", dest="commands", action="append", default=[], help="execute command" , nargs='*')
parser.add_argument("-i", "--interactive", dest="interactive", action="store_true", help="enter interactive mode [default: %(default)s]")
parser.add_argument("-s", "--simulated", dest="simulated", action="store_true", help="Simulated mode (no real hardware I/O) [default: %(default)s]")
# Process arguments
args = parser.parse_args()
if not args.simulated:
if not os.path.isfile("/dev/xdevcfg"):
args.simulated=True
print("Program is forced to run in SIMULATED mode as '/dev/xdevcfg' does not exist (not a camera)")
#print("--- defines=%s"% str(args.defines))
#print("--- paths=%s"% str(args.paths))
#print("--- parameters=%s"% str(args.parameters))
......@@ -259,12 +281,12 @@ USAGE
if verbose > 3: print("vpars1.VERBOSE__TYPE="+str(vpars1.VERBOSE__TYPE))
if verbose > 3: print("vpars1.VERBOSE__RAW="+str(vpars1.VERBOSE__RAW))
x393mem= x393_mem.X393Mem(verbose,True) #add dry run parameter
x393tasks= x393_axi_control_status.X393AxiControlStatus(verbose,True)
x393Pio= x393_pio_sequences.X393PIOSequences(verbose,True)
x393Timing= x393_mcntrl_timing.X393McntrlTiming(verbose,True)
x393Buffers=x393_mcntrl_buffers.X393McntrlBuffers(verbose,True)
x393Tests= x393_mcntrl_tests.X393McntrlTests(verbose,True)
x393mem= x393_mem.X393Mem(verbose,args.simulated) #add dry run parameter
x393tasks= x393_axi_control_status.X393AxiControlStatus(verbose,args.simulated)
x393Pio= x393_pio_sequences.X393PIOSequences(verbose,args.simulated)
x393Timing= x393_mcntrl_timing.X393McntrlTiming(verbose,args.simulated)
x393Buffers=x393_mcntrl_buffers.X393McntrlBuffers(verbose,args.simulated)
x393Tests= x393_mcntrl_tests.X393McntrlTests(verbose,args.simulated)
'''
print ("----------------------")
print("x393_mem.__dict__="+str(x393_mem.__dict__))
......@@ -315,23 +337,40 @@ USAGE
if (args.interactive):
line =""
while True:
line=raw_input('x393--> ').strip()
line=raw_input('x393%s--> '%('','(simulated)')[args.simulated]).strip()
if not line:
print ('Use "quit" to exit, "help" - for help')
elif line == 'quit':
elif (line == 'quit') or (line == 'exit'):
break
elif line== 'help' :
print ("\nAvailable tasks:")
for name,val in sorted(callableTasks.items()):
# funcFArgs=callableTasks[name]['args']
funcFArgs=val['args']
sFuncArgs=""
if funcFArgs:
sFuncArgs+='<'+str(funcFArgs[0])+'>'
for a in funcFArgs[1:]:
sFuncArgs+=' <'+str(a)+'>'
sFuncArgs=getFuncArgsString(name)
print ("Usage: %s %s"%(name,sFuncArgs))
print ('\n"parameters" and "defines" list known defined parameters and macros')
elif (len(line) > len("help")) and (line[:len("help")]=='help'):
helpFilter=line[len('help'):].strip()
try:
re.match(helpFilter,"")
except:
print("Invalid search expression: %s"%helpFilter)
helpFilter=None
if helpFilter:
print
for name,val in sorted(callableTasks.items()):
# if re.findall(helpFilter,name):
if re.match(helpFilter,name):
print('=== %s ==='%name)
sFuncArgs=getFuncArgsString(name)
# print ("Usage: %s %s"%(name,sFuncArgs))
docs=callableTasks[name]['docs']
if docs:
docsl=docs.split("\n")
for l in docsl:
#print (' %s'%l)
print ('%s'%l)
#print(docs)
print (" Usage: %s %s\n"%(name,sFuncArgs))
elif line == 'parameters':
parameters=ivp.getParameters()
for par,val in sorted(parameters.items()):
......
......@@ -65,8 +65,17 @@ class X393AxiControlStatus(object):
'''
def write_contol_register(self, reg_addr, data):
"""
Write 32-bit word to the control register
<addr> - register address relative to the control register address space
<data> - 32-bit data to write
"""
self.x393_mem.axi_write_single_w(self.CONTROL_ADDR+reg_addr, data)
def read_and_wait_status(self, address):
"""
Read word from the status register (up to 26 bits payload and 6-bit sequence number)
<addr> - status register address (currently 0..255)
"""
return self.x393_mem.axi_read_addr_w(self.STATUS_ADDR + address )
def wait_status_condition(self,
......@@ -77,6 +86,20 @@ class X393AxiControlStatus(object):
mask, # input [25:0] mask; // which bits to compare
invert_match, # input invert_match; // 0 - wait until match to pattern (all bits), 1 - wait until no match (any of bits differ)
wait_seq): # input wait_seq; // Wait for the correct sequence number, False assume correct
"""
Poll specified status register until some condition is matched
<status_address> - status register address (currently 0..255)
<status_control_address> - control register address (to control status generation)
<status_mode> - status generation mode:
0: disable status generation,
1: single status request,
2: auto status, keep specified seq number,
4: auto, inc sequence number
<pattern> - 26-bit pattern to match
<mask> - 26-bit mask to enable pattern matching (0-s - ignore)
<invert_match> - invert match (wait until matching condition becomes false)
<wait_seq>- wait for the correct sequence number, if False - assume always correct
"""
match=False
while not match:
data=self.read_and_wait_status(status_address)
......@@ -92,6 +115,9 @@ class X393AxiControlStatus(object):
if self.DRY_MODE: break
def read_all_status(self):
"""
Read and print contents of all defined status registers
"""
# print (self.__dict__)
# for name in self.__dict__:
# print (name+": "+str(name=='MCONTR_PHY_STATUS_REG_ADDR'))
......@@ -113,19 +139,33 @@ class X393AxiControlStatus(object):
reg_addr, # input [7:0] reg_addr;
mode, # input [1:0] mode;
seq_number): # input [5:0] seq_number;
'''
// mode bits:
// 0 disable status generation,
// 1 single status request,
// 2 - auto status, keep specified seq number,
// 3 - auto, inc sequence number
'''
"""
Poll specified status register until some condition is matched
<base_addr> - base control address of the selected module
<reg_addr> - status control register relative to the module address space
<mode> - status generation mode:
0: disable status generation,
1: single status request,
2: auto status, keep specified seq number,
4: auto, inc sequence number
<seq_number> - 6-bit sequence number of the status message to be sent
"""
self.write_contol_register(base_addr + reg_addr, ((mode & 3)<< 6) | (seq_number * 0x3f))
def program_status_all( self,
mode, # input [1:0] mode;
seq_num): # input [5:0] seq_num;
"""
Set status generation mode for all defined modules
<mode> - status generation mode:
0: disable status generation,
1: single status request,
2: auto status, keep specified seq number,
4: auto, inc sequence number
<seq_number> - 6-bit sequence number of the status message to be sent
"""
self.program_status (self.MCONTR_PHY_16BIT_ADDR, self.MCONTR_PHY_STATUS_CNTRL, mode,seq_num)# //MCONTR_PHY_STATUS_REG_ADDR= 'h0,
self.program_status (self.MCONTR_TOP_16BIT_ADDR, self.MCONTR_TOP_16BIT_STATUS_CNTRL, mode,seq_num)# //MCONTR_TOP_STATUS_REG_ADDR= 'h1,
self.program_status (self.MCNTRL_PS_ADDR, self.MCNTRL_PS_STATUS_CNTRL, mode,seq_num)# //MCNTRL_PS_STATUS_REG_ADDR= 'h2,
......@@ -140,32 +180,61 @@ class X393AxiControlStatus(object):
def enable_cmda(self,
en): # input en;
"""
Enable (disable) address, bank and command lines to the DDR3 memory
<en> - 1 - enable, 0 - disable
"""
self.write_contol_register(self.MCONTR_PHY_0BIT_ADDR + self.MCONTR_PHY_0BIT_CMDA_EN + en, 0);
def enable_cke(self,
en): # input en;
"""
Enable (disable) CKE - clock enable to DDR3 memory
<en> - 1 - enable, 0 - disable
"""
self.write_contol_register(self.MCONTR_PHY_0BIT_ADDR + self.MCONTR_PHY_0BIT_CKE_EN + en, 0);
def activate_sdrst(self,
en): # input en;
"""
Activate SDRST (reset) to DDR3 memory
<en> - 1 - activate (low), 0 - deactivate (high)
"""
self.write_contol_register(self.MCONTR_PHY_0BIT_ADDR + self.MCONTR_PHY_0BIT_SDRST_ACT + en, 0);
def enable_refresh(self,
en): # input en;
"""
Enable (disable) refresh of the DDR3 memory
<en> - 1 - enable, 0 - disable
"""
self.write_contol_register(self.MCONTR_TOP_0BIT_ADDR + self.MCONTR_TOP_0BIT_REFRESH_EN + en, 0);
def enable_memcntrl(self,
en): # input en;
"""
Enable memory controller module
<en> - 1 - enable, 0 - disable
"""
self.write_contol_register(self.MCONTR_TOP_0BIT_ADDR + self.MCONTR_TOP_0BIT_MCONTR_EN + en, 0);
def enable_memcntrl_channels(self,
chnen): # input [15:0] chnen; // bit-per-channel, 1 - enable;
"""
Enable memory controller channels (all at once control)
<chnen> - 16-bit control word with per-channel enable bits (bit0 - chn0, ... bit15 - chn15)
"""
self.enabled_channels = chnen; # currently enabled memory channels
self.write_contol_register(self.MCONTR_TOP_16BIT_ADDR + self.MCONTR_TOP_16BIT_CHN_EN, self.enabled_channels & 0xffff) # {16'b0,chnen});
def enable_memcntrl_en_dis(self,
chn, # input [3:0] chn;
en):# input en;
"""
Enable memory controller channels (one at a time)
<chn> - 4-bit channel select
<en> - 1 - enable, 0 - disable of the selected channel
"""
if en:
self.enabled_channels = self.enabled_channels | (1<<chn);
else:
......@@ -175,5 +244,10 @@ class X393AxiControlStatus(object):
def configure_channel_priority(self,
chn, # input [ 3:0] chn;
priority): #input [15:0] priority; // (higher is more important)
"""
Configure channel priority
<chn> - 4-bit channel select
<priority> - 16-bit priority value (higher value means more important)
"""
self.write_contol_register(self.MCONTR_ARBIT_ADDR + chn, priority & 0xffff)# {16'b0,priority});
......@@ -61,7 +61,16 @@ class X393McntrlBuffers(object):
num_bursts, # input [NUM_XFER_BITS:0] num_bursts; // number of 8-bursts to write (will be rounded up to multiple of 16)
startX, # input integer startX;
startY): #input integer startY;
print("====== write_block_scanline_chn:%d page: %x X=0x%x Y=0x%x num=%dt"%(chn, page, startX, startY,num_bursts))
"""
Fill buffer with the generated data in scanline mode
<chn> 4-bit channel number (0,1,2,3,4 are valid) to use
<page> 2-bit page number in the buffer to write to
<num_bursts> number of 8-word (16 bytes) bursts to write
<startX> horizontal shift of the left of the data line to write, in bytes
<startY> line number to encode in the data
"""
if self.DEBUG_MODE > 1:
print("====== write_block_scanline_chn:%d page: %x X=0x%x Y=0x%x num=%dt"%(chn, page, startX, startY,num_bursts))
if chn == 0: start_addr=self.MCONTR_BUF0_WR_ADDR + (page << 8)
elif chn == 1: start_addr=self.MCONTR_BUF1_WR_ADDR + (page << 8)
elif chn == 2: start_addr=self.MCONTR_BUF2_WR_ADDR + (page << 8)
......@@ -76,6 +85,11 @@ class X393McntrlBuffers(object):
def write_block_buf(self,
start_word_address, # input [29:0] start_word_address;
num_words_or_data_list): # input integer num_words; # number of words to write (will be rounded up to multiple of 16)
"""
Fill buffer the pattern data
<start_word_address> full register address in AXI space (in 32-bit words, not bytes)
<num_words_or_data_list> number of 32-bit words to generate/write or a list with integer data
"""
if isinstance (num_words_or_data_list,int):
data=[]
for i in range(num_words_or_data_list):
......@@ -94,6 +108,12 @@ class X393McntrlBuffers(object):
start_word_address, # input [29:0] start_word_address;
num_words, # input integer num_words; # number of words to write (will be rounded up to multiple of 16)
start_value): # input integer start_value;
"""
Fill buffer the incremental data (each next register is written with previous register data + 1
<start_word_address> full register address in AXI space (in 32-bit words, not bytes)
<num_words> number of 32-bit words to generate/write
<start_value> value to write to the first register (to start_word_address)
"""
if self.verbose>0:
print("**** write_block_incremtal, start_word_address=0x%x, num_words=0x%x, start_value=0x%x "%(start_word_address,num_words,start_value))
for i in range(0,num_words):
......@@ -105,6 +125,12 @@ class X393McntrlBuffers(object):
chn, # input integer chn; # buffer channel
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)
"""
Fill specified buffer with the pattern data
<chn> 4-bit buffer channel (0..4) to write data to
<page> 2-bit buffer page to write to
<num_words_or_data_list> number of 32-bit words to generate/write or a list with integer data
"""
start_addr=-1
if chn==0:start_addr=self.MCONTR_BUF0_WR_ADDR + (page << 8)
elif chn==1:start_addr=self.MCONTR_BUF1_WR_ADDR + (page << 8)
......@@ -120,6 +146,13 @@ class X393McntrlBuffers(object):
start_word_address, # input [29:0] start_word_address;
num_read, # input integer num_read; # number of words to read (will be rounded up to multiple of 16)
show_rslt=True):
"""
Fill buffer the incremental data (each next register is written with previous register data + 1
<start_word_address> full register address in AXI space (in 32-bit words, not bytes)
<num_read> number of 32-bit words to read
<show_rslt> print buffer data read
"""
if self.verbose>0:
print("**** read_block_buf, start_word_address=0x%x, num_read=0x%x "%(start_word_address,num_read))
result=[]
......@@ -135,6 +168,13 @@ class X393McntrlBuffers(object):
page, #input [1:0] page;
num_read, #input integer num_read; # number of words to read (will be rounded up to multiple of 16)
show_rslt=True):
"""
Fill buffer the incremental data (each next register is written with previous register data + 1
<chn> 4-bit buffer channel (0..4) to read from
<page> 2-bit buffer page to read from
<num_read> number of 32-bit words to read
<show_rslt> print buffer data read
"""
start_addr=-1
if chn==0: start_addr=self.MCONTR_BUF0_RD_ADDR + (page << 8)
elif chn==1: start_addr=self.MCONTR_BUF1_RD_ADDR + (page << 8)
......
......@@ -72,7 +72,18 @@ class X393McntrlTests(object):
write_mem, # input write_mem; # write to memory mode (0 - read from memory)
enable, # input enable; # enable requests from this channel ( 0 will let current to finish, but not raise want/need)
chn_reset): # input chn_reset; # immediately reset all the internal circuitry
return concat (# func_encode_mode_tiled={
"""
Combines arguments to create a 7-bit encoded data for tiled mode memory R/W
<byte32> use 32-byte wide columns (0 - use 16-byte ones)
<keep_open>, do not close page between accesses (for 8 or less rows only)
<extra_pages>, 2-bit number of extra pages that need to stay (not to be overwritten) in the buffer
This argument can be used for read access with horizontal overlapping tiles
<write_mem>, write to memory mode (0 - read from memory)
<enable>, enable requests from this channel ( 0 will let current to finish, but not raise want/need)
<chn_reset>): immediately reset all the internal circuitry
"""
return concat (
((0,1)[byte32], 1), # byte32,
((0,1)[keep_open],1), # keep_open,
(extra_pages, 2), # extra_pages,
......@@ -86,13 +97,33 @@ class X393McntrlTests(object):
write_mem, # input write_mem; # write to memory mode (0 - read from memory)
enable, # input enable; # enable requests from this channel ( 0 will let current to finish, but not raise want/need)
chn_reset): # input chn_reset; # immediately reset all the internal circuitry
return concat (# func_encode_mode_tiled={
"""
Combines arguments to create a 5-bit encoded data for scanline mode memory R/W
<extra_pages>, 2-bit number of extra pages that need to stay (not to be overwritten) in the buffer
This argument can be used for read access with horizontal overlapping tiles
<write_mem>, write to memory mode (0 - read from memory)
<enable>, enable requests from this channel ( 0 will let current to finish, but not raise want/need)
<chn_reset>): immediately reset all the internal circuitry
"""
return concat (
(extra_pages, 2), # extra_pages,
((0,1)[write_mem],1), # write_mem,
((0,1)[enable], 1), #enable,
((1,0)[chn_reset],1)) # ~chn_reset};
def task_set_up(self,
set_per_pin_delays):
"""
Initial setup of the memory controller, including:
tristate patterns
DQS/DQM patterns
all sequences
channel 0 buffer data
I/O delays
clock phase
<set_per_pin_delays> - 1 - set individual (per-pin) I/O delays, 0 - use common for the whole class
"""
# set dq /dqs tristate on/off patterns
self.x393_mcntrl_timing.axi_set_tristate_patterns()
# set patterns for DM (always 0) and DQS - always the same (may try different for write lev.)
......@@ -117,6 +148,9 @@ class X393McntrlTests(object):
self.x393_mcntrl_timing.axi_set_phase(self.DLY_PHASE);
def set_all_sequences(self):
"""
Set all sequences: MRS, REFRESH, WRITE LEVELLING, READ PATTERN, WRITE BLOCK, READ BLOCK
"""
if self.verbose>0: print("SET MRS")
self.x393_pio_sequences.set_mrs(1) # reset DLL
if self.verbose>0: print("SET REFRESH")
......@@ -145,6 +179,13 @@ class X393McntrlTests(object):
wait_complete, # Wait for operation to complete
wlev_dqs_dly= 0x80,
norm_dqs_odly=0x78):
"""
Test write levelling mode
<wait_complete> wait write levelling operation to complete (0 - may initiate multiple PS PIO operations)
<wlev_dqs_dly> DQS output delay for write levelling mode (default 0x80)
<norm_dqs_odly> DQS output delay for normal (not write levelling) mode (default 0x78)
returns list of the read data
"""
# Set special values for DQS idelay for write leveling
self.x393_pio_sequences.wait_ps_pio_done(self.DEFAULT_STATUS_MODE,1); # not no interrupt running cycle - delays are changed immediately
self.x393_mcntrl_timing.axi_set_dqs_idelay_wlv()
......@@ -155,7 +196,7 @@ class X393McntrlTests(object):
self.x393_pio_sequences.schedule_ps_pio (# schedule software-control memory operation (may need to check FIFO status first)
self.WRITELEV_OFFSET, # input [9:0] seq_addr; # sequence start address
0, # input [1:0] page; # buffer page number
0, # input urgent; # high priority request (only for competion with other channels, wiil not pass in this FIFO)
0, # input urgent; # high priority request (only for competion with other channels, will not pass in this FIFO)
0, # input chn; # channel buffer to use: 0 - memory read, 1 - memory write
wait_complete) # `PS_PIO_WAIT_COMPLETE );# wait_complete; # Do not request a newe transaction from the scheduler until previous memory transaction is finished
......@@ -165,7 +206,7 @@ class X393McntrlTests(object):
self.x393_pio_sequences.schedule_ps_pio ( # schedule software-control memory operation (may need to check FIFO status first)
self.WRITELEV_OFFSET, # input [9:0] seq_addr; # sequence start address
1, # input [1:0] page; # buffer page number
0, # input urgent; # high priority request (only for competion with other channels, wiil not pass in this FIFO)
0, # input urgent; # high priority request (only for competion with other channels, will not pass in this FIFO)
0, # input chn; # channel buffer to use: 0 - memory read, 1 - memory write
wait_complete) # `PS_PIO_WAIT_COMPLETE );# wait_complete; # Do not request a newe transaction from the scheduler until previous memory transaction is finished
self.x393_pio_sequences.wait_ps_pio_done(self.DEFAULT_STATUS_MODE,1); # wait previous memory transaction finished before changing delays (effective immediately)
......@@ -177,11 +218,16 @@ class X393McntrlTests(object):
def test_read_pattern(self,
wait_complete): # Wait for operation to complete
"""
Test read pattern mode
<wait_complete> wait read pattern operation to complete (0 - may initiate multiple PS PIO operations)
returns list of the read data
"""
self.x393_pio_sequences.schedule_ps_pio ( # schedule software-control memory operation (may need to check FIFO status first)
self.READ_PATTERN_OFFSET, # input [9:0] seq_addr; # sequence start address
2, # input [1:0] page; # buffer page number
0, # input urgent; # high priority request (only for competion with other channels, wiil not pass in this FIFO)
0, # input urgent; # high priority request (only for competion with other channels, will not pass in this FIFO)
0, # input chn; # channel buffer to use: 0 - memory read, 1 - memory write
wait_complete) # `PS_PIO_WAIT_COMPLETE ) # wait_complete; # Do not request a newe transaction from the scheduler until previous memory transaction is finished
self.x393_pio_sequences.wait_ps_pio_done(self.DEFAULT_STATUS_MODE,1) # wait previous memory transaction finished before changing delays (effective immediately)
......@@ -189,12 +235,15 @@ class X393McntrlTests(object):
def test_write_block(self,
wait_complete): # Wait for operation to complete
"""
Test write block in PS PIO mode
<wait_complete> wait write block operation to complete (0 - may initiate multiple PS PIO operations)
"""
# write_block_buf_chn; # fill block memory - already set in set_up task
self.x393_pio_sequences.schedule_ps_pio ( # schedule software-control memory operation (may need to check FIFO status first)
self.WRITE_BLOCK_OFFSET, # input [9:0] seq_addr; # sequence start address
0, # input [1:0] page; # buffer page number
0, # input urgent; # high priority request (only for competion with other channels, wiil not pass in this FIFO)
0, # input urgent; # high priority request (only for competion with other channels, will not pass in this FIFO)
1, # input chn; # channel buffer to use: 0 - memory read, 1 - memory write
wait_complete) # `PS_PIO_WAIT_COMPLETE )# wait_complete; # Do not request a newe transaction from the scheduler until previous memory transaction is finished
# temporary - for debugging:
......@@ -202,22 +251,27 @@ class X393McntrlTests(object):
def test_read_block(self,
wait_complete): # Wait for operation to complete
"""
Test read block in PS PIO mode
<wait_complete> wait read block operation to complete (0 - may initiate multiple PS PIO operations)
returns list of the read data
"""
self.x393_pio_sequences.schedule_ps_pio ( # schedule software-control memory operation (may need to check FIFO status first)
self.READ_BLOCK_OFFSET, # input [9:0] seq_addr; # sequence start address
3, # input [1:0] page; # buffer page number
0, # input urgent; # high priority request (only for competion with other channels, wiil not pass in this FIFO)
0, # input urgent; # high priority request (only for competion with other channels, will not pass in this FIFO)
0, # input chn; # channel buffer to use: 0 - memory read, 1 - memory write
wait_complete) # wait_complete; # Do not request a newe transaction from the scheduler until previous memory transaction is finished
self.x393_pio_sequences.schedule_ps_pio ( # schedule software-control memory operation (may need to check FIFO status first)
self.READ_BLOCK_OFFSET, # input [9:0] seq_addr; # sequence start address
2, # input [1:0] page; # buffer page number
0, # input urgent; # high priority request (only for competion with other channels, wiil not pass in this FIFO)
0, # input urgent; # high priority request (only for competion with other channels, will not pass in this FIFO)
0, # input chn; # channel buffer to use: 0 - memory read, 1 - memory write
wait_complete) # wait_complete; # Do not request a newe transaction from the scheduler until previous memory transaction is finished
self.x393_pio_sequences.schedule_ps_pio ( # schedule software-control memory operation (may need to check FIFO status first)
self.READ_BLOCK_OFFSET, # input [9:0] seq_addr; # sequence start address
1, # input [1:0] page; # buffer page number
0, # input urgent; # high priority request (only for competion with other channels, wiil not pass in this FIFO)
0, # input urgent; # high priority request (only for competion with other channels, will not pass in this FIFO)
0, # input chn; # channel buffer to use: 0 - memory read, 1 - memory write
wait_complete) # wait_complete; # Do not request a newe transaction from the scheduler until previous memory transaction is finished
self.x393_pio_sequences.wait_ps_pio_done(self.DEFAULT_STATUS_MODE,1); # wait previous memory transaction finished before changing delays (effective immediately)
......@@ -231,6 +285,16 @@ class X393McntrlTests(object):
window_height, # input [15:0] window_height;
window_left, # input [15:0] window_left;
window_top): # input [15:0] window_top;
"""
Test scanline write (frame size/row increment is set in parameters)
<channel> channel number to use. Valid values: 1, 3
<extra_pages> 2-bit number of extra pages that need to stay (not to be overwritten) in the buffer
<wait_done> for operation finished
<window_width> 13-bit window width in 8-bursts (16 bytes)
<window_height> 16 bit window height
<window_left>, 13-bit window left margin in 8-bursts (16 bytes)
<window_top> 16-bit window top margin
"""
# integer startx,starty; # temporary - because of the vdt bug with integer ports
# pages_per_row= (window_width>>NUM_XFER_BITS)+((window_width[NUM_XFER_BITS-1:0]==0)?0:1);
pages_per_row= (window_width>>self.NUM_XFER_BITS)+(0,1)[(window_width & ((1<<self.NUM_XFER_BITS))-1)==0] # (window_width>>NUM_XFER_BITS)+((window_width[NUM_XFER_BITS-1:0]==0)?0:1);
......@@ -336,6 +400,18 @@ class X393McntrlTests(object):
window_height, # input [15:0] window_height;
window_left, # input [15:0] window_left;
window_top): # input [15:0] window_top;
"""
Test scanline read (frame size/row increment is set in parameters)
<channel> channel number to use. Valid values: 1, 3
<extra_pages> 2-bit number of extra pages that need to stay (not to be overwritten) in the buffer
<show_data> print read data
<window_width> 13-bit window width in 8-bursts (16 bytes)
<window_height> 16 bit window height
<window_left>, 13-bit window left margin in 8-bursts (16 bytes)
<window_top> 16-bit window top margin
Returns read data as list
"""
result=[] # will be a 2-d array
# pages_per_row= (window_width>>NUM_XFER_BITS)+((window_width[NUM_XFER_BITS-1:0]==0)?0:1);
......@@ -415,6 +491,22 @@ class X393McntrlTests(object):
tile_width, # input [ 7:0] tile_width;
tile_height, # input [ 7:0] tile_height;
tile_vstep): # input [ 7:0] tile_vstep;
"""
Test tiled mode write (frame size/row increment is set in parameters)
<channel> channel number to use. Valid values: 2, 4
<byte32> use 32-byte wide columns (0 - use 16-byte ones)
<keep_open>, do not close page between accesses (for 8 or less rows only)
<extra_pages> 2-bit number of extra pages that need to stay (not to be overwritten) in the buffer
<wait_done> wait for operation finished
<window_width> 13-bit window width in 8-bursts (16 bytes)
<window_height> 16 bit window height
<window_left>, 13-bit window left margin in 8-bursts (16 bytes)
<window_top> 16-bit window top margin
<tile_width> 6-bit tile width in 8-bursts (16 bytes) (0 -> 64)
<tile_height> 6-bit tile_height (0->64)
<tile_vstep> 6-bit tile vertical step (0->64) to control tole vertical overlap
"""
# tiles_per_row= (window_width/tile_width)+ ((window_width % tile_width==0)?0:1);
tiles_per_row= (window_width/tile_width)+ (0,1)[(window_width % tile_width)==0]
tile_rows_per_window= ((window_height-1)/tile_vstep) + 1
......@@ -525,6 +617,22 @@ class X393McntrlTests(object):
tile_width, # input [ 7:0] tile_width;
tile_height, # input [ 7:0] tile_height;
tile_vstep): # input [ 7:0] tile_vstep;
"""
Test tiled mode write (frame size/row increment is set in parameters)
<channel> channel number to use. Valid values: 2, 4
<byte32> use 32-byte wide columns (0 - use 16-byte ones)
<keep_open>, do not close page between accesses (for 8 or less rows only)
<extra_pages> 2-bit number of extra pages that need to stay (not to be overwritten) in the buffer
<show_data> print read data
<window_width> 13-bit window width in 8-bursts (16 bytes)
<window_height> 16 bit window height
<window_left>, 13-bit window left margin in 8-bursts (16 bytes)
<window_top> 16-bit window top margin
<tile_width> 6-bit tile width in 8-bursts (16 bytes) (0 -> 64)
<tile_height> 6-bit tile_height (0->64)
<tile_vstep> 6-bit tile vertical step (0->64) to control tole vertical overlap
Returns read data as a list
"""
result=[] # will be a 2-d array
# tiles_per_row= (window_width/tile_width)+ ((window_width % tile_width==0)?0:1);
tiles_per_row= (window_width/tile_width)+ (0,1)[(window_width % tile_width)==0]
......
......@@ -52,6 +52,9 @@ class X393McntrlTiming(object):
self.x393_axi_tasks=X393AxiControlStatus(debug_mode,dry_mode)
self.__dict__.update(VerilogParameters.__dict__["_VerilogParameters__shared_state"]) # Add verilog parameters to the class namespace
def get_target_phase(self):
"""
Returns previously set clock phase value
"""
return self.target_phase
def axi_set_same_delays(self, #
dq_idelay, # input [7:0] dq_idelay;
......@@ -60,7 +63,20 @@ class X393McntrlTiming(object):
dqs_odelay, # input [7:0] dqs_odelay;
dm_odelay, # input [7:0] dm_odelay;
cmda_odelay): # input [7:0] cmda_odelay;
print("SET DELAYS(0x%x,0x%x,0x%x,0x%x,0x%x,0x%x)"%(dq_idelay,dq_odelay,dqs_idelay,dqs_odelay,dm_odelay,cmda_odelay))
"""
Set I/O delays for the DDR3 memory, same delay for all signals in the same class
Each delay value is 8-bit, 5 MSB program in equal steps (=360/32 degrees each),
and 3 LSB (valid values are 0..4) add additional non-calibrated 10ps delay
<dq_idelay> input delay for DQ lines
<dq_odelay> output delay for DQ lines
<dqs_idelay> input delay for DQS lines
<dqs_odelay> output delay for DQS lines
<dm_odelay> input delay for DM lines
<cmda_odelay> output delay for DM lines
"""
if self.DEBUG_MODE > 1:
print("SET DELAYS(0x%x,0x%x,0x%x,0x%x,0x%x,0x%x)"%(dq_idelay,dq_odelay,dqs_idelay,dqs_odelay,dm_odelay,cmda_odelay))
self.axi_set_dq_idelay(dq_idelay)
self.axi_set_dq_odelay(dq_odelay)
self.axi_set_dqs_idelay(dqs_idelay)
......@@ -69,21 +85,34 @@ class X393McntrlTiming(object):
self.axi_set_cmda_odelay(cmda_odelay)
def axi_set_dqs_odelay_nominal(self):
"""
Set DQS output delays to nominal values (parameter-defined)
"""
self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE0_ODELAY + 8, (self.DLY_LANE0_ODELAY >> (8<<3)) & 0xff) # 32'hff);
self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE1_ODELAY + 8, (self.DLY_LANE1_ODELAY >> (8<<3)) & 0xff) # 32'hff);
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0);
def axi_set_dqs_idelay_nominal(self):
"""
Set DQS input delays to nominal values (parameter-defined)
"""
self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE0_IDELAY + 8, (self.DLY_LANE0_IDELAY >> (8<<3)) & 0xff) # 32'hff);
self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE1_IDELAY + 8, (self.DLY_LANE1_IDELAY >> (8<<3)) & 0xff) # 32'hff);
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0);
def axi_set_dqs_idelay_wlv(self):
"""
Set DQS input delays to values defined for the write levelling mode (parameter-defined)
"""
self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE0_IDELAY + 8, self.DLY_LANE0_DQS_WLV_IDELAY)
self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE1_IDELAY + 8, self.DLY_LANE1_DQS_WLV_IDELAY)
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0)
def axi_set_delays(self): # set all individual delays
"""
Set all DDR3 I/O delays to individual parameter-defined values
"""
for i in range(0,10): # (i=0;i<10;i=i+1) begin
self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE0_ODELAY + i, (self.DLY_LANE0_ODELAY >> (i<<3)) & 0xff) # 32'hff);
for i in range(0,9): # (i=0;i<9;i=i+1) begin
......@@ -98,42 +127,72 @@ class X393McntrlTiming(object):
def axi_set_dq_idelay(self, # sets same delay to all dq idelay
delay): # input [7:0] delay;
print("SET DQ IDELAY=0x%x"%delay)
"""
Set all DQ input delays to the same value
<delay> 8-bit (5+3) delay value to use
"""
if self.DEBUG_MODE > 1:
print("SET DQ IDELAY=0x%x"%delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE0_IDELAY, 8, delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE1_IDELAY, 8, delay)
self.x393_axi_tasks.write_contol_register (self.DLY_SET,0);# // set all delays
def axi_set_dq_odelay(self,
delay): # input [7:0] delay;
print("SET DQ ODELAY=0x%x"%delay)
"""
Set all DQ OUTput delays to the same value
<delay> 8-bit (5+3) delay value to use
"""
if self.DEBUG_MODE > 1:
print("SET DQ ODELAY=0x%x"%delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE0_ODELAY, 8, delay);
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE1_ODELAY, 8, delay);
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0); # set all delays
def axi_set_dqs_idelay(self,
delay): # input [7:0] delay;
print("SET DQS IDELAY=0x%x"%delay)
"""
Set all DQs input delays to the same value
<delay> 8-bit (5+3) delay value to use
"""
if self.DEBUG_MODE > 1:
print("SET DQS IDELAY=0x%x"%delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE0_IDELAY + 8, 1, delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE1_IDELAY + 8, 1, delay)
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0); # set all delays
def axi_set_dqs_odelay(self,
delay): # input [7:0] delay;
print("SET DQS ODELAY=0x%x"%delay)
"""
Set all DQs OUTput delays to the same value
<delay> 8-bit (5+3) delay value to use
"""
if self.DEBUG_MODE > 1:
print("SET DQS ODELAY=0x%x"%delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE0_ODELAY + 8, 1, delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE1_ODELAY + 8, 1, delay)
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0); # set all delays
def axi_set_dm_odelay (self,
delay): # input [7:0] delay;
print("SET DQM IDELAY=0x%x"%delay)
"""
Set all DM output delays to the same value
<delay> 8-bit (5+3) delay value to use
"""
if self.DEBUG_MODE > 1:
print("SET DQM IDELAY=0x%x"%delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE0_ODELAY + 9, 1, delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE1_ODELAY + 9, 1, delay)
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0) # set all delays
def axi_set_cmda_odelay(self,
delay): # input [7:0] delay;
print("SET COMMAND and ADDRESS ODELAY=0x%x"%delay)
"""
Set all command/addressoutput delays to the same value
<delay> 8-bit (5+3) delay value to use
"""
if self.DEBUG_MODE > 1:
print("SET COMMAND and ADDRESS ODELAY=0x%x"%delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_CMDA, 32, delay);
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0) # set all delays
......@@ -141,17 +200,32 @@ class X393McntrlTiming(object):
reg_addr, #input [29:0] reg_addr;
number, # input integer number;
delay): # input [7:0] delay;
"""
Set same delay to a range of I/O delay registers
<reg_addr> control register address of the first register in the range
<number> number of registers to write
<delay> 8-bit (5+3) delay value to use
"""
for i in range(0,number): # (i=0;i<number;i=i+1) begin
self.x393_axi_tasks.write_contol_register(reg_addr + i, delay) # {24'b0,delay}); // control regiter address
self.x393_axi_tasks.write_contol_register(reg_addr + i, delay) # {24'b0,delay}); // control register address
def axi_set_phase(self,
phase): # input [PHASE_WIDTH-1:0] phase;
print("SET CLOCK PHASE=0x%x"%phase)
"""
Set clock phase
<phase> 8-bit clock phase value
"""
if self.DEBUG_MODE > 1:
print("SET CLOCK PHASE=0x%x"%phase)
self.x393_axi_tasks.write_contol_register(self.LD_DLY_PHASE, phase & ((1<<self.PHASE_WIDTH)-1)) # {{(32-PHASE_WIDTH){1'b0}},phase}); // control regiter address
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0)
self.target_phase = phase
def wait_phase_shifter_ready(self):
"""
Wait until clock phase shifter is ready
"""
data=self.x393_axi_tasks.read_and_wait_status(self.MCONTR_PHY_STATUS_REG_ADDR)
while (((data & self.STATUS_PSHIFTER_RDY_MASK) == 0) or (((data ^ self.target_phase) & 0xff) != 0)):
data=self.x393_axi_tasks.read_and_wait_status(self.MCONTR_PHY_STATUS_REG_ADDR)
......@@ -159,10 +233,18 @@ class X393McntrlTiming(object):
def axi_set_wbuf_delay(self,
delay): # input [3:0] delay;
print("SET WBUF DELAY=0x%x"%delay)
"""
Set write to buffer latency
<delay> 4-bit write to buffer signal delay (in mclk clock cycles)
"""
if self.DEBUG_MODE > 1:
print("SET WBUF DELAY=0x%x"%delay)
self.x393_axi_tasks.write_contol_register(self.MCONTR_PHY_16BIT_ADDR+self.MCONTR_PHY_16BIT_WBUF_DELAY, delay & 0xf) # {28'h0, delay});
#set dq /dqs tristate on/off patterns
def axi_set_tristate_patterns(self):
"""
Set sequencer patterns for the tristate ON/OFF (defined by parameters)
"""
# may fail if some of the parameters used have undefined width
delays=concat((0,16), # {16'h0,
(self.DQSTRI_LAST, getParWidth(self.DQSTRI_LAST__TYPE)), # DQSTRI_LAST,
......@@ -170,10 +252,15 @@ class X393McntrlTiming(object):
(self.DQTRI_LAST, getParWidth(self.DQTRI_LAST_FIRST__TYPE)), # DQTRI_LAST,
(self.DQTRI_FIRST, getParWidth(self.DQTRI_FIRST__TYPE)) # DQTRI_FIRST});
)
print("SET TRISTATE PATTERNS, combined delays=0x%x"%delays)
if self.DEBUG_MODE > 1:
print("SET TRISTATE PATTERNS, combined delays=0x%x"%delays)
self.x393_axi_tasks.write_contol_register(self.MCONTR_PHY_16BIT_ADDR +self.MCONTR_PHY_16BIT_PATTERNS_TRI, delays) # DQSTRI_LAST, DQSTRI_FIRST, DQTRI_LAST, DQTRI_FIRST});
def axi_set_dqs_dqm_patterns(self):
print("SET DQS+DQM PATTERNS")
"""
Set sequencer patterns for the DQ lines ON/OFF (defined by parameters)
"""
if self.DEBUG_MODE > 1:
print("SET DQS+DQM PATTERNS")
# set patterns for DM (always 0) and DQS - always the same (may try different for write lev.)
self.x393_axi_tasks.write_contol_register(self.MCONTR_PHY_16BIT_ADDR + self.MCONTR_PHY_16BIT_PATTERNS, 0x55) # 32'h0055);
......@@ -45,8 +45,12 @@ class X393Mem(object):
def __init__(self, debug_mode=1,dry_mode=True):
self.DEBUG_MODE=debug_mode
self.DRY_MODE=dry_mode
def write_mem (self,addr, data):
"""
Write 32-bit word to physical memory
<addr> - physical byte address
<data> - 32-bit data to write
"""
if self.DRY_MODE:
print ("write_mem(0x%x,0x%x)"%(addr,data))
return
......@@ -73,6 +77,10 @@ class X393Mem(object):
'''
def read_mem (self,addr):
'''
Read 32-bit word from physical memory
<addr> - physical byte address
'''
if self.DRY_MODE:
print ("read_mem(0x%x)"%(addr))
return
......@@ -89,93 +97,36 @@ class X393Mem(object):
return d
# mm.close() #probably not needed with "with"
'''
Read/write slave AXI using byte addresses relative to the AXI memory reagion
Read/write slave AXI using byte addresses relative to the AXI memory region
'''
def axi_write_single(self,addr,data):
"""
Write 32-bit word to the slave AXI address range
<addr> - physical byte address relative to the slave AXI memory region
<data> - 32-bit data to write
"""
self.write_mem(self.AXI_SLAVE0_BASE+addr,data)
def axi_read_addr(self,addr):
"""
Read 32-bit word from the slave AXI address range
<addr> - physical byte address relative to slave AXI AXI memory region
"""
return self.read_mem(self.AXI_SLAVE0_BASE+addr)
'''
Read/write slave AXI using 32-bit word addresses (same as in Verilog code)
'''
def axi_write_single_w(self,addr,data):
"""
Write 32-bit word to the slave AXI address range, using 32-word address
<addr> - 32-bit word (register) address relative to the slave AXI memory region
<data> - 32-bit data to write
"""
self.axi_write_single(addr<<2,data)
def axi_read_addr_w(self,addr):
"""
Read 32-bit word from the slave AXI address range, using 32-word address
<addr> - 32-bit word (register) address relative to the slave AXI memory region
"""
return self.axi_read_addr(addr<<2)
'''
task axi_write_addr_data;
input [11:0] id;
input [31:0] addr;
input [31:0] data;
input [ 3:0] len;
input [ 1:0] burst;
input data_en; // if 0 - do not send data, only address
input [ 3:0] wstrb;
input last;
reg data_sent;
// wire data_sent_d;
// assign #(.1) data_sent_d= data_sent;
begin
wait (!CLK && AW_READY);
AWID_IN_r <= id;
AWADDR_IN_r <= addr;
AWLEN_IN_r <= len;
AWSIZE_IN_r <= 3'b010;
AWBURST_IN_r <= burst;
AW_SET_CMD_r <= 1'b1;
if (data_en && W_READY) begin
WID_IN_r <= id;
WDATA_IN_r <= data;
WSTRB_IN_r <= wstrb;
WLAST_IN_r <= last;
W_SET_CMD_r <= 1'b1;
data_sent <= 1'b1;
end else begin
data_sent <= 1'b0;
end
DEBUG1 <=1'b1;
wait (CLK);
DEBUG1 <=1'b0;
AWID_IN_r <= 'hz;
AWADDR_IN_r <= 'hz;
AWLEN_IN_r <= 'hz;
AWSIZE_IN_r <= 'hz;
AWBURST_IN_r <= 'hz;
AW_SET_CMD_r <= 1'b0;
DEBUG2 <=1'b1;
if (data_sent) begin
WID_IN_r <= 'hz;
WDATA_IN_r <= 'hz;
WSTRB_IN_r <= 'hz;
WLAST_IN_r <= 'hz;
W_SET_CMD_r <= 1'b0;
end
// Now sent data if it was not sent simultaneously with the address
if (data_en && !data_sent) begin
DEBUG3 <=1'b1;
wait (!CLK && W_READY);
DEBUG3 <=1'b0;
WID_IN_r <= id;
WDATA_IN_r <= data;
WSTRB_IN_r <= wstrb;
WLAST_IN_r <= last;
W_SET_CMD_r <= 1'b1;
wait (CLK);
DEBUG3 <=1'bx;
WID_IN_r <= 'hz;
WDATA_IN_r <= 'hz;
WSTRB_IN_r <= 'hz;
WLAST_IN_r <= 'hz;
W_SET_CMD_r <= 1'b0;
end
DEBUG2 <=1'b0;
#0.1;
data_sent <= 1'b0;
#0.1;
end
endtask
'''
\ No newline at end of file
......@@ -70,6 +70,15 @@ class X393PIOSequences(object):
urgent, # input urgent; // high priority request (only for competion wityh other channels, wiil not pass in this FIFO)
chn, # input chn; // channel buffer to use: 0 - memory read, 1 - memory write
wait_complete): # input wait_complete; // Do not request a newe transaction from the scheduler until previous memory transaction is finished
"""
Schedule PS PIO memory transaction
<seq_addr> 10-bit sequence start address
<page> buffer page address to use (0..3)
<urgent> high priority request (only for competition with other channels,
will not pass other commands in this module FIFO)
<chn> sub-channel to use: 0 - memory read, 1 - memory write
<wait_complete> Do not request a new transaction from the scheduler until previous memory transaction is finished
"""
self.write_contol_register(self.MCNTRL_PS_ADDR + self.MCNTRL_PS_CMD,
# {17'b0,
((0,1)[wait_complete]<<14) |
......@@ -81,6 +90,12 @@ class X393PIOSequences(object):
def wait_ps_pio_ready(self, #; // wait PS PIO module can accept comamnds (fifo half empty)
mode, # input [1:0] mode;
sync_seq): # input sync_seq; // synchronize sequences
"""
Wait until PS PIO module can accept comamnds (fifo half empty)
<mode> status mode (0..3) - see 'help program_status'
<synq_seq> status sequence number - see 'help program_status'
"""
self.x393_axi_tasks.wait_status_condition (
self.MCNTRL_PS_STATUS_REG_ADDR,
self.MCNTRL_PS_ADDR + self.MCNTRL_PS_STATUS_CNTRL,
......@@ -93,6 +108,11 @@ class X393PIOSequences(object):
def wait_ps_pio_done(self, # // wait PS PIO module has no pending/running memory transaction
mode, # input [1:0] mode;
sync_seq): # input sync_seq; // synchronize sequences
"""
Wait PS PIO module has no pending/running memory transaction
<mode> status mode (0..3) - see 'help program_status'
<synq_seq> status sequence number - see 'help program_status'
"""
self.x393_axi_tasks.wait_status_condition (
self.MCNTRL_PS_STATUS_REG_ADDR,
self.MCNTRL_PS_ADDR + self.MCNTRL_PS_STATUS_CNTRL,
......@@ -119,6 +139,23 @@ class X393PIOSequences(object):
buf_rd, # input buf_rd; // connect to external buffer (but only if not paused)
nop, # input nop; // add NOP after the current command, keep other data
buf_rst): # input buf_rst; // connect to external buffer (but only if not paused)
"""
Encode data into memory controller sequencer word
<addr> 15-bit row/column adderss
<bank> 3-bit bank address
<rcw> 3-bit combined {RAS,CAS,WE}, positive logic
<odt_en> enable ODT
<cke> disable CKE
<sel> first(0)/second(1) half-cycle, other half-cycle will be NOP (cke+odt applicable to both)
<dq_en> enable (turn tristate off) DQ lines (internal timing sequencer for 0->1 and 1->0)
<dqs_en> enable (turn tristate off) DQS lines (internal timing sequencer for 0->1 and 1->0)
<dqs_toggle> enable toggle DQS lines according to the pattern
<dci> DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
<buf_wr> generate external buffer write/address increment
<buf_rd> generate external buffer read/address increment
<nop> add NOP after the current command, keep other data
<buf_rst> reset external buffer page address to 0, increment page number
"""
return (
((addr & 0x7fff) << 17) | # addr[14:0], // 15-bit row/column adderss
((bank & 0x7) << 14) | # bank [2:0], // bank
......@@ -149,7 +186,23 @@ class X393PIOSequences(object):
dci, # input dci; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
buf_wr, # input buf_wr; // connect to external buffer (but only if not paused)
buf_rd, # input buf_rd; // connect to external buffer (but only if not paused)
buf_rst): #input buf_rst; // connect to external buffer (but only if not paused)
buf_rst): #input buf_rst; // connect to external buffer (but only if not paused)
"""
Encode skip cycles command into memory controller sequencer word. NOP will be present on RCW(RAS/CAS/WE) lines
<skip> 10-bit number of cycles to skip minus 1
<done> 10-bit number of cycles to skip minus 1
<bank> 3-bit bank address
<odt_en> enable ODT
<cke> disable CKE
<sel> first(0)/second(1) half-cycle, other half-cycle will be NOP (cke+odt applicable to both)
<dq_en> enable (turn tristate off) DQ lines (internal timing sequencer for 0->1 and 1->0)
<dqs_en> enable (turn tristate off) DQS lines (internal timing sequencer for 0->1 and 1->0)
<dqs_toggle> enable toggle DQS lines according to the pattern
<dci> DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
<buf_wr> generate external buffer write/address increment
<buf_rd> generate external buffer read/address increment
<buf_rst> reset external buffer page address to 0, increment page number
"""
return self.func_encode_cmd (
((0,1)[done] << self.CMD_PAUSE_BITS) | # {{14-CMD_DONE_BIT{1'b0}}, done,
(skip & ((1 << self.CMD_PAUSE_BITS)-1)), # skip[CMD_PAUSE_BITS-1:0]}, // 15-bit row/column address
......@@ -197,6 +250,39 @@ class X393PIOSequences(object):
# 2'b01 - 4 or 8 on-the-fly by A12
# 2'b10 - fixed BL4 (chop)
# 2'b11 - reserved
"""
Encode DDR3 MR0 register data
<pd> precharge power down 0 - dll off (slow exit), 1 - dll on (fast exit)
<wr> write recovery:
000: 16
001: 5
010: 6
011: 7
100: 8
101: 10
110: 12
111: 14
<dll_rst> 1 - dll reset (self clearing bit)
<cl> CAS latency (>=15ns):
0000: reserved
0010: 5
0100: 6
0110: 7
1000: 8
1010: 9
1100: 10
1110: 11
0001: 12
0011: 13
0101: 14
<bt> read burst type: 0 sequential (nibble), 1 - interleaved
<bl> burst length:
00 - fixed BL8
01 - 4 or 8 on-the-fly by A12
10 - fixed BL4 (chop)
11 - reserved
"""
return concat((
(0,3), # 3'b0,
(0,self.ADDRESS_NUMBER-13), # {ADDRESS_NUMBER-13{1'b0}},
......@@ -231,6 +317,30 @@ class X393PIOSequences(object):
# 2'b10 - AL=CL-2
# 2'b11 - reserved
dll): #input dll; # 0 - DLL enabled (normal), 1 - DLL disabled
"""
Encode DDR3 MR1 register data
<qoff> output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
<tdqs> termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
<rtt> on-die termination resistance:
000 - disabled
001 - RZQ/4 (60 Ohm)
010 - RZQ/2 (120 Ohm)
011 - RZQ/6 (40 Ohm)
100 - RZQ/12(20 Ohm)
101 - RZQ/8 (30 Ohm)
11x - reserved
<wlev> write leveling mode
<ods> output drive strength:
00 - RZQ/6 - 40 Ohm
01 - RZQ/7 - 34 Ohm
1x - reserved
<al> additive latency:
00 - disabled (AL=0)
01 - AL=CL-1;
10 - AL=CL-2
11 - reserved
<dll> 0 - DLL enabled (normal), 1 - DLL disabled
"""
return concat (( # ddr3_mr1 = {
(1,3), # 3'h1,
(0, self.ADDRESS_NUMBER-13), # {ADDRESS_NUMBER-13{1'b0}},
......@@ -263,6 +373,24 @@ class X393PIOSequences(object):
# 3'b100 9CK (1.071ns <= tCK < 1.25ns)
# 3'b101 10CK (0.938ns <= tCK < 1.071ns)
# 3'b11x reserved
"""
Encode DDR3 MR2 register data
<rtt_wr> Dynamic ODT :
00 - disabled
01 - RZQ/4 = 60 Ohm
10 - RZQ/2 = 120 Ohm
11 - reserved
<srt> Self-refresh temperature 0 - normal (0-85C), 1 - extended (<=95C)
<asr> Auto self-refresh 0 - disabled (manual), 1 - enabled (auto)
<cwl> CAS write latency:
000 5CK ( tCK >= 2.5ns)
001 6CK (1.875ns <= tCK < 2.5ns)
010 7CK (1.5ns <= tCK < 1.875ns)
011 8CK (1.25ns <= tCK < 1.5ns)
100 9CK (1.071ns <= tCK < 1.25ns)
101 10CK (0.938ns <= tCK < 1.071ns)
11x reserved
"""
return concat ((
(2,3), # 3'h2,
(0, self.ADDRESS_NUMBER-11), # {ADDRESS_NUMBER-11{1'b0}},
......@@ -278,6 +406,13 @@ class X393PIOSequences(object):
mpr_rf): # input [1:0] mpr_rf; # MPR read function:
# 2'b00: predefined pattern 0101...
# 2'b1x, 2'bx1 - reserved
"""
Encode DDR3 MR3 register data
<mpr> MPR mode: 0 - normal, 1 - dataflow from MPR
<mpr_rf> MPR read function:
00: predefined pattern 0101...
1x, 2'bx1 - reserved
"""
return concat((
(3,3), # 3'h3,
(0,self.ADDRESS_NUMBER), # {ADDRESS_NUMBER-3{1'b0}},
......@@ -290,6 +425,12 @@ class X393PIOSequences(object):
def enable_reset_ps_pio(self, #; // control reset and enable of the PS PIO channel;
en, # input en;
rst): #input rst;
"""
Enable/disable and reset PS PIO channel
<en> 1 - enable, 0 - disable (only influences request for arbitration, started transactions will finish if disabled)
<rst> 1 - reset active, 0 - reset off
"""
self.write_contol_register(self.MCNTRL_PS_ADDR + self.MCNTRL_PS_EN_RST,
((0,1)[en]<<1) | #{30'b0,en,
(1,0)[rst]) #~rst});
......@@ -299,6 +440,12 @@ class X393PIOSequences(object):
ba, # input [ 2:0] ba;
ra, # input [14:0] ra;
ca): #input [ 9:0] ca;
"""
Setup read block sequence at parameter defined address in the sequencer memory
<ba> 3-bit memory bank address
<ra> 15-bit memory row address
<ca> 10-bit memory column address
"""
cmd_addr = self.MCONTR_CMD_WR_ADDR + self.READ_BLOCK_OFFSET
# activate
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
......@@ -363,6 +510,13 @@ class X393PIOSequences(object):
ba, # input[2:0]ba;
ra, # input[14:0]ra;
ca): # input[9:0]ca;
"""
Setup write block sequence at parameter defined address in the sequencer memory
<ba> 3-bit memory bank address
<ra> 15-bit memory row address
<ca> 10-bit memory column address
"""
cmd_addr = self.MCONTR_CMD_WR_ADDR + self.WRITE_BLOCK_OFFSET
# activate
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
......@@ -445,6 +599,11 @@ class X393PIOSequences(object):
# Set MR3, read nrep*8 words, save to buffer (port0). No ACTIVATE/PRECHARGE are needed/allowed
def set_read_pattern (self,
nrep): # input integer nrep;
"""
Setup read pattern sequence at parameter defined address in the sequencer memory
<nrep> number of times pattern burst is read
"""
cmd_addr = self.MCONTR_CMD_WR_ADDR + self.READ_PATTERN_OFFSET
mr3_norm = self.func_ddr3_mr3(
0, # 1'h0, // mpr; // MPR mode: 0 - normal, 1 - dataflow from MPR
......@@ -526,6 +685,10 @@ class X393PIOSequences(object):
def set_write_lev(self,
nrep): #input[CMD_PAUSE_BITS-1:0]nrep;
"""
Setup write levelling sequence at parameter defined address in the sequencer memory
<nrep> number of times write levelling burst is repeated
"""
dqs_low_rpt = 8
nrep_minus_1 = nrep - 1;
mr1_norm = self.func_ddr3_mr1(
......@@ -593,6 +756,13 @@ class X393PIOSequences(object):
t_rfc, # input[9:0]t_rfc; # =50 for tCK=2.5ns
t_refi, # input[7:0]t_refi; # 48/97 for normal, 8 - for simulation
en_refresh=0):
"""
Setup refresh sequence at parameter defined address in the sequencer memory
<t_rfc> tRFC =50 for tCK=2.5ns
<t_refi> tREFI 48/97 for hardware, 8 - for simulation
<en_refresh> enable refresh immediately
"""
cmd_addr = self.MCONTR_CMD_WR_ADDR + self.REFRESH_OFFSET
# 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)
......@@ -618,6 +788,10 @@ class X393PIOSequences(object):
def set_mrs(self, # will also calibrate ZQ
reset_dll): # input reset_dll;
"""
Setup sequence (at paramter-defined adderss) to write MR0, MR1, MR2 and MR3 mode registers of DDR3 memory
<reset_dll> reset memory DLL when running this sequence
"""
mr0 = self.func_ddr3_mr0(
0, # 1'h0, # pd; # precharge power down 0 - dll off (slow exit), 1 - dll on (fast exit)
2, # 3'h2, # [2:0] wr; # write recovery (encode ceil(tWR/tCK)) # 3'b010: 6
......
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