Commit 66c790ed authored by Ille, Ondrej, Ing.'s avatar Ille, Ondrej, Ing.

Removed Reg. map gen to merge new reg. map gen as sub-module.

parent ff941cbf
################################################################################
##
## CAN with Flexible Data-Rate IP Core
##
## Copyright (C) 2018 Ondrej Ille <ondrej.ille@gmail.com>
##
## Library with auxiliarly functions for pyXact generator.
##
## Revision history:
## 24.01.2018 First implementation based on the previous stand-alone
## script for generation of VHDL package
##
################################################################################
import argparse
import sys
import time
import importlib.util
import os
import inspect
import math
################################################################################
# File path to the local repo of the PyXact framework
################################################################################
PYXACT_PATH = "./pyXact_generator/ipyxact_parser"
sys.path.insert(0, PYXACT_PATH)
from ipyxact.ipyxact import Component
from license_updater import *
def open_output(output):
return open(output, 'w')
def split_string(input, size):
return [input[start:start+size] for start in range(0, len(input), size)]
def str_arg_to_bool(input):
if (input == "yes" or
input == "true" or
input == "True" or
input == "y"):
return True
else:
return False
################################################################################
##
## CAN with Flexible Data-Rate IP Core
##
## Copyright (C) 2018 Ondrej Ille <ondrej.ille@gmail.com>
##
## Base class for specific address Map generators.
## Two separate address maps are considered. Map for address creation
## and map for bitfields, enums and reset values creation.
##
## Revision history:
## 25.01.2018 First implementation
##
################################################################################
from abc import ABCMeta, abstractmethod
class IpXactAddrGenerator(metaclass=ABCMeta):
addrMap = None
fieldMap = None
busWidth = None
of = None
def __init__(self, pyXactComp, addrMap, fieldMap, busWidth):
self.busWidth = busWidth
if (not pyXactComp.memoryMaps):
return None
for map in pyXactComp.memoryMaps.memoryMap:
if map.name == addrMap:
self.addrMap = map
if map.name == fieldMap:
self.fieldMap = map
def commit_to_file(self, of, text):
"""
Write a text into the output file
Arguments:
of Open output file
text List of strings to write
"""
for line in text :
of.write(line)
def set_of(self, of):
"""
Sets the output file to the internal output file of instance
Arguments:
of Output file to set
"""
self.of = of
def move_till_text(self, of, text):
"""
Move till text in a file. The file must be opened for reading.
Arguments:
of Output file
text Text until which to move in a file
"""
line = "BEGIN"
while (line != None):
line = of.read()
if (line == text):
break
def addr_reg_lookup(self, fieldReg):
"""
Search the "addrMap" for register with the same address offset aligned
to "busWidth" and return it.
Arguments:
fieldReg Register from the field map to search for in the address
map.
"""
for block in self.addrMap.addressBlock:
for reg in block.register:
if (reg.addressOffset * 4 == fieldReg.addressOffset):
return reg
return None
@abstractmethod
def write_mem_map_addr(self):
"""
Write the address map into the generator output.
"""
pass
@abstractmethod
def write_mem_map_fields(self):
"""
Write the register field map with reset values, bit indices and enums
into the output generator.
"""
pass
@abstractmethod
def write_mem_map_both(self):
"""
Write address map and field map into the generator output.
"""
pass
@abstractmethod
def write_reg(self, reg, writeFields, writeRstVal, writeEnums):
"""
Write single register into the generator output.
Arguments:
writeFields If fields indices should be written.
writeRstVal If Reset values should be written
writeEnums If Enum values should be written.
"""
pass
\ No newline at end of file
################################################################################
##
## 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
prefix = ""
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)
def write_reg_group(self, regGroup):
decls = []
enumDecl = []
unName = self.prefix + "_"
for (j,reg) in enumerate(regGroup):
for (i,field) in enumerate(sorted(reg.field, key=lambda a: a.bitOffset)):
if (i == 0):
comment = reg.name.upper()
else:
comment = None
decls.append(LanDeclaration(field.name.lower(), value=0,
type="uint{}_t".format(self.busWidth),
bitWidth=field.bitWidth,
gap=2, alignLen=40, comment=comment,
bitIndex=field.bitOffset +
((int(reg.addressOffset)*8) % self.busWidth),
intType="bitfield"))
unName += reg.name.lower()
if (j != len(regGroup) - 1):
unName += "_"
enumDecl = []
enumDecl.append(LanDeclaration("u{}".format(self.busWidth),
value=0, type="uint{}_t".format(self.busWidth),
gap=1))
enumDecl.append(decls)
self.headerGen.create_union(unName, enumDecl)
self.headerGen.wr_nl()
def addr_reg_lookup(self, fieldReg):
return super().addr_reg_lookup(fieldReg)
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)):
decls.append(LanDeclaration((e.name).upper(),
e.value, intType="enum"))
self.headerGen.create_enum((self.prefix + "_" + reg.name +
"_" + field.name).lower(), decls)
self.headerGen.wr_nl()
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
if (reg.addressOffset >= lowInd + self.busWidth / 8):
lowInd = reg.addressOffset - reg.addressOffset % 4
regGroups.append([])
regGroups[-1].append(reg)
for regGroup in regGroups:
self.write_reg_group(regGroup)
for reg in regGroup:
self.write_reg_enums(reg)
def write_mem_map_fields(self):
for block in self.fieldMap.addressBlock:
# Skip memory blocks.
if (block.usage == "memory"):
continue
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):
decls.append(LanDeclaration((self.prefix + "_" + reg.name).upper(),
value=reg.addressOffset+block.baseAddress,
intType="enum"))
self.headerGen.create_enum(self.prefix.lower() + "_" + self.addrMap.name.lower(),
decls)
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()
self.headerGen.create_package((self.prefix + "_" + name).upper())
self.headerGen.wr_nl()
if (self.addrMap):
print ("Writing addresses of '%s' register map" % self.addrMap.name)
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):
print ("Writing bit fields of '%s' register map" % self.fieldMap.name)
self.write_mem_map_fields()
self.headerGen.commit_append_line(1)
def write_reg(self):
pass
This diff is collapsed.
################################################################################
##
## CAN with Flexible Data-Rate IP Core
##
## Copyright (C) 2018 Ondrej Ille <ondrej.ille@gmail.com>
##
## Address map generator to VHDL package with constants from IP-XACT memory
## map defined by pyXact framework.
##
## 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_vhdl import VhdlGenerator
from pyXact_generator.languages.declaration import LanDeclaration
class VhdlAddrGenerator(IpXactAddrGenerator):
vhdlGen = None
def __init__(self, pyXactComp, addrMap, fieldMap, busWidth):
super().__init__(pyXactComp, addrMap, fieldMap, busWidth)
self.vhdlGen = VhdlGenerator()
def commit_to_file(self):
"""
Commit the generator output into the output file.
"""
for line in self.vhdlGen.out :
self.of.write(line)
def write_reg_enums(self, field):
"""
Write register enums values as VHDL constants (std_logic) into the
generator output.
Arguments:
field Register field object (parsed from pyXact) whose
enums to write.
"""
if (field.enumeratedValues == []):
return False
self.vhdlGen.wr_nl()
self.vhdlGen.write_comment('"{}" field enumerated values'.format(
field.name), 2, small=True)
for es in field.enumeratedValues:
for e in sorted(es.enumeratedValue, key=lambda x: x.value):
decl = LanDeclaration(e.name, e.value, "std_logic",
field.bitWidth, "constant", 50)
self.vhdlGen.write_decl(decl)
def write_res_vals(self, field):
"""
Write restart values of register field as VHDL constants (std_logic)
into the generator output.
Arguments:
field Register field object (parsed from pyXact) whose
restart values to write.
"""
if (field.resets == None):
return False
if (field.resets.reset == None):
return False
decl = LanDeclaration(field.name+"_RSTVAL", field.resets.reset.value,
"std_logic", field.bitWidth, "constant", 50)
self.vhdlGen.write_decl(decl)
def write_reg_field(self, field, reg):
"""
Write register field indices as VHDL constants. Use the "busWidth"
property to concatenate the register indices into word aligned sizes.
E.g. register with 0x1 offset will start at index 8, 0x2 at index 16 etc...
Write into the generator output.
Arguments:
field Register field object (parsed from pyXact) whose
field indices to write.
reg Register object (parsed from pyXact) to which belongs
the field in previous argument.
"""
bitIndexL = field.bitOffset
bitIndexH = field.bitOffset + field.bitWidth-1
bitIndexL = bitIndexL + ((reg.addressOffset*8) % self.busWidth)
bitIndexH = bitIndexH + ((reg.addressOffset*8) % self.busWidth)
if (bitIndexH == bitIndexL):
iter = [["_IND", bitIndexL]]
else:
iter = [["_L", bitIndexL], ["_H", bitIndexH]]
for item in iter:
decl = LanDeclaration(field.name+item[0], item[1], "natural",
field.bitWidth, "constant", 50)
self.vhdlGen.write_decl(decl)
def __write_reg(self, reg, writeFields, writeEnums, writeReset):
"""
Write the register as set of VHDL constants into the generator output.
Arguments:
reg Register field object (parsed from pyXact) to write
writeFields IF bit field indices should be written.
writeEnums If Enums for each bit field should be written.
writeReset If reset values for each field should be written.
"""
# Write the register title
capt = '{} register'.format(reg.name.upper())
self.vhdlGen.write_comment(reg.description, 2, caption=capt)
#Write the individual elements
if (writeFields == True):
for field in sorted(reg.field, key=lambda a: a.bitOffset):
self.write_reg_field(field, reg)
#Write the enums (iterate separately not to mix up fields and enums)
if (writeEnums == True):
for field in reg.field:
self.write_reg_enums(field)
self.vhdlGen.wr_nl()
#Write reset values for each field
if (writeReset == True):
self.vhdlGen.write_comment("{} register reset values".format(
reg.name.upper()), 2, small=True)
for field in reg.field:
self.write_res_vals(field)
self.vhdlGen.wr_nl()
def write_regs(self, regs):
"""
Write the multiple registers as sets of VHDL constants.
Arguments:
regs List of register objects as parsed by pyxact framework.
"""
for reg in sorted(regs, key=lambda a: a.addressOffset):
self.__write_reg(reg, True, True, True)
def write_addrbl_head(self, addressBlock):
"""
Write the address block from IP-XACT memory map as VHDL constant
to generator output.
Arguments:
addressBlock Address block to write (parsed from pyXact framework)
"""
# Write capital comment with name of the address Block
self.vhdlGen.write_comm_line()
self.vhdlGen.write_comment("Address block: {}".format(addressBlock.name), 2)
self.vhdlGen.write_comm_line()
# Write the VHDL constant for Address block offset defined as:
# block.baseAddress/block.range
bitWidth = 4 # TODO: So far not bound to IP-XACT
decl = LanDeclaration(addressBlock.name+"_BLOCK",
addressBlock.baseAddress/addressBlock.range,
"std_logic", bitWidth, "constant", 80)
self.vhdlGen.write_decl(decl)
self.vhdlGen.wr_nl()
def write_addrbl_regs(self, addressBlock):
"""
Write the address block registers from IP-XACT address block to the
generator output.
Arguments:
addressBlock Address block to write as parsed by pyXact.
"""
for reg in sorted(addressBlock.register, key=lambda a: a.addressOffset):
decl = LanDeclaration(reg.name+"_ADR",
reg.addressOffset+addressBlock.baseAddress, "std_logic",
12, "constant", 80)
self.vhdlGen.write_decl(decl)
def write_mem_map_addr(self):
"""
Write address map specified at instance creation time and stored in
"addrMap".
"""
#Each Address block reflects to VHDL memory region
for block in self.addrMap.addressBlock:
self.write_addrbl_head(block)
self.write_addrbl_regs(block)
self.vhdlGen.wr_nl()
def write_mem_map_fields(self):
"""
Write field map specified at instance creation time and stored in
"addrMap".
"""
for block in self.fieldMap.addressBlock:
self.write_regs(block.register)
def write_mem_map_both(self):
"""
Write address and field map specified at instance creation time and
stored in "addrMap".
"""
self.write_mem_map_fields()
self.write_mem_map_addr()
def create_addrMap_package(self, name):
"""
Create a VHDL package to the address generator output. Insert basic
IEEE include: std_logic_1164.all
Arguments:
name VHDL pacakge name
"""
self.vhdlGen.wr_nl()
self.vhdlGen.write_comm_line(gap=0)
if (self.addrMap != None):
print ("Writing addresses of '%s' register map" % self.addrMap.name)
self.vhdlGen.write_comment("Addresses map for: {}".format(
self.addrMap.name), 0, small=True)
if (self.fieldMap != None):
print ("Writing bit fields of '%s' register map" % self.fieldMap.name)
self.vhdlGen.write_comment("Field map for: {}".format(self.fieldMap.name),
0, small=True)
self.vhdlGen.write_comment("This file is autogenerated, DO NOT EDIT!",
0, small=True)
self.vhdlGen.write_comm_line(gap=0)
self.vhdlGen.wr_nl()
self.vhdlGen.create_includes(["std_logic_1164.all"])
self.vhdlGen.wr_nl()
self.vhdlGen.create_package(name)
self.vhdlGen.wr_nl()
if (self.addrMap):
self.write_mem_map_addr()
if (self.fieldMap):
self.write_mem_map_fields()
self.vhdlGen.commit_append_line(1)
def write_reg(self, reg, writeFields, writeRstVal, writeEnums):
"""
Public version of internal function. TODO: remove the internal one
and use the public one.
"""
self.__write_reg(self, reg, writeFields, writeEnums, writeRstVal)
\ No newline at end of file
Subproject commit da2182fb69c8e49cb83da3842c2c738892e44669
################################################################################
##
## CAN with Flexible Data-Rate IP Core
##
## Copyright (C) 2018 Ondrej Ille <ondrej.ille@gmail.com>
##
## Class for language declaration of variable, constant, etc...
##
## Revision history:
## 25.01.2018 First implementation
##
################################################################################
from abc import ABCMeta, abstractmethod
class LanDeclaration(metaclass=ABCMeta):
# Declaration specifier: const, volatile ...
specifier = None