from __future__ import print_function ''' # Copyright (C) 2015, Elphel.inc. # 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 # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . @author: Andrey Filippov @copyright: 2015 Elphel, Inc. @license: GPLv3.0+ @contact: andrey@elphel.coml @deffield updated: Updated ''' __author__ = "Andrey Filippov" __copyright__ = "Copyright 2015, Elphel, Inc." __license__ = "GPL" __version__ = "3.0+" __maintainer__ = "Andrey Filippov" __email__ = "andrey@elphel.com" __status__ = "Development" #import sys #import x393_mem #x393_pio_sequences from import_verilog_parameters import VerilogParameters from x393_mem import X393Mem from x393_axi_control_status import X393AxiControlStatus from x393_pio_sequences import X393PIOSequences from x393_mcntrl_timing import X393McntrlTiming from x393_mcntrl_buffers import X393McntrlBuffers #from verilog_utils import * # concat, bits #from verilog_utils import hx, concat, bits, getParWidth from verilog_utils import concat #, getParWidth #from x393_axi_control_status import concat, bits class X393McntrlTests(object): DRY_MODE= True # True DEBUG_MODE=1 x393_mem=None x393_axi_tasks=None #x393X393AxiControlStatus x393_pio_sequences=None x393_mcntrl_timing=None x393_mcntrl_buffers=None verbose=1 def __init__(self, debug_mode=1,dry_mode=True): self.DEBUG_MODE= debug_mode self.DRY_MODE= dry_mode self.x393_mem= X393Mem(debug_mode,dry_mode) self.x393_axi_tasks= X393AxiControlStatus(debug_mode,dry_mode) self.x393_pio_sequences= X393PIOSequences(debug_mode,True) self.x393_mcntrl_timing= X393McntrlTiming(debug_mode,True) self.x393_mcntrl_buffers= X393McntrlBuffers(debug_mode,True) self.__dict__.update(VerilogParameters.__dict__["_VerilogParameters__shared_state"]) # Add verilog parameters to the class namespace try: self.verbose=self.VERBOSE except: pass def func_encode_mode_tiled(self, # function [6:0] byte32, # input byte32; # 32-byte columns (0 - 16-byte columns) keep_open, # input keep_open; # for 8 or less rows - do not close page between accesses extra_pages, # input [1:0] extra_pages; # number of extra pages that need to stay (not to be overwritten) in the buffer # can be used for overlapping tile read access 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 """ Combines arguments to create a 7-bit encoded data for tiled mode memory R/W use 32-byte wide columns (0 - use 16-byte ones) , do not close page between accesses (for 8 or less rows only) , 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 to memory mode (0 - read from memory) , enable requests from this channel ( 0 will let current to finish, but not raise want/need) ): 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, ((0,1)[write_mem],1), # write_mem, ((0,1)[enable], 1), #enable, ((1,0)[chn_reset],1)) # ~chn_reset}; def func_encode_mode_scanline(self, # function [4:0] extra_pages, # input [1:0] extra_pages; # number of extra pages that need to stay (not to be overwritten) in the buffer # can be used for overlapping tile read access 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 """ Combines arguments to create a 5-bit encoded data for scanline mode memory R/W , 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 to memory mode (0 - read from memory) , enable requests from this channel ( 0 will let current to finish, but not raise want/need) ): 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 - 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.) self.x393_mcntrl_timing.axi_set_dqs_dqm_patterns() # prepare all sequences self.set_all_sequences; # prepare write buffer self.x393_mcntrl_buffers.write_block_buf_chn(0,0,256); # fill block memory (channel, page, number) # set all delays ##axi_set_delays - from tables, per-pin if set_per_pin_delays: self.x393_mcntrl_timing.axi_set_delays() # set all individual delays, aslo runs axi_set_phase() else: self.x393_mcntrl_timing.axi_set_same_delays( self.DLY_DQ_IDELAY, self.DLY_DQ_ODELAY, self.DLY_DQS_IDELAY, self.DLY_DQS_ODELAY, self.DLY_DM_ODELAY, self.DLY_CMDA_ODELAY) # set clock phase relative to DDR clk 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") self.x393_pio_sequences.set_refresh( 50, # input [ 9:0] t_rfc; # =50 for tCK=2.5ns 16) #input [ 7:0] t_refi; # 48/97 for normal, 8 - for simulation if self.verbose>0: print("SET WRITE LEVELING") self.x393_pio_sequences.set_write_lev(16) # write leveling, 16 times (full buffer - 128) if self.verbose>0: print("SET READ PATTERNt") self.x393_pio_sequences.set_read_pattern(8) # 8x2*64 bits, 32x32 bits to read if self.verbose>0: print("SET WRITE BLOCK") self.x393_pio_sequences.set_write_block( 5, # 3'h5, # bank 0x1234, # 15'h1234, # row address 0x100 # 10'h100 # column address ) if self.verbose>0: print("SET READ BLOCK"); self.x393_pio_sequences.set_read_block ( 5, # 3'h5, # bank 0x1234, # 15'h1234, # row address 0x100 # 10'h100 # column address ) def test_write_levelling(self, wait_complete, # Wait for operation to complete wlev_dqs_dly= 0x80, norm_dqs_odly=0x78): """ Test write levelling mode wait write levelling operation to complete (0 - may initiate multiple PS PIO operations) DQS output delay for write levelling mode (default 0x80) 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() # Set write buffer (from DDR3) WE signal delay for write leveling mode self.x393_mcntrl_timing.axi_set_wbuf_delay(self.WBUF_DLY_WLV) # TODO: Set configurable delay time instead of #80 self.x393_mcntrl_timing.axi_set_dqs_odelay(wlev_dqs_dly) # 'h80); # 'h80 - inverted, 'h60 - not - 'h80 will cause warnings during simulation 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, 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) self.x393_mcntrl_buffers.read_block_buf_chn (0, 0, 32, 1, 1); # chn=0, page=0, number of 32-bit words=32, wait_done self.x393_mcntrl_timing.axi_set_dqs_odelay(self.DLY_DQS_ODELAY) 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, 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) rslt=self.x393_mcntrl_buffers.read_block_buf_chn (0, 1, 32, 1, 1 ); # chn=0, page=1, number of 32-bit words=32, wait_done self.x393_mcntrl_timing.axi_set_dqs_idelay_nominal() self.x393_mcntrl_timing.axi_set_dqs_odelay(norm_dqs_odly) # 'h78); self.x393_mcntrl_timing.axi_set_wbuf_delay(self.WBUF_DLY_DFLT); #DFLT_WBUF_DELAY return rslt def test_read_pattern(self, wait_complete): # Wait for operation to complete """ Test read pattern mode 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, 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) return self.x393_mcntrl_buffers.read_block_buf_chn (0, 2, 32, 1, 1 ) # chn=0, page=2, number of 32-bit words=32, wait_done def test_write_block(self, wait_complete): # Wait for operation to complete """ Test write block in PS PIO mode 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, 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: # self.x393_pio_sequences.wait_ps_pio_done(self.DEFAULT_STATUS_MODE,1) # wait previous memory transaction finished before changing delays (effective immediately) def test_read_block(self, wait_complete): # Wait for operation to complete """ Test read block in PS PIO mode 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, 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, 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, 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) return self.x393_mcntrl_buffers.read_block_buf_chn (0, 3, 256, 1, 1 ) # chn=0, page=3, number of 32-bit words=256, wait_done def test_scanline_write(self, # channel, # input [3:0] channel; 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; """ Test scanline write (frame size/row increment is set in parameters) channel number to use. Valid values: 1, 3 2-bit number of extra pages that need to stay (not to be overwritten) in the buffer for operation finished 13-bit window width in 8-bursts (16 bytes) 16 bit window height , 13-bit window left margin in 8-bursts (16 bytes) 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<>NUM_XFER_BITS)+((window_width[NUM_XFER_BITS-1:0]==0)?0:1); print("====== test_scanline_write: channel=%d, extra_pages=%d, wait_done=%d"% (channel, extra_pages, wait_done)) if channel == 1: start_addr= self.MCNTRL_SCANLINE_CHN1_ADDR status_address= self.MCNTRL_TEST01_STATUS_REG_CHN1_ADDR status_control_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN1_STATUS_CNTRL test_mode_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN1_MODE elif channel == 3: start_addr= self.MCNTRL_SCANLINE_CHN3_ADDR status_address= self.MCNTRL_TEST01_STATUS_REG_CHN3_ADDR status_control_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN3_STATUS_CNTRL test_mode_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN3_MODE else: print("**** ERROR: Invalid channel, only 1 and 3 are valid") start_addr= self.MCNTRL_SCANLINE_CHN1_ADDR status_address= self.MCNTRL_TEST01_STATUS_REG_CHN1_ADDR status_control_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN1_STATUS_CNTRL test_mode_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN1_MODE mode= self.func_encode_mode_scanline( extra_pages, 1, # write_mem, 1, # enable 0) # chn_reset self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_SCANLINE_STARTADDR, self.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_contol_register(start_addr + self.MCNTRL_SCANLINE_FRAME_FULL_WIDTH, self.FRAME_FULL_WIDTH); self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_SCANLINE_WINDOW_WH, {window_height,window_width}); #WINDOW_WIDTH + (WINDOW_HEIGHT<<16)); self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_SCANLINE_WINDOW_X0Y0, {window_top,window_left}); #WINDOW_X0+ (WINDOW_Y0<<16)); self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_SCANLINE_WINDOW_STARTXY, self.SCANLINE_STARTX+(self.SCANLINE_STARTY<<16)); self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_SCANLINE_MODE, mode); self.x393_axi_tasks.configure_channel_priority(channel,0); # lowest priority channel 3 # enable_memcntrl_channels(16'h000b); # channels 0,1,3 are enabled self.x393_axi_tasks.enable_memcntrl_en_dis(channel,1); self.x393_axi_tasks.write_contol_register(test_mode_address, self.TEST01_START_FRAME); for ii in range(0,self.TEST_INITIAL_BURST): # for (ii=0;ii 1: if (ii % pages_per_row) < (pages_per_row-1): xfer_size= 1 << self.NUM_XFER_BITS else: xfer_size= window_width % (1<= self.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_CHN3_ADDR, status_control_address, # MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN3_STATUS_CNTRL, self.DEFAULT_STATUS_MODE, (ii-self.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 == self.TEST_INITIAL_BURST]) # synchronize sequence number - only first time, next just wait fro auto update if pages_per_row > 1: if (ii % pages_per_row) < (pages_per_row-1): xfer_size= 1 << self.NUM_XFER_BITS else: xfer_size= window_width % (1< channel number to use. Valid values: 1, 3 2-bit number of extra pages that need to stay (not to be overwritten) in the buffer print read data 13-bit window width in 8-bursts (16 bytes) 16 bit window height , 13-bit window left margin in 8-bursts (16 bytes) 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); pages_per_row= (window_width>>self.NUM_XFER_BITS)+(0,1)[(window_width & ((1<>NUM_XFER_BITS)+((window_width[NUM_XFER_BITS-1:0]==0)?0:1); print("====== test_scanline_read: channel=%d, extra_pages=%d, show_data=%d"% (channel, extra_pages, show_data)) if channel == 1: start_addr= self.MCNTRL_SCANLINE_CHN1_ADDR status_address= self.MCNTRL_TEST01_STATUS_REG_CHN1_ADDR status_control_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN1_STATUS_CNTRL test_mode_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN1_MODE elif channel == 3: start_addr= self.MCNTRL_SCANLINE_CHN3_ADDR status_address= self.MCNTRL_TEST01_STATUS_REG_CHN3_ADDR status_control_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN3_STATUS_CNTRL test_mode_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN3_MODE else: print("**** ERROR: Invalid channel, only 1 and 3 are valid") start_addr= self.MCNTRL_SCANLINE_CHN1_ADDR status_address= self.MCNTRL_TEST01_STATUS_REG_CHN1_ADDR status_control_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN1_STATUS_CNTRL test_mode_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN1_MODE mode= self.func_encode_mode_scanline( extra_pages, 0, # write_mem, 1, # enable 0) # chn_reset # program to the self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_SCANLINE_STARTADDR, self.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_contol_register(start_addr + self.MCNTRL_SCANLINE_FRAME_FULL_WIDTH, self.FRAME_FULL_WIDTH); self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_SCANLINE_WINDOW_WH, {window_height,window_width}); #WINDOW_WIDTH + (WINDOW_HEIGHT<<16)); self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_SCANLINE_WINDOW_X0Y0, {window_top,window_left}); #WINDOW_X0+ (WINDOW_Y0<<16)); self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_SCANLINE_WINDOW_STARTXY, self.SCANLINE_STARTX+(self.SCANLINE_STARTY<<16)); self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_SCANLINE_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_contol_register(test_mode_address, self.TEST01_START_FRAME); for ii in range(window_height * pages_per_row): # for (ii=0;ii<(window_height * pages_per_row);ii = ii+1) begin if pages_per_row > 1: if (ii % pages_per_row) < (pages_per_row-1): xfer_size= 1 << self.NUM_XFER_BITS else: xfer_size= window_width % (1< channel number to use. Valid values: 2, 4 use 32-byte wide columns (0 - use 16-byte ones) , do not close page between accesses (for 8 or less rows only) 2-bit number of extra pages that need to stay (not to be overwritten) in the buffer wait for operation finished 13-bit window width in 8-bursts (16 bytes) 16 bit window height , 13-bit window left margin in 8-bursts (16 bytes) 16-bit window top margin 6-bit tile width in 8-bursts (16 bytes) (0 -> 64) 6-bit tile_height (0->64) 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= self.MCNTRL_TILED_CHN2_ADDR status_address= self.MCNTRL_TEST01_STATUS_REG_CHN2_ADDR status_control_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN2_STATUS_CNTRL test_mode_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN2_MODE elif channel == 4: start_addr= self.MCNTRL_TILED_CHN4_ADDR; status_address= self.MCNTRL_TEST01_STATUS_REG_CHN4_ADDR; status_control_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN4_STATUS_CNTRL; test_mode_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN4_MODE; else: print("**** ERROR: Invalid channel, only 2 and 4 are valid"); start_addr= self.MCNTRL_TILED_CHN2_ADDR; status_address= self.MCNTRL_TEST01_STATUS_REG_CHN2_ADDR; status_control_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN2_STATUS_CNTRL; test_mode_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN2_MODE; mode= self.func_encode_mode_tiled( byte32, keep_open, extra_pages, 1, # write_mem, 1, # enable 0) # chn_reset self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_TILED_STARTADDR, self.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_contol_register(start_addr + self.MCNTRL_TILED_FRAME_FULL_WIDTH, self.FRAME_FULL_WIDTH) self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_TILED_WINDOW_WH, concat((window_height,16), (window_width, 16))) # {window_height,window_width}); self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_TILED_WINDOW_X0Y0, concat((window_top, 16), (window_left, 16))) # {window_top,window_left}); self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_TILED_WINDOW_STARTXY, concat((self.TILED_STARTY, 16), (self.TILED_STARTX, 16))) # TILED_STARTX+(TILED_STARTY<<16)); self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_TILED_TILE_WHS, concat((tile_vstep, 8), (tile_height, 8), (tile_width, 8))) # {8'b0,tile_vstep,tile_height,tile_width});#tile_width+(tile_height<<8)+(tile_vstep<<16)); self.x393_axi_tasks.write_contol_register(start_addr + self.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_contol_register(test_mode_address, self.TEST01_START_FRAME); for ii in range(self.TEST_INITIAL_BURST): # for (ii=0;ii= self.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, self.DEFAULT_STATUS_MODE, (ii-self.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 == self.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_contol_register(test_mode_address, self.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, self.DEFAULT_STATUS_MODE, 2 << self.STATUS_2LSB_SHFT, # bit 24 - busy, bit 25 - frame done 2 << self.STATUS_2LSB_SHFT, # mask for the 4-bit page number 0, # equal to 0) # no need to synchronize sequence number # enable_memcntrl_en_dis(channel,0); # disable channel 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 number to use. Valid values: 2, 4 use 32-byte wide columns (0 - use 16-byte ones) , do not close page between accesses (for 8 or less rows only) 2-bit number of extra pages that need to stay (not to be overwritten) in the buffer print read data 13-bit window width in 8-bursts (16 bytes) 16 bit window height , 13-bit window left margin in 8-bursts (16 bytes) 16-bit window top margin 6-bit tile width in 8-bursts (16 bytes) (0 -> 64) 6-bit tile_height (0->64) 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= self.MCNTRL_TILED_CHN2_ADDR; status_address= self.MCNTRL_TEST01_STATUS_REG_CHN2_ADDR; status_control_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN2_STATUS_CNTRL; test_mode_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN2_MODE; elif channel == 4: start_addr= self.MCNTRL_TILED_CHN4_ADDR; status_address= self.MCNTRL_TEST01_STATUS_REG_CHN4_ADDR; status_control_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN4_STATUS_CNTRL; test_mode_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN4_MODE; else: print("**** ERROR: Invalid channel, only 2 and 4 are valid"); start_addr= self.MCNTRL_TILED_CHN2_ADDR; status_address= self.MCNTRL_TEST01_STATUS_REG_CHN2_ADDR; status_control_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN2_STATUS_CNTRL; test_mode_address= self.MCNTRL_TEST01_ADDR + self.MCNTRL_TEST01_CHN2_MODE; mode= self.func_encode_mode_tiled( byte32, keep_open, extra_pages, 0, # write_mem, 1, # enable 0) # chn_reset self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_TILED_STARTADDR, self.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_contol_register(start_addr + self.MCNTRL_TILED_FRAME_FULL_WIDTH, self.FRAME_FULL_WIDTH) self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_TILED_WINDOW_WH, concat((window_height,16), (window_width, 16))) # {window_height,window_width}); self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_TILED_WINDOW_X0Y0, concat((window_top, 16), (window_left, 16))) # {window_top,window_left}); self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_TILED_WINDOW_STARTXY, concat((self.TILED_STARTY, 16), (self.TILED_STARTX, 16))) # TILED_STARTX+(TILED_STARTY<<16)); self.x393_axi_tasks.write_contol_register(start_addr + self.MCNTRL_TILED_TILE_WHS, concat((tile_vstep, 8), (tile_height, 8), (tile_width, 8))) # {8'b0,tile_vstep,tile_height,tile_width});#tile_width+(tile_height<<8)+(tile_vstep<<16)); self.x393_axi_tasks.write_contol_register(start_addr + self.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_contol_register(test_mode_address, self.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, self.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, wait_done show_data)) self.x393_axi_tasks.write_contol_register(test_mode_address, self.TEST01_NEXT_PAGE); # enable_memcntrl_en_dis(channel,0); # disable channel return result