def axi_set_tristate_patterns(self, strPattern=None): """ Set sequencer patterns for the tristate ON/OFF (defined by parameters) <strPattern> - optional up to 4-letter pattern. Each letter is one of 3: 'E'- early, "N" - nominal and 'L' - late, first for DQ start, second - for DQS start, then DQ end and DQS end. If no pattern is provided, all will be set to Verilog parameter values (DQ*TRI_*), if only 1 - it will be applied to all, if 2 - it will be repeated twice, 3 will use the same value for DQS end as for DQS start """ modes={'E':0,'N':1,'L':2} evNames=('DQ_FIRST', 'DQS_FIRST', 'DQ_LAST','DQS_LAST') patVals={evNames[0]: (0x3,0x7,0xf), # DQ_FIRST: early, nominal, late evNames[1]: (0x1,0x3,0x7), # DQS_FIRST: early, nominal, late evNames[2]: (0xf,0xe,0xc), # DQ_LAST: early, nominal, late evNames[3]: (0xe,0xc,0x8)} # DQS_LAST: early, nominal, late if not strPattern: delays=concat(((0,16), # {16'h0, (vrlg.DQSTRI_LAST, getParWidth(vrlg.DQSTRI_LAST__TYPE)), # DQSTRI_LAST, (vrlg.DQSTRI_FIRST,getParWidth(vrlg.DQSTRI_FIRST__TYPE)), # DQSTRI_FIRST, (vrlg.DQTRI_LAST, getParWidth(vrlg.DQTRI_LAST__TYPE)), # DQTRI_LAST, (vrlg.DQTRI_FIRST, getParWidth(vrlg.DQTRI_FIRST__TYPE))) # DQTRI_FIRST}); )[0] else: strPattern=strPattern.upper() if len(strPattern) == 1: strPattern*=4 elif len(strPattern) == 2: strPattern*=2 elif len(strPattern) == 3: strPattern+=strPattern[1] strPattern=strPattern[:4] vals={} for i,n in enumerate(evNames): try: vals[n]=patVals[n][modes[strPattern[i]]] except: msg="axi_set_tristate_patterns(%s): Failed to determine delay mode for %s, got %s"%(strPattern,n,strPattern[i]) print (msg) Exception(msg) print ("axi_set_tristate_patterns(%s) : %s"%(strPattern,str(vals))) delays=concat(((0,16), # {16'h0, (vals['DQS_LAST'],4), # vrlg.DQSTRI_LAST, getParWidth(vrlg.DQSTRI_LAST__TYPE)), # DQSTRI_LAST, (vals['DQS_FIRST'],4), # vrlg.DQSTRI_FIRST,getParWidth(vrlg.DQSTRI_FIRST__TYPE)), # DQSTRI_FIRST, (vals['DQ_LAST'],4), # vrlg.DQTRI_LAST, getParWidth(vrlg.DQTRI_LAST__TYPE)), # DQTRI_LAST, (vals['DQ_FIRST'],4)) # vrlg.DQTRI_FIRST, getParWidth(vrlg.DQTRI_FIRST__TYPE))) # DQTRI_FIRST}); )[0] # may fail if some of the parameters used have undefined width print("DQTRI_FIRST=%s, DQTRI_FIRST__TYPE=%s"%(str(vrlg.DQTRI_FIRST),str(vrlg.DQTRI_FIRST__TYPE))) print("DQTRI_LAST=%s, DQTRI_LAST__TYPE=%s"%(str(vrlg.DQTRI_LAST),str(vrlg.DQTRI_LAST__TYPE))) if self.DEBUG_MODE > 1: print("SET TRISTATE PATTERNS, combined delays=%s"%str(delays)) print("SET TRISTATE PATTERNS, combined delays=0x%x"%delays) self.x393_axi_tasks.write_control_register(vrlg.MCONTR_PHY_16BIT_ADDR +vrlg.MCONTR_PHY_16BIT_PATTERNS_TRI, delays) # DQSTRI_LAST, DQSTRI_FIRST, DQTRI_LAST, DQTRI_FIRST});
def axi_set_tristate_patterns(self, strPattern=None): """ Set sequencer patterns for the tristate ON/OFF (defined by parameters) <strPattern> - optional up to 4-letter pattern. Each letter is one of 3: 'E'- early, "N" - nominal and 'L' - late, first for DQ start, second - for DQS start, then DQ end and DQS end. If no pattern is provided, all will be set to Verilog parameter values (DQ*TRI_*), if only 1 - it will be applied to all, if 2 - it will be repeated twice, 3 will use the same value for DQS end as for DQS start """ modes = {'E': 0, 'N': 1, 'L': 2} evNames = ('DQ_FIRST', 'DQS_FIRST', 'DQ_LAST', 'DQS_LAST') patVals = { evNames[0]: (0x3, 0x7, 0xf), # DQ_FIRST: early, nominal, late evNames[1]: (0x1, 0x3, 0x7), # DQS_FIRST: early, nominal, late evNames[2]: (0xf, 0xe, 0xc), # DQ_LAST: early, nominal, late evNames[3]: (0xe, 0xc, 0x8) } # DQS_LAST: early, nominal, late if not strPattern: delays = concat(( (0, 16), # {16'h0, (vrlg.DQSTRI_LAST, getParWidth(vrlg.DQSTRI_LAST__TYPE)), # DQSTRI_LAST, (vrlg.DQSTRI_FIRST, getParWidth(vrlg.DQSTRI_FIRST__TYPE)), # DQSTRI_FIRST, (vrlg.DQTRI_LAST, getParWidth(vrlg.DQTRI_LAST__TYPE)), # DQTRI_LAST, (vrlg.DQTRI_FIRST, getParWidth(vrlg.DQTRI_FIRST__TYPE)) ) # DQTRI_FIRST}); )[0] else: strPattern = strPattern.upper() if len(strPattern) == 1: strPattern *= 4 elif len(strPattern) == 2: strPattern *= 2 elif len(strPattern) == 3: strPattern += strPattern[1] strPattern = strPattern[:4] vals = {} for i, n in enumerate(evNames): try: vals[n] = patVals[n][modes[strPattern[i]]] except: msg = "axi_set_tristate_patterns(%s): Failed to determine delay mode for %s, got %s" % ( strPattern, n, strPattern[i]) print(msg) Exception(msg) print("axi_set_tristate_patterns(%s) : %s" % (strPattern, str(vals))) delays = concat(( (0, 16), # {16'h0, ( vals['DQS_LAST'], 4 ), # vrlg.DQSTRI_LAST, getParWidth(vrlg.DQSTRI_LAST__TYPE)), # DQSTRI_LAST, ( vals['DQS_FIRST'], 4 ), # vrlg.DQSTRI_FIRST,getParWidth(vrlg.DQSTRI_FIRST__TYPE)), # DQSTRI_FIRST, ( vals['DQ_LAST'], 4 ), # vrlg.DQTRI_LAST, getParWidth(vrlg.DQTRI_LAST__TYPE)), # DQTRI_LAST, (vals['DQ_FIRST'], 4) ) # vrlg.DQTRI_FIRST, getParWidth(vrlg.DQTRI_FIRST__TYPE))) # DQTRI_FIRST}); )[0] # may fail if some of the parameters used have undefined width print("DQTRI_FIRST=%s, DQTRI_FIRST__TYPE=%s" % (str(vrlg.DQTRI_FIRST), str(vrlg.DQTRI_FIRST__TYPE))) print("DQTRI_LAST=%s, DQTRI_LAST__TYPE=%s" % (str(vrlg.DQTRI_LAST), str(vrlg.DQTRI_LAST__TYPE))) if self.DEBUG_MODE > 1: print("SET TRISTATE PATTERNS, combined delays=%s" % str(delays)) print("SET TRISTATE PATTERNS, combined delays=0x%x" % delays) self.x393_axi_tasks.write_control_register( vrlg.MCONTR_PHY_16BIT_ADDR + vrlg.MCONTR_PHY_16BIT_PATTERNS_TRI, delays) # DQSTRI_LAST, DQSTRI_FIRST, DQTRI_LAST, DQTRI_FIRST});
def test_tiled_read( self, # \ channel, # input [3:0] channel; byte32, # input byte32; keep_open, # input keep_open; extra_pages, # input [1:0] extra_pages; show_data, # input show_data; window_width, # input [15:0] window_width; window_height, # input [15:0] window_height; window_left, # input [15:0] window_left; window_top, # input [15:0] window_top; 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] tile_rows_per_window = ((window_height - 1) / tile_vstep) + 1 tile_size = tile_width * tile_height channel = (0, 1)[channel] keep_open = (0, 1)[keep_open] show_data = (0, 1)[show_data] print( "====== test_tiled_read: channel=%d, byte32=%d, keep_open=%d, extra_pages=%d, show_data=%d" % (channel, byte32, keep_open, extra_pages, show_data) ) if channel == 2: start_addr = vrlg.MCNTRL_TILED_CHN2_ADDR status_address = vrlg.MCNTRL_TEST01_STATUS_REG_CHN2_ADDR status_control_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN2_STATUS_CNTRL test_mode_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN2_MODE elif channel == 4: start_addr = vrlg.MCNTRL_TILED_CHN4_ADDR status_address = vrlg.MCNTRL_TEST01_STATUS_REG_CHN4_ADDR status_control_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN4_STATUS_CNTRL test_mode_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN4_MODE else: print("**** ERROR: Invalid channel, only 2 and 4 are valid") start_addr = vrlg.MCNTRL_TILED_CHN2_ADDR status_address = vrlg.MCNTRL_TEST01_STATUS_REG_CHN2_ADDR status_control_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN2_STATUS_CNTRL test_mode_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN2_MODE """ mode= self.func_encode_mode_tiled( byte32, keep_open, extra_pages, 0, # write_mem, 1, # enable 0) # chn_reset """ mode = x393_mcntrl.func_encode_mode_scan_tiled( disable_need=False, repetitive=True, single=False, reset_frame=False, byte32=byte32, keep_open=keep_open, extra_pages=extra_pages, write_mem=False, enable=True, chn_reset=False, ) self.x393_axi_tasks.write_control_register(start_addr + vrlg.MCNTRL_TILED_MODE, 0) # reset channel, including page address self.x393_axi_tasks.write_control_register( start_addr + vrlg.MCNTRL_TILED_STARTADDR, vrlg.FRAME_START_ADDRESS ) # RA=80, CA=0, BA=0 22-bit frame start address (3 CA LSBs==0. BA==0) self.x393_axi_tasks.write_control_register( start_addr + vrlg.MCNTRL_TILED_FRAME_FULL_WIDTH, vrlg.FRAME_FULL_WIDTH ) self.x393_axi_tasks.write_control_register( start_addr + vrlg.MCNTRL_TILED_WINDOW_WH, concat(((window_height, 16), (window_width, 16)))[0] ) # {window_height,window_width}); self.x393_axi_tasks.write_control_register( start_addr + vrlg.MCNTRL_TILED_WINDOW_X0Y0, concat(((window_top, 16), (window_left, 16)))[0] ) # {window_top,window_left}); self.x393_axi_tasks.write_control_register( start_addr + vrlg.MCNTRL_TILED_WINDOW_STARTXY, concat(((vrlg.TILED_STARTY, 16), (vrlg.TILED_STARTX, 16)))[0] ) # TILED_STARTX+(TILED_STARTY<<16)); self.x393_axi_tasks.write_control_register( start_addr + vrlg.MCNTRL_TILED_TILE_WHS, concat(((tile_vstep, 8), (tile_height, 8), (tile_width, 8)))[0] ) # {8'b0,tile_vstep,tile_height,tile_width});#tile_width+(tile_height<<8)+(tile_vstep<<16)); self.x393_axi_tasks.write_control_register(start_addr + vrlg.MCNTRL_TILED_MODE, mode) # set mode register: {extra_pages[1:0],enable,!reset} self.x393_axi_tasks.configure_channel_priority(channel, 0) # lowest priority channel 3 self.x393_axi_tasks.enable_memcntrl_en_dis(channel, 1) self.x393_axi_tasks.write_control_register(test_mode_address, vrlg.TEST01_START_FRAME) for ii in range( tiles_per_row * tile_rows_per_window ): # (ii=0;ii<(tiles_per_row * tile_rows_per_window);ii = ii+1) begin self.x393_axi_tasks.wait_status_condition( status_address, # MCNTRL_TEST01_STATUS_REG_CHN4_ADDR, status_control_address, # MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN4_STATUS_CNTRL, vrlg.DEFAULT_STATUS_MODE, ii << 16, # -TEST_INITIAL_BURST)<<16, # 4-bit page number 0xF << 16, #'hf << 16, # mask for the 4-bit page number 1, # not equal to (0, 1)[ii == 0], ) # synchronize sequence number - only first time, next just wait fro auto update if show_data: print("########### test_tiled_read block %d: channel=%d" % (ii, channel)) result.append( self.x393_mcntrl_buffers.read_block_buf_chn( channel, (ii & 3), tile_size << 2, # 1, # chn=0, page=3, number of 32-bit words=256, show_rslt show_data, ) ) self.x393_axi_tasks.write_control_register(test_mode_address, vrlg.TEST01_NEXT_PAGE) # enable_memcntrl_en_dis(channel,0); # disable channel return result
def test_tiled_write( self, # channel, # input [3:0] channel; byte32, # input byte32; keep_open, # input keep_open; extra_pages, # input [1:0] extra_pages; wait_done, # input wait_done; window_width, # input [15:0] window_width; window_height, # input [15:0] window_height; window_left, # input [15:0] window_left; window_top, # input [15:0] window_top; 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 tile_size = tile_width * tile_height channel = (0, 1)[channel] keep_open = (0, 1)[keep_open] wait_done = (0, 1)[wait_done] print( "====== test_tiled_write: channel=%d, byte32=%d, keep_open=%d, extra_pages=%d, wait_done=%d" % (channel, byte32, keep_open, extra_pages, wait_done) ) if channel == 2: start_addr = vrlg.MCNTRL_TILED_CHN2_ADDR status_address = vrlg.MCNTRL_TEST01_STATUS_REG_CHN2_ADDR status_control_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN2_STATUS_CNTRL test_mode_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN2_MODE elif channel == 4: start_addr = vrlg.MCNTRL_TILED_CHN4_ADDR status_address = vrlg.MCNTRL_TEST01_STATUS_REG_CHN4_ADDR status_control_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN4_STATUS_CNTRL test_mode_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN4_MODE else: print("**** ERROR: Invalid channel, only 2 and 4 are valid") start_addr = vrlg.MCNTRL_TILED_CHN2_ADDR status_address = vrlg.MCNTRL_TEST01_STATUS_REG_CHN2_ADDR status_control_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN2_STATUS_CNTRL test_mode_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN2_MODE """ mode= self.func_encode_mode_tiled( byte32, keep_open, extra_pages, 1, # write_mem, 1, # enable 0) # chn_reset """ mode = x393_mcntrl.func_encode_mode_scan_tiled( disable_need=False, repetitive=True, single=False, reset_frame=False, byte32=byte32, keep_open=keep_open, extra_pages=extra_pages, write_mem=True, enable=True, chn_reset=False, ) self.x393_axi_tasks.write_control_register(start_addr + vrlg.MCNTRL_TILED_MODE, 0) # reset channel, including page address self.x393_axi_tasks.write_control_register( start_addr + vrlg.MCNTRL_TILED_STARTADDR, vrlg.FRAME_START_ADDRESS ) # RA=80, CA=0, BA=0 22-bit frame start address (3 CA LSBs==0. BA==0) self.x393_axi_tasks.write_control_register( start_addr + vrlg.MCNTRL_TILED_FRAME_FULL_WIDTH, vrlg.FRAME_FULL_WIDTH ) self.x393_axi_tasks.write_control_register( start_addr + vrlg.MCNTRL_TILED_WINDOW_WH, concat(((window_height, 16), (window_width, 16)))[0] ) # {window_height,window_width}); self.x393_axi_tasks.write_control_register( start_addr + vrlg.MCNTRL_TILED_WINDOW_X0Y0, concat(((window_top, 16), (window_left, 16)))[0] ) # {window_top,window_left}); self.x393_axi_tasks.write_control_register( start_addr + vrlg.MCNTRL_TILED_WINDOW_STARTXY, concat(((vrlg.TILED_STARTY, 16), (vrlg.TILED_STARTX, 16)))[0] ) # TILED_STARTX+(TILED_STARTY<<16)); self.x393_axi_tasks.write_control_register( start_addr + vrlg.MCNTRL_TILED_TILE_WHS, concat(((tile_vstep, 8), (tile_height, 8), (tile_width, 8)))[0] ) # {8'b0,tile_vstep,tile_height,tile_width});#tile_width+(tile_height<<8)+(tile_vstep<<16)); self.x393_axi_tasks.write_control_register(start_addr + vrlg.MCNTRL_TILED_MODE, mode) # set mode register: {extra_pages[1:0],enable,!reset} self.x393_axi_tasks.configure_channel_priority(channel, 0) # lowest priority channel 3 self.x393_axi_tasks.enable_memcntrl_en_dis(channel, 1) self.x393_axi_tasks.write_control_register(test_mode_address, vrlg.TEST01_START_FRAME) for ii in range(vrlg.TEST_INITIAL_BURST): # for (ii=0;ii<TEST_INITIAL_BURST;ii=ii+1) begin print("########### test_tiled_write block %d: channel=%d" % (ii, channel)) startx = window_left + ((ii % tiles_per_row) * tile_width) starty = window_top + (ii / tile_rows_per_window) # SCANLINE_CUR_Y); self.x393_mcntrl_buffers.write_block_scanline_chn( # TODO: Make a different tile buffer data, matching the order channel, # channel (ii & 3), tile_size, startx, # window_left + ((ii % tiles_per_row) * tile_width), starty, ) # window_top + (ii / tile_rows_per_window)); # SCANLINE_CUR_Y);\ for ii in range( tiles_per_row * tile_rows_per_window ): # for (ii=0;ii<(tiles_per_row * tile_rows_per_window);ii = ii+1) begin if ii >= vrlg.TEST_INITIAL_BURST: # ) begin # wait page ready and fill page after first 4 are filled self.x393_axi_tasks.wait_status_condition( status_address, # MCNTRL_TEST01_STATUS_REG_CHN5_ADDR, status_control_address, # MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN5_STATUS_CNTRL, vrlg.DEFAULT_STATUS_MODE, (ii - vrlg.TEST_INITIAL_BURST) << 16, # 4-bit page number 0xF << 16, # 'hf << 16, # mask for the 4-bit page number 1, # not equal to (0, 1)[ii == vrlg.TEST_INITIAL_BURST], ) # synchronize sequence number - only first time, next just wait fro auto update print("########### test_tiled_write block %d: channel=%d" % (ii, channel)) startx = window_left + ((ii % tiles_per_row) * tile_width) starty = window_top + (ii / tile_rows_per_window) self.x393_mcntrl_buffers.write_block_scanline_chn( # TODO: Make a different tile buffer data, matching the order channel, # channel (ii & 3), tile_size, startx, # window_left + ((ii % tiles_per_row) * tile_width), starty, ) # window_top + (ii / tile_rows_per_window)); # SCANLINE_CUR_Y);\ self.x393_axi_tasks.write_control_register(test_mode_address, vrlg.TEST01_NEXT_PAGE) if wait_done: self.x393_axi_tasks.wait_status_condition( # may also be read directly from the same bit of mctrl_linear_rw (address=5) status status_address, # MCNTRL_TEST01_STATUS_REG_CHN3_ADDR, status_control_address, # MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN3_STATUS_CNTRL, vrlg.DEFAULT_STATUS_MODE, 2 << vrlg.STATUS_2LSB_SHFT, # bit 24 - busy, bit 25 - frame done 2 << vrlg.STATUS_2LSB_SHFT, # mask for the 4-bit page number 0, # equal to 0, ) # no need to synchronize sequence number