x393_mem.py 6.28 KB
Newer Older
1
from __future__ import print_function
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 34 35 36 37
'''
# Copyright (C) 2015, Elphel.inc.
# Memory read/write functions 
# 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 mmap
#import sys
import struct
class X393Mem(object):
    '''
    classdocs
    '''
38
    DRY_MODE= True # True
39 40 41 42 43
    PAGE_SIZE=4096
    DEBUG_MODE=1
    ENDIAN="<" # little, ">" for big
    AXI_SLAVE0_BASE=0x40000000

44
    def __init__(self, debug_mode=1,dry_mode=True):
45 46 47
        self.DEBUG_MODE=debug_mode
        self.DRY_MODE=dry_mode
    def write_mem (self,addr, data):
48 49 50 51 52
        """
        Write 32-bit word to physical memory
        <addr> - physical byte address
        <data> - 32-bit data to write
        """
53
        if self.DRY_MODE:
54
            print ("simulated: write_mem(0x%x,0x%x)"%(addr,data))
55 56 57 58 59 60
            return
        with open("/dev/mem", "r+b") as f:
            page_addr=addr & (~(self.PAGE_SIZE-1))
            page_offs=addr-page_addr
            if (page_addr>=0x80000000):
                page_addr-= (1<<32)
61 62 63 64 65 66
            mm = mmap.mmap(f.fileno(), self.PAGE_SIZE, offset=page_addr)
            packedData=struct.pack(self.ENDIAN+"L",data)
            d=struct.unpack(self.ENDIAN+"L",packedData)[0]
            mm[page_offs:page_offs+4]=packedData
            if self.DEBUG_MODE > 2:
                print ("0x%08x <== 0x%08x (%d)"%(addr,d,d))
67 68 69 70 71 72 73 74 75 76 77
        '''    
        if MONITOR_EMIO and VEBOSE:
            gpio0=read_mem (0xe000a068)
            gpio1=read_mem (0xe000a06c)
            print("GPIO: %04x %04x %04x %04x"%(gpio1>>16, gpio1 & 0xffff, gpio0>>16, gpio0 & 0xffff))
            if ((gpio0 & 0xc) != 0xc) or ((gpio0 & 0xff00) != 0):
                print("******** AXI STUCK ************")
                exit (0)
        '''    

    def read_mem (self,addr):
78 79 80 81
        '''
         Read 32-bit word from physical memory
         <addr> - physical byte address
        '''    
82
        if self.DRY_MODE:
83
            print ("simulated: read_mem(0x%x)"%(addr))
84
            return addr # just some data
85 86 87 88 89 90 91 92 93 94 95 96
        with open("/dev/mem", "r+b") as f:
            page_addr=addr & (~(self.PAGE_SIZE-1))
            page_offs=addr-page_addr
            if (page_addr>=0x80000000):
                page_addr-= (1<<32)
            mm = mmap.mmap(f.fileno(), self.PAGE_SIZE, offset=page_addr)
            data=struct.unpack(self.ENDIAN+"L",mm[page_offs:page_offs+4])
            d=data[0]
            if self.DEBUG_MODE > 2:
                print ("0x%08x ==> 0x%08x (%d)"%(addr,d,d))
            return d
#        mm.close() #probably not needed with "with"
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
    def mem_dump (self,start_addr,end_addr=0):
        '''
         Read and print memory range from physical memory
         <start_addr> - physical byte start address
         <end_addr> - physical byte end address (inclusive)
         Returns list of read values
        '''
        start_addr &= 0xfffffffc
        end_addr &=   0xfffffffc
        if end_addr<start_addr:
            end_addr = start_addr
        rslt=[]
        if self.DRY_MODE:
            rslt=range(start_addr,end_addr+1,4)
        else:
            with open("/dev/mem", "r+b") as f:
                for addr in range (start_addr,end_addr+4,4):
                    page_addr=addr & (~(self.PAGE_SIZE-1))
                    page_offs=addr-page_addr
                    if (page_addr>=0x80000000):
                        page_addr-= (1<<32)
                    mm = mmap.mmap(f.fileno(), self.PAGE_SIZE, offset=page_addr)
                    data=struct.unpack(self.ENDIAN+"L",mm[page_offs:page_offs+4])
                    rslt.append(data[0])
                    
        for addr in range (start_addr,end_addr+4,4):
            if (addr == start_addr) or ((addr & 0x3f) == 0):
124 125 126 127
                if self.DRY_MODE:
                    print ("\nsimulated: 0x%08x:"%addr,end="")
                else:     
                    print ("\n0x%08x:"%addr,end="")
128 129 130 131
            d=rslt[(addr-start_addr) >> 2]
            print ("%08x "%d,end=""),
        print("")
        return rslt    
132
    '''
133
    Read/write slave AXI using byte addresses relative to the AXI memory region
134 135
    '''
    def axi_write_single(self,addr,data):
136 137 138 139 140
        """
        Write 32-bit word to the slave AXI address range
        <addr> - physical byte address relative to the slave AXI memory region
        <data> - 32-bit data to write
        """
141 142 143
        self.write_mem(self.AXI_SLAVE0_BASE+addr,data)

    def axi_read_addr(self,addr):
144 145 146 147
        """
        Read 32-bit word from the  slave AXI address range
        <addr> - physical byte address relative to slave AXI AXI memory region
        """
148 149 150 151
        return self.read_mem(self.AXI_SLAVE0_BASE+addr)
    '''
    Read/write slave AXI using 32-bit word addresses (same as in Verilog code)
    '''
152
    def axi_write_single_w(self,addr,data,verbose=0):
153 154 155 156
        """
        Write 32-bit word to the slave AXI address range, using 32-word address
        <addr> - 32-bit word (register) address relative to the slave AXI memory region
        <data> - 32-bit data to write
157
        <verbose> print data being written (default: 0)
158
        """
159 160
        if verbose:
            print("axi_write_single_w(0x%x,0x%08x)"%(addr,data))
161 162 163
        self.axi_write_single(addr<<2,data)

    def axi_read_addr_w(self,addr):
164 165 166 167
        """
        Read 32-bit word from the slave AXI address range, using 32-word address
        <addr> - 32-bit word (register) address relative to the slave AXI memory region
        """
168
        return self.axi_read_addr(addr<<2)