h_addr_generator.py 4.61 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
################################################################################                                                     
## 
##   CAN with Flexible Data-Rate IP Core 
##   
##   Copyright (C) 2018 Ondrej Ille <ondrej.ille@gmail.com>
##
##   Address map generator to C header file.  
## 
##	Revision history:
##		25.01.2018	First implementation
##
################################################################################

from abc import ABCMeta, abstractmethod
from pyXact_generator.ip_xact.addr_generator import IpXactAddrGenerator

from pyXact_generator.languages.gen_h import HeaderGenerator
from pyXact_generator.languages.declaration import LanDeclaration

class HeaderAddrGenerator(IpXactAddrGenerator):

	headerGen = None
23
	prefix	= ""
24 25 26 27 28 29 30 31 32 33 34

	def __init__(self, pyXactComp, addrMap, fieldMap, busWidth):
		super().__init__(pyXactComp, addrMap, fieldMap, busWidth)
		self.headerGen = HeaderGenerator()
	
	
	def commit_to_file(self):
		for line in self.headerGen.out :
			self.of.write(line)
	

35
	def write_reg_group(self, regGroup):
36 37
		decls = []
		enumDecl = []
38
		unName = self.prefix + "_"
39
		for (j,reg) in enumerate(regGroup):
40 41 42 43 44 45 46
			for (i,field) in enumerate(sorted(reg.field, key=lambda a: a.bitOffset)):
				
				if (i == 0):
					comment = reg.name.upper()
				else:
					comment = None
				
47 48 49
				decls.append(LanDeclaration(field.name.lower(), value=0, 
							type="uint{}_t".format(self.busWidth),
							bitWidth=field.bitWidth,
50
							gap=2, alignLen=40, comment=comment,
51 52
							bitIndex=field.bitOffset + 
									((int(reg.addressOffset)*8) % self.busWidth), 
53
							intType="bitfield"))
54
							
55 56 57
			unName += reg.name.lower()
			if (j != len(regGroup) - 1):
				unName += "_"
58
			
59 60 61 62 63 64
		enumDecl = []
		enumDecl.append(LanDeclaration("u{}".format(self.busWidth),
							value=0, type="uint{}_t".format(self.busWidth),
							gap=1))
		enumDecl.append(decls)
		
65
		self.headerGen.create_union(unName, enumDecl)
66 67
		self.headerGen.wr_nl()
	
68
	
69
	def addr_reg_lookup(self, fieldReg):
70
		return super().addr_reg_lookup(fieldReg)
71
	
72 73 74 75 76 77 78 79 80 81
	
	def write_reg_enums(self, reg):
		for (i,field) in enumerate(sorted(reg.field, key=lambda a: a.bitOffset)):
			if (field.enumeratedValues == []):
				continue
			decls = []
			
			if (len(field.enumeratedValues[0].enumeratedValue) > 0):
				for es in field.enumeratedValues:
					for (i,e) in enumerate(sorted(es.enumeratedValue, key=lambda x: x.value)):
82
							decls.append(LanDeclaration((e.name).upper(), 
83 84
								e.value, intType="enum"))
							
85 86
			self.headerGen.create_enum((self.prefix + "_" + reg.name + 
										"_" + field.name).lower(), decls)
87 88 89
			self.headerGen.wr_nl()
			
	
90 91 92 93 94 95 96 97
	def write_regs(self, regs):
		regGroups = [[]]
		lowInd = 0
		
		# Sort the registers from field map into sub-lists	
		for reg in sorted(regs, key=lambda a: a.addressOffset):
			
			# We hit the register aligned create new group
98
			if (reg.addressOffset >= lowInd + self.busWidth / 8):
99 100 101 102 103 104
				lowInd = reg.addressOffset - reg.addressOffset % 4
				regGroups.append([])
	
			regGroups[-1].append(reg)
			
		for regGroup in regGroups:
105
			self.write_reg_group(regGroup)
106 107
			for reg in regGroup:
				self.write_reg_enums(reg)
108 109 110 111

	
	def write_mem_map_fields(self):
		for block in self.fieldMap.addressBlock:
112 113 114 115 116
			
			# Skip memory blocks. 
			if (block.usage == "memory"):
				continue
			
117 118 119 120 121 122 123 124 125 126 127
			self.write_regs(block.register)


	def write_mem_map_addr(self):
		
		cmnt = "{} memory map".format(self.addrMap.name)
		self.headerGen.write_comment(cmnt, 0, small=True)
		decls = []
		
		for block in self.addrMap.addressBlock:
			for reg in sorted(block.register, key=lambda a: a.addressOffset):
128
				decls.append(LanDeclaration((self.prefix + "_" + reg.name).upper(), 
129
								value=reg.addressOffset+block.baseAddress,
130 131
								intType="enum"))
		
132 133
		self.headerGen.create_enum(self.prefix.lower() + "_" + self.addrMap.name.lower(),
										decls)
134 135 136 137 138 139 140 141 142 143 144 145 146
	
	
	def write_mem_map_both(self):
		self.write_mem_map_addr()
		self.write_mem_map_fields()
	
	
	def create_addrMap_package(self, name):
		
		self.headerGen.wr_nl()
		self.headerGen.write_comment("This file is autogenerated, DO NOT EDIT!",
										0, small=True)
		self.headerGen.wr_nl()
147
		self.headerGen.create_package((self.prefix + "_" + name).upper())
148 149 150
		self.headerGen.wr_nl()
		
		if (self.addrMap):
151
			print ("Writing addresses of '%s' register map" % self.addrMap.name)
152 153 154 155 156 157 158 159 160
			self.write_mem_map_addr()
		
		self.headerGen.wr_nl()
		self.headerGen.wr_nl()
		
		self.headerGen.write_comment("Register descriptions:",
										0, small=False)
		
		if (self.fieldMap):
161
			print ("Writing bit fields of '%s' register map" % self.fieldMap.name)
162 163
			self.write_mem_map_fields()
	
164
		self.headerGen.commit_append_line(1)
165 166 167
		
	
	def write_reg(self):
168
		pass