#!/usr/bin/python

import sys
import rr
import time


class CCSR:

	def __init__(self, bus, base_addr, reg_map=None):
		self.base_addr = base_addr;
		self.bus = bus;
                self.reg_map = reg_map

	def wr_reg(self, addr, val):
		#print("                wr:%.8X reg:%.8X")%(val,(self.base_addr+addr))
		self.bus.iwrite(0, self.base_addr +  addr, 4, val)

	def rd_reg(self, addr):
		reg = self.bus.iread(0, self.base_addr + addr, 4)
		#print("                reg:%.8X value:%.8X")%((self.base_addr+addr), reg)
		return reg

	def wr_bit(self, addr, bit, value):
		reg = self.rd_reg(addr)
		if(0==value):
			reg &= ~(1<<bit)
		else:
			reg |= (1<<bit)
		self.wr_reg(addr, reg)


	def rd_bit(self, addr, bit):
		if(self.rd_reg(addr) & (1<<bit)):
			return 1
		else:
			return 0

        #--------------------------------------------
        # Get register's field value
        def get_field(self, reg, field):
            if(reg in self.reg_map[1]): # test if register exist in register map
                if(field in self.reg_map[1][reg][2]): # test if field exist in register

                    reg_addr = self.reg_map[1][reg][0]
                    field_mask = self.reg_map[1][reg][2][field][2]
                    field_offset = self.reg_map[1][reg][2][field][0]

                    reg_val = self.rd_reg(reg_addr)
                    reg_val = (field_mask & (reg_val >> field_offset))
                    return reg_val
                else:
                    raise CSRDeviceOperationError(self.base_addr, self.reg_map, 'Requested field (%s) doesn\'t exist.'%field)
            else:
                raise CSRDeviceOperationError(self.base_addr, self.reg_map, 'Requested register (%s) doesn\'t exist.'%reg)



        # Set register's field value
        def set_field(self, reg, field, value):
            if(reg in self.reg_map[1]): # test if register exist in register map
                if(field in self.reg_map[1][reg][2]): # test if field exist in register

                    reg_addr = self.reg_map[1][reg][0]
                    field_mask = self.reg_map[1][reg][2][field][2]
                    field_offset = self.reg_map[1][reg][2][field][0]

                    reg_val = self.rd_reg(reg_addr)
                    reg_val &= ~(field_mask << field_offset)
                    reg_val |= ((field_mask & value) << field_offset)
                    self.wr_reg(reg_addr, reg_val)
                    return reg_val
                else:
                    raise CSRDeviceOperationError(self.base_addr, self.reg_map, 'Requested field (%s) doesn\'t exist.'%field)
            else:
                raise CSRDeviceOperationError(self.base_addr, self.reg_map, 'Requested register (%s) doesn\'t exist.'%reg)

        # Set register value
        def set_reg(self, reg, value):
            if(reg in self.reg_map[1]): # test if register exist in register map
                self.wr_reg(self.reg_map[1][reg][0], value)
            else:
                raise CSRDeviceOperationError(self.base_addr, self.reg_map, 'Requested register (%s) doesn\'t exist.'%reg)

        # Get register value
        def get_reg(self, reg):
            if(reg in self.reg_map[1]): # test if register exist in register map
                return self.rd_reg(self.reg_map[1][reg][0])
            else:
                raise CSRDeviceOperationError(self.base_addr, self.reg_map, 'Requested register (%s) doesn\'t exist.'%reg)

        # Print all register map
        def print_reg_map(self):
            print "\n%s:" % (self.reg_map[0])
            print "--------------------------------------------------"
            # loop over registers and sort them by address offset
            for reg in sorted(self.reg_map[1].iteritems(), key=lambda (k,v): v[0]):
                value = self.get_reg(reg[0])
                print " * %-50s:0x%08X (%d)" % (reg[1][1],value, value)
                # loop over fields and sort them by position
                for field in sorted(reg[1][2].iteritems(), key=lambda (k,v): v[0]):
                    value = self.get_field(reg[0], field[0])
                    print "   - %-48s:0x%X (%d)" % (field[1][1],value, value)
                if(len(reg[1][2]) != 0):
                    print ''



