Commit eba342eb authored by Andrey Filippov's avatar Andrey Filippov

continue with python hardware test code

parent 63ff2819
eclipse.preferences.version=1
encoding/import_verilog_parameters.py=utf-8
encoding/test1.py=utf-8
encoding/test2.py=utf-8
......@@ -29,7 +29,10 @@ __version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
'''
~/git/x393/py393$ ./test1.py -vv -f/home/andrey/git/x393/system_defines.vh -f /home/andrey/git/x393/includes/x393_parameters.vh /home/andrey/git/x393/includes/x393_localparams.vh -pNEWPAR=\'h3ff -c write_mem 0x377 25 -c read_mem 0x3ff -i
'''
import sys
import os
......@@ -39,6 +42,8 @@ from argparse import RawDescriptionHelpFormatter
from import_verilog_parameters import ImportVerilogParameters
from import_verilog_parameters import VerilogParameters
import x393_axi_control_status
import x393_mem
__all__ = []
__version__ = 0.1
__date__ = '2015-03-01'
......@@ -47,7 +52,7 @@ __updated__ = '2015-03-01'
DEBUG = 1
TESTRUN = 0
PROFILE = 0
callableTasks={}
class CLIError(Exception):
#Generic exception to raise and log different fatal errors.
def __init__(self, msg):
......@@ -57,8 +62,56 @@ class CLIError(Exception):
return self.msg
def __unicode__(self):
return self.msg
'''
for name in x393_mem.X393Mem.__dict__:
if hasattr((x393_mem.X393Mem.__dict__[name]), '__call__') and not (name[0]=='_'):
func_args=x393_mem.X393Mem.__dict__[name].func_code.co_varnames[1:x393_mem.X393Mem.__dict__[name].func_code.co_argcount]
# print (name+": "+str(x393_mem.X393Mem.__dict__[name]))
# print ("args="+str(func_args))
print (name+": "+str(func_args))
'''
def extractTasks(obj,inst):
for name in obj.__dict__:
if hasattr((obj.__dict__[name]), '__call__') and not (name[0]=='_'):
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}
def execTask(commandLine):
result=None
cmdList=commandLine #.split()
try:
funcName=cmdList[0]
funcArgs=cmdList[1:]
except:
return None
for i,arg in enumerate(funcArgs):
try:
funcArgs[i]=eval(arg) # Try parsing parameters as numbers, if possible
except:
pass
# result = callableTasks[funcName]['func'](callableTasks[funcName]['inst'],*funcArgs)
try:
result = callableTasks[funcName]['func'](callableTasks[funcName]['inst'],*funcArgs)
except Exception as e:
print ('Error while executing %s %s'%(funcName,str(funcArgs)))
try:
funcFArgs= callableTasks[funcName]['args']
except:
print ("Unknown task: %s"%(funcName))
return None
sFuncArgs=""
if funcFArgs:
sFuncArgs+='<'+str(funcFArgs[0])+'>'
for a in funcFArgs[1:]:
sFuncArgs+=' <'+str(a)+'>'
print ("Usage:\n%s %s"%(funcName,sFuncArgs))
print ("exception message:"+str(e))
return result
def hx(obj):
try:
return "0x%x"%obj
except:
return str(obj)
def main(argv=None): # IGNORE:C0111
'''Command line options.'''
......@@ -97,13 +150,19 @@ USAGE
parser = ArgumentParser(description=program_license, formatter_class=RawDescriptionHelpFormatter)
parser.add_argument("-v", "--verbose", dest="verbose", action="count", help="set verbosity level [default: %(default)s]")
parser.add_argument('-V', '--version', action='version', version=program_version_message)
parser.add_argument( dest="paths", help="Verilog include files with parameter definitions [default: %(default)s]", metavar="path", nargs='*')
# parser.add_argument( dest="paths", help="Verilog include files with parameter definitions [default: %(default)s]", metavar="path", nargs='*')
parser.add_argument("-f", "--icludeFile", dest="paths", action="append", help="Verilog include files with parameter definitions [default: %(default)s]", metavar="path", nargs='*')
parser.add_argument("-d", "--define", dest="defines", action="append", help="Define macro(s)" )
parser.add_argument("-p", "--parameter", dest="parameters", action="append", help="Define parameter(s) as name=value" )
parser.add_argument("-c", "--command", dest="commands", action="append", help="execute command" , nargs='*')
parser.add_argument("-i", "--interactive", dest="interactive", action="store_true", help="enter interactive mode [default: %(default)s]")
# Process arguments
args = parser.parse_args()
paths = args.paths
# paths = args.paths
paths=[]
for group in args.paths:
paths+=group
verbose = args.verbose
if args.defines:
for predef in args.defines:
......@@ -131,8 +190,13 @@ USAGE
sys.stderr.write(indent + " for help use --help")
return 2
# Take out from the try/except for debugging
ivp= ImportVerilogParameters(preParameters,preDefines)
ivp= ImportVerilogParameters(preParameters,preDefines)
if verbose > 3: print ('paths='+str(paths))
if verbose > 3: print ('defines='+str(args.defines))
if verbose > 3: print ('parameters='+str(args.parameters))
if verbose > 3: print ('comamnds='+str(args.commands))
for path in paths:
if verbose > 2: print ('path='+str(path))
### do something with inpath ###
ivp.readParameterPortList(path)
parameters=ivp.getParameters()
......@@ -152,13 +216,93 @@ USAGE
print("vpars.VERBOSE__TYPE="+str(vpars.VERBOSE__TYPE))
print("vpars.VERBOSE__RAW="+str(vpars.VERBOSE__RAW))
print (VerilogParameters.__dict__)
if verbose > 3: print (VerilogParameters.__dict__)
vpars1=VerilogParameters()
print("vpars1.VERBOSE="+str(vpars1.VERBOSE))
print("vpars1.VERBOSE__TYPE="+str(vpars1.VERBOSE__TYPE))
print("vpars1.VERBOSE__RAW="+str(vpars1.VERBOSE__RAW))
if verbose > 3: print("vpars1.VERBOSE="+str(vpars1.VERBOSE))
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)
x393tasks=x393_axi_control_status.X393AxiControlStatus(verbose,True)
'''
print ("----------------------")
print("x393_mem.__dict__="+str(x393_mem.__dict__))
print ("----------------------")
print("x393mem.__dict__="+str(x393mem.__dict__))
print ("----------------------")
print("x393_mem.X393Mem.__dict__="+str(x393_mem.X393Mem.__dict__))
'''
if verbose > 3:
print ("----------------------")
for name in x393_mem.X393Mem.__dict__:
if hasattr((x393_mem.X393Mem.__dict__[name]), '__call__') and not (name[0]=='_'):
func_args=x393_mem.X393Mem.__dict__[name].func_code.co_varnames[1:x393_mem.X393Mem.__dict__[name].func_code.co_argcount]
print (name+": "+str(func_args))
extractTasks(x393_mem.X393Mem,x393mem)
extractTasks(x393_axi_control_status.X393AxiControlStatus,x393tasks)
if verbose > 3:
funcName="read_mem"
funcArgs=[0x377,123]
print ('==== testing function : '+funcName+str(funcArgs)+' ====')
#execTask(commandLine)
try:
callableTasks[funcName]['func'](callableTasks[funcName]['inst'],*funcArgs)
except Exception as e:
print ('Error while executing %s'%funcName)
funcFArgs= callableTasks[funcName]['args']
sFuncArgs=""
if funcFArgs:
sFuncArgs+='<'+str(funcFArgs[0])+'>'
for a in funcFArgs[1:]:
sFuncArgs+=' <'+str(a)+'>'
print ("Usage:\n%s %s"%(funcName,sFuncArgs))
print ("exception message:"+str(e))
for cmdLine in args.commands:
print ('Running task: '+str(cmdLine))
rslt= execTask(cmdLine)
print (' Result: '+str(rslt))
'''
#TODO: use readline
'''
if (args.interactive):
line =""
while True:
line=raw_input('x393--> ').strip()
if not line:
print ('Use "quit" to exit, "help" - for help')
elif line == 'quit':
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)+'>'
print ("Usage: %s %s"%(name,sFuncArgs))
print ('\n"parameters" and "defines" list known defined parameters and macros')
elif line == 'parameters':
parameters=ivp.getParameters()
for par in parameters:
try:
print (par+" = "+hex(parameters[par][0])+" (type = "+parameters[par][1]+" raw = "+parameters[par][2]+")")
except:
print (par+" = "+str(parameters[par][0])+" (type = "+parameters[par][1]+" raw = "+parameters[par][2]+")")
elif (line == 'defines') or (line == 'macros'):
defines= ivp.getDefines()
for macro in defines:
print ("`"+macro+": "+defines[macro])
else:
cmdLine=line.split()
rslt= execTask(cmdLine)
print (' Result: '+hx(rslt))
#http://stackoverflow.com/questions/11781265/python-using-getattr-to-call-function-with-variable-parameters
#*getattr(foo,bar)(*params)
return 0
if __name__ == "__main__":
......
from __future__ import print_function
'''
# Copyright (C) 2015, Elphel.inc.
# Memory read/write functions
# Methods that mimic Verilog tasks used for simulation
# 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
......@@ -27,24 +28,61 @@ __version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
from __future__ import print_function
#import sys
#import x393_mem
from import_verilog_parameters import VerilogParameters
from x393_mem import X393Mem
#MCNTRL_TEST01_CHN4_STATUS_CNTRL=0
def hx(obj):
try:
return "0x%x"%obj
except:
return str(obj)
'''
Simulate Verilog concatenation. Input list tuple of items, each being a pair of (value, width)
'''
def concat(items):
val=0
width=0
for vw in reversed(items):
v=vw[0]
if vw[1]==1:
v=(0,1)[v] # So True/False will also work, not juet o/1
val |= (v & ((1 << vw[1])-1))<<width
width += vw[1]
return (val,width)
def bits(val,field):
try:
high=field[0]
low=field[1]
if low > high:
low,high=high,low
except:
low=field+0 # will be error if not a number
high=low
return (val >> low) & ((1 << (high-low+1))-1)
class X393AxiControlStatus(object):
DRY_MODE= False # True
DRY_MODE= True # True
DEBUG_MODE=1
# vpars=None
x393_mem=None
target_phase=0 # TODO: set!
def __init__(self, debug_mode=1,dry_mode=False):
def __init__(self, debug_mode=1,dry_mode=True):
self.DEBUG_MODE=debug_mode
self.DRY_MODE=dry_mode
# self.vpars=VerilogParameters()
self.x393_mem=X393Mem(debug_mode,dry_mode)
self.__dict__.update(VerilogParameters.__dict__) # Add verilog parameters to the class namespace
# print ("+++++++++++++++ self.__dict__ ++++++++++++++++++++++++++")
# print (self.__dict__)
# print ("+++++++++++++++ VerilogParameters.__dict__ ++++++++++++++++++++++++++")
# print (VerilogParameters.__dict__)
# self.__dict__.update(VerilogParameters.__dict__) # Add verilog parameters to the class namespace
self.__dict__.update(VerilogParameters.__dict__["_VerilogParameters__shared_state"]) # Add verilog parameters to the class namespace
# print ("+++++++++++++++ self.__dict__ ++++++++++++++++++++++++++")
# print (self.__dict__)
'''
Maybe import parameters into the module, not class namespace to use directly, w/o self. ?
# __dict__.update(VerilogParameters.__dict__) # Add verilog parameters to the class namespace
......@@ -71,26 +109,33 @@ class X393AxiControlStatus(object):
data=self.read_and_wait_status(status_address)
while (((data >> self.STATUS_SEQ_SHFT) ^ seq_num) & 0x30) !=0:
data=self.read_and_wait_status(status_address)
if self.DRY_MODE: break
match = (((data ^ pattern) & mask & 0x3ffffff)==0)
if invert_match:
match = not match
if self.DRY_MODE: break
def wait_phase_shifter_ready(self):
data=self.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.read_and_wait_status(self.MCONTR_PHY_STATUS_REG_ADDR)
if self.DRY_MODE: break
def read_all_status(self):
print ("MCONTR_PHY_STATUS_REG_ADDR: 0x%x"%(self.read_and_wait_status(self.MCONTR_PHY_STATUS_REG_ADDR)))
print ("MCONTR_TOP_STATUS_REG_ADDR: 0x%x"%(self.read_and_wait_status(self.MCONTR_TOP_STATUS_REG_ADDR)))
print ("MCNTRL_PS_STATUS_REG_ADDR: 0x%x"%(self.read_and_wait_status(self.MCNTRL_PS_STATUS_REG_ADDR)))
print ("MCNTRL_SCANLINE_STATUS_REG_CHN1_ADDR:0x%x"%(self.read_and_wait_status(self.MCNTRL_SCANLINE_STATUS_REG_CHN1_ADDR)))
print ("MCNTRL_SCANLINE_STATUS_REG_CHN3_ADDR:0x%x"%(self.read_and_wait_status(self.MCNTRL_SCANLINE_STATUS_REG_CHN3_ADDR)))
print ("MCNTRL_TILED_STATUS_REG_CHN2_ADDR: 0x%x"%(self.read_and_wait_status(self.MCNTRL_TILED_STATUS_REG_CHN2_ADDR)))
print ("MCNTRL_TILED_STATUS_REG_CHN4_ADDR: 0x%x"%(self.read_and_wait_status(self.MCNTRL_TILED_STATUS_REG_CHN4_ADDR)))
print ("MCNTRL_TEST01_STATUS_REG_CHN1_ADDR: 0x%x"%(self.read_and_wait_status(self.MCNTRL_TEST01_STATUS_REG_CHN1_ADDR)))
print ("MCNTRL_TEST01_STATUS_REG_CHN2_ADDR: 0x%x"%(self.read_and_wait_status(self.MCNTRL_TEST01_STATUS_REG_CHN2_ADDR)))
print ("MCNTRL_TEST01_STATUS_REG_CHN3_ADDR: 0x%x"%(self.read_and_wait_status(self.MCNTRL_TEST01_STATUS_REG_CHN3_ADDR)))
print ("MCNTRL_TEST01_STATUS_REG_CHN4_ADDR: 0x%x"%(self.read_and_wait_status(self.MCNTRL_TEST01_STATUS_REG_CHN4_ADDR)))
# print (self.__dict__)
# for name in self.__dict__:
# print (name+": "+str(name=='MCONTR_PHY_STATUS_REG_ADDR'))
# print (self.__dict__['MCONTR_PHY_STATUS_REG_ADDR'])
print ("MCONTR_PHY_STATUS_REG_ADDR: %s"%(hx(self.read_and_wait_status(self.MCONTR_PHY_STATUS_REG_ADDR))))
print ("MCONTR_TOP_STATUS_REG_ADDR: %s"%(hx(self.read_and_wait_status(self.MCONTR_TOP_STATUS_REG_ADDR))))
print ("MCNTRL_PS_STATUS_REG_ADDR: %s"%(hx(self.read_and_wait_status(self.MCNTRL_PS_STATUS_REG_ADDR))))
print ("MCNTRL_SCANLINE_STATUS_REG_CHN1_ADDR:%s"%(hx(self.read_and_wait_status(self.MCNTRL_SCANLINE_STATUS_REG_CHN1_ADDR))))
print ("MCNTRL_SCANLINE_STATUS_REG_CHN3_ADDR:%s"%(hx(self.read_and_wait_status(self.MCNTRL_SCANLINE_STATUS_REG_CHN3_ADDR))))
print ("MCNTRL_TILED_STATUS_REG_CHN2_ADDR: %s"%(hx(self.read_and_wait_status(self.MCNTRL_TILED_STATUS_REG_CHN2_ADDR))))
print ("MCNTRL_TILED_STATUS_REG_CHN4_ADDR: %s"%(hx(self.read_and_wait_status(self.MCNTRL_TILED_STATUS_REG_CHN4_ADDR))))
print ("MCNTRL_TEST01_STATUS_REG_CHN1_ADDR: %s"%(hx(self.read_and_wait_status(self.MCNTRL_TEST01_STATUS_REG_CHN1_ADDR))))
print ("MCNTRL_TEST01_STATUS_REG_CHN2_ADDR: %s"%(hx(self.read_and_wait_status(self.MCNTRL_TEST01_STATUS_REG_CHN2_ADDR))))
print ("MCNTRL_TEST01_STATUS_REG_CHN3_ADDR: %s"%(hx(self.read_and_wait_status(self.MCNTRL_TEST01_STATUS_REG_CHN3_ADDR))))
print ("MCNTRL_TEST01_STATUS_REG_CHN4_ADDR: %s"%(hx(self.read_and_wait_status(self.MCNTRL_TEST01_STATUS_REG_CHN4_ADDR))))
def program_status(self,
base_addr, # input [29:0] base_addr;
......@@ -227,14 +272,433 @@ class X393AxiControlStatus(object):
0, # 1'b0, // nop
buf_rst) #
def func_ddr3_mr0(self, # ; # function [ADDRESS_NUMBER+2:0]
pd, # input pd; // precharge power down 0 - dll off (slow exit), 1 - dll on (fast exit)
wr, # input [2:0] wr; // write recovery:
# 3'b000: 16
# 3'b001: 5
# 3'b010: 6
# 3'b011: 7
# 3'b100: 8
# 3'b101: 10
# 3'b110: 12
# 3'b111: 14
dll_rst, # input dll_rst; // 1 - dll reset (self clearing bit)
cl, # input [3:0] 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, #input bt; # read burst type: 0 sequential (nibble), 1 - interleaved
bl): #input [1:0] bl; # burst length:
# 2'b00 - fixed BL8
# 2'b01 - 4 or 8 on-the-fly by A12
# 2'b10 - fixed BL4 (chop)
# 2'b11 - reserved
return concat((
(0,3), # 3'b0,
(0,self.ADDRESS_NUMBER-13), # {ADDRESS_NUMBER-13{1'b0}},
(pd,1), # pd, # MR0.12
(wr,3), # wr, # MR0.11_9
(dll_rst,1), # dll_rst, # MR0.8
(0,1), # 1'b0, # MR0.7
(cl>>1,3), # cl[3:1], # MR0.6_4
(bt,1), # bt, # MR0.3
(cl&1,1), # cl[0], # MR0.2
(bl,2)))[0] # bl[1:0]}; # MR0.1_0
def func_ddr3_mr1(self, # function [ADDRESS_NUMBER+2:0]
qoff, # input qoff; # output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
tdqs, # input tdqs; # termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
rtt, # input [2:0] rtt; # on-die termination resistance:
# 3'b000 - disabled
# 3'b001 - RZQ/4 (60 Ohm)
# 3'b010 - RZQ/2 (120 Ohm)
# 3'b011 - RZQ/6 (40 Ohm)
# 3'b100 - RZQ/12(20 Ohm)
# 3'b101 - RZQ/8 (30 Ohm)
# 3'b11x - reserved
wlev, #input wlev; # write leveling
ods, # input [1:0] ods; # output drive strength:
# 2'b00 - RZQ/6 - 40 Ohm
# 2'b01 - RZQ/7 - 34 Ohm
# 2'b1x - reserved
al, # input [1:0] al; # additive latency:
# 2'b00 - disabled (AL=0)
# 2'b01 - AL=CL-1;
# 2'b10 - AL=CL-2
# 2'b11 - reserved
dll): #input 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}},
(qoff,1), # qoff, # MR1.12
(tdqs,1), # tdqs, # MR1.11
(0,1), # 1'b0, # MR1.10
(rtt>>2,1), # rtt[2], # MR1.9
(0,1), # 1'b0, # MR1.8
(wlev,1), # wlev, # MR1.7
(rtt>>1,1), # rtt[1], # MR1.6
(ods>>1,1), # ods[1], # MR1.5
(al,2), # al[1:0], # MR1.4_3
(rtt,1), # rtt[0], # MR1.2
(ods,1), # ods[0], # MR1.1
(dll)))[0] #dll}; # MR1.0
def func_ddr3_mr2(self, # ; function [ADDRESS_NUMBER+2:0]
rtt_wr, # input [1:0] rtt_wr; # Dynamic ODT :
# 2'b00 - disabled
# 2'b01 - RZQ/4 = 60 Ohm
# 2'b10 - RZQ/2 = 120 Ohm
# 2'b11 - reserved
srt, # input srt; # Self-refresh temperature 0 - normal (0-85C), 1 - extended (<=95C)
asr, # input asr; # Auto self-refresh 0 - disabled (manual), 1 - enabled (auto)
cwl): # input [2:0] cwl; # CAS write latency:
# 3'b000 5CK ( tCK >= 2.5ns)
# 3'b001 6CK (1.875ns <= tCK < 2.5ns)
# 3'b010 7CK (1.5ns <= tCK < 1.875ns)
# 3'b011 8CK (1.25ns <= tCK < 1.5ns)
# 3'b100 9CK (1.071ns <= tCK < 1.25ns)
# 3'b101 10CK (0.938ns <= tCK < 1.071ns)
# 3'b11x reserved
return concat ((
(2,3), # 3'h2,
(0, self.ADDRESS_NUMBER-11), # {ADDRESS_NUMBER-11{1'b0}},
(rtt_wr,2), # rtt_wr[1:0], # MR2.10_9
(0,1), # 1'b0, # MR2.8
(srt,1), # srt, # MR2.7
(asr,1), # asr, # MR2.6
(cwl,3), # cwl[2:0], # MR2.5_3
(0,3)))[0] # 3'b0}; # MR2.2_0
def func_ddr3_mr3(self, # function [ADDRESS_NUMBER+2:0]
mpr, # input mpr; # MPR mode: 0 - normal, 1 - dataflow from MPR
mpr_rf): # input [1:0] mpr_rf; # MPR read function:
# 2'b00: predefined pattern 0101...
# 2'b1x, 2'bx1 - reserved
return concat((
(3,3), # 3'h3,
(0,self.ADDRESS_NUMBER), # {ADDRESS_NUMBER-3{1'b0}},
(mpr, 1), # mpr, # MR3.2
(mpr_rf,2)))[0] # mpr_rf[1:0]}; # MR3.1_0
'''
x393_tasks_pio_sequences
'''
def enable_reset_ps_pio(self, #; // control reset and enable of the PS PIO channel;
en, # input en;
rst): #input rst;
self.write_contol_register(self.MCNTRL_PS_ADDR + self.MCNTRL_PS_EN_RST,
((0,1)[en]<<1) | #{30'b0,en,
(1,0)[rst]) #~rst});
def set_read_block(self, #
ba, # input [ 2:0] ba;
ra, # input [14:0] ra;
ca): #input [ 9:0] ca;
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
data=self.func_encode_cmd( ra, ba, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# see if pause is needed . See when buffer read should be started - maybe before WR command
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr+=1
# first read
# read
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data=self.func_encode_cmd(ca&0x3ff, ba, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# nop
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, ba, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
#repeat remaining reads
for i in range(1,64):
# read
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data=self.func_encode_cmd((ca & 0x3ff)+(i<<3),ba, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# nop - all 3 below are the same? - just repeat?
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, ba, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# nop
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, ba, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# nop
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, ba, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# tRTP = 4*tCK is already satisfied, no skip here
# precharge, end of a page (B_RST)
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data=self.func_encode_cmd( ra, ba, 5, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# Turn off DCI, set DONE
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
def set_write_block(self, #):
ba, # input[2:0]ba;
ra, # input[14:0]ra;
ca): # input[9:0]ca;
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
data=self.func_encode_cmd( ra, ba, 4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# see if pause is needed . See when buffer read should be started - maybe before WR command
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0) # tRCD - 2 read bufs
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# first write, 3 rd_buf
# write
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data=self.func_encode_cmd(ca&0x3ff, ba, 3, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0) # B_RD moved 1 cycle earlier
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# nop 4-th rd_buf
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, ba, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
#repeat remaining writes
for i in range(1,62) : #(i = 1; i < 62; i = i + 1) begin
# write
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data=self.func_encode_cmd((ca&0x3ff)+(i<<3), ba, 3, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data=self.func_encode_cmd((ca&0x3ff)+(62<<3), ba, 3, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0) # write w/o nop
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
#nop
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, ba, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0) # nop with buffer read off
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
'''
# One last write pair w/o buffer
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data=self.func_encode_cmd((ca&0x3ff)+(63<<3), ba, 3, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0) # write with nop
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# nop
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, ba, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# nop
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, ba, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1) # removed B_RD 1 cycle earlier
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# nop
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, ba, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# ODT off, it has latency
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 2, 0, ba, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# precharge, ODT off
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data=self.func_encode_cmd( ra, ba, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 2, 0, ba, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# Finalize, set DONE
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# 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;
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
0) # 2'h0); // [1:0] mpr_rf; // MPR read function: 2'b00: predefined pattern 0101...
mr3_patt = self.func_ddr3_mr3(
1, # 1'h1, // mpr; // MPR mode: 0 - normal, 1 - dataflow from MPR
0) # 2'h0); // [1:0] mpr_rf; // MPR read function: 2'b00: predefined pattern 0101...
# Set pattern mode
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data=self.func_encode_cmd(bits(mr3_patt,(14,0)), bits(mr3_patt,(17,15)), 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data.self.func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)# tMOD
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# first read
#@ read
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data=self.func_encode_cmd( 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# nop (combine with previous?)
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
#repeat remaining reads
# for (i = 1; i < nrep; i = i + 1) begin
for _ in range(1,nrep):
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data=self.func_encode_cmd( 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# nop - all 3 below are the same? - just repeat?
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# nop
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# nop
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# nop, no write buffer - next page
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# Turn off read pattern mode
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data=self.func_encode_cmd(bits(mr3_norm,(14,0)), bits(mr3_norm,(17,15)), 7, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# tMOD (keep DCI enabled)
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# Turn off DCI
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
# Finalize (set DONE)
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
self.axi_write_single_w(cmd_addr, data)
cmd_addr += 1
'''
task set_write_lev;
input[CMD_PAUSE_BITS-1:0]nrep;
reg[17:0] mr1_norm;
reg[17:0] mr1_wlev;
reg[29:0] cmd_addr;
reg[31:0] data;
reg[CMD_PAUSE_BITS-1:0] dqs_low_rpt;
reg[CMD_PAUSE_BITS-1:0] nrep_minus_1;
begin
dqs_low_rpt <= 8;
nrep_minus_1 <= nrep - 1;
mr1_norm <= ddr3_mr1(
1'h0, // qoff; // output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
1'h0, // tdqs; // termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
3'h2, // [2:0] rtt; // on-die termination resistance: // 3'b010 - RZQ/2 (120 Ohm)
1'h0, // wlev; // write leveling
2'h0, // ods; // output drive strength: // 2'b00 - RZQ/6 - 40 Ohm
2'h0, // [1:0] al; // additive latency: 2'b00 - disabled (AL=0)
1'b0); // dll; // 0 - DLL enabled (normal), 1 - DLL disabled
mr1_wlev <= ddr3_mr1(
1'h0, // qoff; // output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
1'h0, // tdqs; // termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
3'h2, // [2:0] rtt; // on-die termination resistance: // 3'b010 - RZQ/2 (120 Ohm)
1'h1, // wlev; // write leveling
2'h0, // ods; // output drive strength: // 2'b00 - RZQ/6 - 40 Ohm
2'h0, // [1:0] al; // additive latency: 2'b00 - disabled (AL=0)
1'b0); // dll; // 0 - DLL enabled (normal), 1 - DLL disabled
cmd_addr <= MCONTR_CMD_WR_ADDR + WRITELEV_OFFSET;
// Enter write leveling mode
@(posedge CLK)
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr1_wlev[14:0], mr1_wlev[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // tWLDQSEN=25tCK
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// enable DQS output, keep it low (15 more tCK for the total of 40 tCK
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip(dqs_low_rpt, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Toggle DQS as needed for write leveling, write to buffer
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip(nrep_minus_1,0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// continue toggling (5 times), but disable writing to buffer (used same wbuf latency as for read)
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 4, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Keep DCI (but not ODT) active ODT should be off befor MRS
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// exit write leveling mode, ODT off, DCI off
// addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data <= func_encode_cmd(mr1_norm[14:0], mr1_norm[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // tMOD
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// Finalize. See if DONE can be combined with B_RST, if not - insert earlier
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); // can DONE be combined with B_RST?
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
end
endtask
'''
'''
vpars1=VerilogParameters()
......
from __future__ import print_function
'''
# Copyright (C) 2015, Elphel.inc.
# Memory read/write functions
......@@ -27,7 +28,6 @@ __version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
from __future__ import print_function
import mmap
#import sys
import struct
......@@ -36,13 +36,13 @@ class X393Mem(object):
'''
classdocs
'''
DRY_MODE= False # True
DRY_MODE= True # True
PAGE_SIZE=4096
DEBUG_MODE=1
ENDIAN="<" # little, ">" for big
AXI_SLAVE0_BASE=0x40000000
def __init__(self, debug_mode=1,dry_mode=False):
def __init__(self, debug_mode=1,dry_mode=True):
self.DEBUG_MODE=debug_mode
self.DRY_MODE=dry_mode
......
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