################################################################################                                                     
## 
## Register map generation tool
##
## Copyright (C) 2018 Ondrej Ille <ondrej.ille@gmail.com>
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this SW component and associated documentation files (the "Component"),
## to deal in the Component without restriction, including without limitation
## the rights to use, copy, modify, merge, publish, distribute, sublicense,
## and/or sell copies of the Component, and to permit persons to whom the
## Component is furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included in
## all copies or substantial portions of the Component.
##
## THE COMPONENT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
## AUTHORS OR COPYRIGHTHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
## FROM, OUT OF OR IN CONNECTION WITH THE COMPONENT OR THE USE OR OTHER DEALINGS
## IN THE COMPONENT.
##
###############################################################################

###############################################################################
##   
##   Class for generation of VHDL register map entity from IP-XACT 
##   specification.
##
##	Revision history:
##		25.11.2018	Implemented the script
##      27.11.2018  Changed implementation to be a class
##
################################################################################

import argparse
import sys
import time
import importlib.util
import os
import inspect
import math

from .gen_lib import *
from .ip_xact.vhdl_reg_map_generator import VhdlRegMapGenerator

from shutil import copyfile

class VhdlRegMapGeneratorWrapper():

	# File with license which should be placed to header of the all source code files
	licPath = ""

	# Path to a IP-XACT specification file with register maps
	xactSpec = ""

	# Name of the IP-XACT Memory map which should be used for VHDL package generatio.
	memMap = None

	# Size of the access bus word. Register bit field offsets are concatenated into 
	# word width size instead of simple offset from beginning of register. (E.g. 32 bit  ->
	# bitfields from first four 8-bit register are concatenated into 32 bit values)
	wordWidth = 32

	# When set to "True" read data are read with one clock cycle delay. When set to 
	# false read data are available within the same clock cycle
	registeredRead = True

	# Output directory where to write VHDL register map implementation.
	outDir = ""


	# Variable for loaded license Text
	lic_text = ""


	def write_reg_map_package(self, vhdlGen, dir_path):
		"""
		Create package with records for register blocks within an address block.
		"""
		reg_map_pkg_name = os.path.join(dir_path, vhdlGen.memMap.name.lower() + "_pkg.vhd")
		
		of = open(reg_map_pkg_name, 'w')
		vhdlGen.set_of(of)

		write_license(self.lic_text, '-', of)
		vhdlGen.write_reg_map_pkg()
		vhdlGen.commit_to_file()

		of.close()


	def write_reg_map_implementation(self, vhdlGen, dir_path):
		"""
		Write register map implementation. Create separate entity file for
		each register memory block.
		"""
		for block in vhdlGen.memMap.addressBlock:
			print("Processing memory block: " + block.name)
			
			if (block.usage == "register"):
				file_path = os.path.join(dir_path, block.name.lower() + "_reg_map.vhd")

				of = open(file_path, 'w')
				vhdlGen.set_of(of)

				write_license(self.lic_text, '-', of)
				vhdlGen.write_reg_block(block)
				vhdlGen.commit_to_file()

				of.close()

			else:
				print("Skipping unsupported block type: " + block.usage)

			print("\n")


	def copy_reg_map_sources(self, vhdlGen, dir_path, destDir):
		"""
		Copy VHDL templates to destination directory!
		"""
		for templ_name, templ_path in vhdlGen.template_sources.items():
			src_path = os.path.join(ROOT_PATH, templ_path)
			dest_path = os.path.join(ROOT_PATH, destDir)
			dest_path = os.path.join(dest_path, os.path.basename(templ_path))

			copyfile(src_path, dest_path)


	def do_update(self):

		with open(self.xactSpec) as f:
			name = None
			offset = 0

			# Load IP-Xact component
			component = Component()
			component.load(f)

			# Create new VHDL register map generator
			vhdlGen = VhdlRegMapGenerator(component, self.memMap, self.wordWidth)

			# Load license text
			self.lic_text = ""
			if (self.licPath != ""):
				self.lic_text = load_license(self.licPath)

			# Check output directory
			dir_path = os.path.join(ROOT_PATH, self.outDir)
			if (not os.path.isdir(dir_path)):
				print("ERROR: " + dir_path + " is not a directory")
				sys.exit(1)

			# Configure registered / non-registered read
			if (str_arg_to_bool(self.registeredRead)):
				vhdlGen.registered_read = True
			else:
				vhdlGen.registered_read = False

			# Create common package for whole address map
			self.write_reg_map_package(vhdlGen, dir_path)

			# Create implementation of each register block within address map
			self.write_reg_map_implementation(vhdlGen, dir_path)

			# Copy source templates to destination directory
			self.copy_reg_map_sources(vhdlGen, dir_path, self.outDir)


	if __name__ == '__main__':
		self.do_update()

