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,6 +61,15 @@ 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;
"""
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)
......@@ -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)
......
This diff is collapsed.
This diff is collapsed.
......@@ -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
This diff is collapsed.
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