x393_mcntrl_buffers.py 10.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
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 <http:#www.gnu.org/licenses/>.

@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
34
#from import_verilog_parameters import VerilogParameters
35
from x393_mem import X393Mem
36 37
#from x393_axi_control_status import X393AxiControlStatus
import x393_axi_control_status
38 39 40
#from verilog_utils import * # concat, bits 
#from verilog_utils import hx, concat, bits, getParWidth 
#from verilog_utils import concat, getParWidth
41 42
#from x393_axi_control_status import concat, bits
import vrlg 
43 44 45 46 47 48 49 50 51 52 53
class X393McntrlBuffers(object):
    DRY_MODE= True # True
    DEBUG_MODE=1
#    vpars=None
    x393_mem=None
    x393_axi_tasks=None #x393X393AxiControlStatus
    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)
54 55
#        self.x393_axi_tasks=X393AxiControlStatus(debug_mode,dry_mode)
        self.x393_axi_tasks=x393_axi_control_status.X393AxiControlStatus(debug_mode,dry_mode)
56
#        self.__dict__.update(VerilogParameters.__dict__["_VerilogParameters__shared_state"]) # Add verilog parameters to the class namespace
57
        try:
58
            self.verbose=vrlg.VERBOSE
59 60 61 62 63 64 65 66
        except:
            pass
    def write_block_scanline_chn(self,       #
                                 chn,        # input   [3:0] chn; // buffer channel
                                 page,       # input   [1:0] page;
                                 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;
67 68 69 70 71 72 73 74 75 76
        """
        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))
77 78 79 80 81
        if   chn == 0:  start_addr=vrlg.MCONTR_BUF0_WR_ADDR + (page << 8)
        elif chn == 1:  start_addr=vrlg.MCONTR_BUF1_WR_ADDR + (page << 8)
        elif chn == 2:  start_addr=vrlg.MCONTR_BUF2_WR_ADDR + (page << 8)
        elif chn == 3:  start_addr=vrlg.MCONTR_BUF3_WR_ADDR + (page << 8)
        elif chn == 4:  start_addr=vrlg.MCONTR_BUF4_WR_ADDR + (page << 8)
82 83
        else:
            print("**** ERROR: Invalid channel for write_block_scanline_chn = %d"% chn)
84
            start_addr = vrlg.MCONTR_BUF0_WR_ADDR+ (page << 8);
85 86 87 88 89 90
        num_words=num_bursts << 2;
        self.write_block_incremtal (start_addr, num_words, (startX<<2) + (startY<<16));# 1 of startX is 8x16 bit, 16 bytes or 4 32-bit words

    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)
91 92 93 94 95
        """
        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
        """
96 97 98 99 100
        xor=0
        if (isinstance (num_words_or_data_list,list) or isinstance (num_words_or_data_list,tuple)) and (len(num_words_or_data_list) == 2):
            xor=num_words_or_data_list[1]
            num_words_or_data_list=num_words_or_data_list[0]
                    
101
        if isinstance (num_words_or_data_list,(int,long)):
102 103
            data=[]
            for i in range(num_words_or_data_list):
104
                data.append(xor ^(i | (((i + 7) & 0xff) << 8)  | (((i + 23) & 0xff) << 16) | (((i + 31) & 0xff) << 24)))
105 106 107 108 109
        else:
            data=num_words_or_data_list
        if self.verbose>0:
            print("**** write_block_buf, start_word_address=0x%x, num+words=0x%x"%(start_word_address,len(data)))
        for i,d in enumerate(data):
110
#            d= i | (((i + 7) & 0xff) << 8)  | (((i + 23) & 0xff) << 16) | (((i + 31) & 0xff) << 24)
111 112 113 114 115 116 117 118
            if self.verbose>2:
                print("     write_block_buf 0x%x:0x%x"%(start_word_address+i,d))
            self.x393_mem.axi_write_single_w(start_word_address+i, d)

    def write_block_incremtal(self,
                              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;      
119 120 121 122 123 124
        """
        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)
        """
125 126 127 128 129 130 131 132 133 134 135
        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):
            if self.verbose>2:
                print("     write_block_buf 0x%x:0x%x"%(start_word_address+i,start_value+i))
            self.x393_mem.axi_write_single_w(start_word_address+i, start_value+i)

    def write_block_buf_chn(self,       #
                            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)
136 137
        """
        Fill specified buffer with the pattern data
138 139 140
        @param chn                    4-bit buffer channel (0..4) to write data to
        @param page                   2-bit buffer page to write to
        @param num_words_or_data_list> number of 32-bit words to generate/write or a list with integer data
141
        """
142 143 144 145 146 147 148
        print("===write_block_buf_chn() chn=0x%x, page=0x%x"%(chn,page), end=" ")
        if isinstance (num_words_or_data_list,list):
            try:
                print("=== [0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,...]"%tuple(num_words_or_data_list[:8]),end="")
            except:
                print("=== [%s]"%str(num_words_or_data_list))
        print("===")    
149
        start_addr=-1
150 151 152 153 154
        if   chn==0:start_addr=vrlg.MCONTR_BUF0_WR_ADDR + (page << 8)
        elif chn==1:start_addr=vrlg.MCONTR_BUF1_WR_ADDR + (page << 8)
        elif chn==2:start_addr=vrlg.MCONTR_BUF2_WR_ADDR + (page << 8)
        elif chn==3:start_addr=vrlg.MCONTR_BUF3_WR_ADDR + (page << 8)
        elif chn==4:start_addr=vrlg.MCONTR_BUF4_WR_ADDR + (page << 8)
155 156
        else:
            print("**** ERROR: Invalid channel for write buffer = %d"% chn)
157
            start_addr = vrlg.MCONTR_BUF0_WR_ADDR+ (page << 8)
158
            
159 160 161 162 163 164
        self.write_block_buf (start_addr, num_words_or_data_list)
    
    def read_block_buf(self, 
                       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):
165 166 167 168 169 170 171
        """
        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
        """
        
172
        if (self.verbose>1) or show_rslt:
173 174 175 176 177 178 179 180 181 182 183 184 185 186
            print("**** read_block_buf, start_word_address=0x%x, num_read=0x%x "%(start_word_address,num_read))
        result=[]    
        for i in range(num_read): #for (i = 0; i < num_read; i = i + 16) begin
            d=self.x393_mem.axi_read_addr_w(start_word_address+i)
            if (self.verbose>2) or show_rslt:
                print("     read_block_buf 0x%x:0x%x"%(start_word_address+i,d))
            result.append(d)
        return result

    def read_block_buf_chn(self,  # S uppressThisWarning VEditor : may be unused
                           chn, # input [3:0] chn; # buffer channel
                           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):
187 188 189 190 191 192 193
        """
        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
        """
194
        start_addr=-1
195 196 197 198 199
        if   chn==0:  start_addr=vrlg.MCONTR_BUF0_RD_ADDR + (page << 8)
        elif chn==1:  start_addr=vrlg.MCONTR_BUF1_RD_ADDR + (page << 8)
        elif chn==2:  start_addr=vrlg.MCONTR_BUF2_RD_ADDR + (page << 8)
        elif chn==3:  start_addr=vrlg.MCONTR_BUF3_RD_ADDR + (page << 8)
        elif chn==4:  start_addr=vrlg.MCONTR_BUF4_RD_ADDR + (page << 8)
200 201
        else:
            print("**** ERROR: Invalid channel for read buffer = %d"%chn)
202
            start_addr = vrlg.MCONTR_BUF0_RD_ADDR+ (page << 8)
203 204
        result=self.read_block_buf (start_addr, num_read, show_rslt)
        return result