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
################################################################################
##
## CAN with Flexible Data-Rate IP Core
##
## Copyright (C) 2018 Ondrej Ille <ondrej.ille@gmail.com>
##
## Address map generator to Lyx document from IP-XACT parsed memory map
## with pyXact framework.
##
## Revision history:
## 25.01.2018 First implementation
##
################################################################################
import math
from abc import ABCMeta, abstractmethod
from pyXact_generator.ip_xact.addr_generator import IpXactAddrGenerator
from pyXact_generator.languages.gen_lyx import LyxGenerator
from pyXact_generator.languages.declaration import LanDeclaration
from pyXact_generator.gen_lib import *
class LyxAddrGenerator(IpXactAddrGenerator):
lyxGen = None
template = None
genFieldDesc = None
genRegions = None
def __init__(self, pyXactComp, fieldMap, busWidth, genRegions=True,
genFiDesc=True):
super().__init__(pyXactComp, fieldMap, fieldMap, busWidth)
self.lyxGen = LyxGenerator()
self.genFieldDesc = str_arg_to_bool(genFiDesc)
self.genRegions = str_arg_to_bool(genRegions)
def commit_to_file(self):
for line in self.lyxGen.out :
self.of.write(line)
def reg_append_short_enums(self, field):
appendText = ""
if (field.enumeratedValues == []):
return appendText
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)):
appendText += "\\begin_inset Newline newline\\end_inset\n"
binSize = "{:0" + "{}".format(field.bitWidth) + "b}"
binFmt = binSize.format(e.value)
appendText += " 0b{} - {} - {}".format(binFmt, e.name,
e.description)
return appendText
def write_reg_field_desc(self, reg):
for field in sorted(reg.field, key=lambda a: a.bitOffset):
self.lyxGen.insert_layout("Description")
descText = field.description
descText += self.reg_append_short_enums(field)
self.lyxGen.wr_line("{} {}\n".format(field.name, descText))
self.lyxGen.commit_append_line(1)
def getBit(self, val, bitIndex):
tmp = "{0:032b}".format(val)
return tmp[31 - bitIndex]
def reg_unwrap_fields(self, reg):
retVal = [[], [], [], []]
subRegIndex = 0
highVal = 0
for i in range(0, int(reg.size / 8)):
for j in range(0, 8):
retVal[i].append([])
# Check if such a field exists
fieldExist = False
for field in sorted(reg.field, key=lambda a: a.bitOffset):
tmp = (7 - j) + i * 8
if (field.bitOffset <= tmp and
field.bitOffset + field.bitWidth > tmp):
fieldExist = True
break;
# Insert the field or reserved field
if (fieldExist):
fieldName = field.name
if (field.resets != None and field.resets.reset != None):
fieldRst = self.getBit(field.resets.reset.value,
tmp - field.bitOffset)
else:
fieldRst = "X"
# If the field is overllaped over several 8 bit registers
# add index to define it more clearly
if (int(field.bitOffset / 8) !=
int((field.bitOffset + field.bitWidth - 1) / 8)):
hInd = min(field.bitOffset + field.bitWidth - 1,
((i + 1) * 8) - 1)
lInd = max(field.bitOffset, (i * 8))
hInd = hInd - field.bitOffset
lInd = lInd - field.bitOffset
append = "[{}".format(hInd)
if (hInd != lInd):
append += ":{}]".format(lInd)
else:
append += "]"
fieldName = fieldName + append
else:
fieldName = "Reserved"
fieldRst = "-"
retVal[i][j].append(fieldName)
retVal[i][j].append(fieldRst)
return retVal
def merge_common_fields(self, table, rowIndices, startCol=0, endCol=None):
prevName = ""
multiOpts = []
if (endCol == None):
endCol = len(table[1][0])
for i,row in enumerate(table[1]):
if (i in rowIndices):
highInd = 0
lowInd = 32
for j,cell in enumerate(row):
if (j >= startCol and j <= endCol):
multicolumn = (prevName == cell[2])
if (multicolumn):
mcVal = "2"
lowInd = j
else:
mcVal = "1"
highInd = j
prevName = cell[2]
self.lyxGen.set_cell_option(table, i, j, "multicolumn",
mcVal)
# Set the right panel if end is present
if (lowInd == len(row) - 1):
self.lyxGen.set_cell_option(table, i, highInd,
"rightline", "true")
def write_reg_field_table(self, reg):
regFields = self.reg_unwrap_fields(reg)
for i in reversed(range(1, int(reg.size / 8 + 1))):
table = self.lyxGen.build_table(9, 3)
# Set the width
self.lyxGen.set_columns_option(table, range(1,9),
[["width", "1.4cm"] for j in range(1, 9)])
rows = [[row, j + 1] for j in range(8) for row in range(3)]
# Title row
self.lyxGen.set_cell_object(table, 0, 0, "Bit index")
bitIndexes = [str((8 * i) - j) for j in range(1,9)]
self.lyxGen.set_cells_object(table, [[0, j + 1] for j in range(8)],
bitIndexes)
# Field name row
self.lyxGen.set_cell_object(table, 1, 0, "Field name")
cells = [[1, j + 1] for j in range(8)]
fieldNames = [regFields[i - 1][j][0] for j in range(8)]
self.lyxGen.set_cells_object(table, cells, fieldNames)
# Restart value row
self.lyxGen.set_cell_object(table, 2, 0, "Reset value")
cells = [[2, j + 1] for j in range(8)]
rstVals = [regFields[i - 1][j][1] for j in range(8)]
self.lyxGen.set_cells_object(table, cells, rstVals)
# Merge adjacent fields with the same names
self.merge_common_fields(table, [1], startCol=1)
self.lyxGen.insert_table(table)
def write_regs(self, block):
# Memory type blocks dont need to be described by field! We use it
# to express mapping to other registers and thus It means we dont
# want unnecessary words described!
if (block.usage == "memory"):
return
for reg in sorted(block.register, key=lambda a: a.addressOffset):
# Add the Section title
self.lyxGen.write_layout_text("Subsection", "{}\n".format(reg.name),
label="label")
# Register type, address, size and description
self.lyxGen.write_layout_text("Description", "Type: {}\n".format(
reg.access))
self.lyxGen.write_layout_text("Description", "Address: {}\n".format(
"0x{:X}".format(reg.addressOffset +
block.baseAddress)))
pluralAp = "s" if (reg.size > 8) else ""
self.lyxGen.write_layout_text("Description", "Size: {} byte{}\n".format(
int(reg.size / 8), pluralAp))
self.lyxGen.write_layout_text("Standard", "{}\n".format(
reg.description))
# Bit table and bit field descriptions
if (self.genFieldDesc == True):
self.write_reg_field_table(reg)
self.write_reg_field_desc(reg)
# Separation from next register
self.lyxGen.insert_layout("Standard")
self.lyxGen.insert_inset("VSpace bigskip")
self.lyxGen.commit_append_line(2)
def write_mem_map_title(self):
self.lyxGen.write_layout_text("Chapter", "{}\n".format(
self.fieldMap.displayName), label="label")
self.lyxGen.write_layout_text("Standard", "{}\n".format(self.fieldMap
.description))
def write_mem_map_regions(self, memMap):
table = self.lyxGen.build_table(2, len(memMap.addressBlock) + 1)
self.lyxGen.set_columns_option(table, range(0,2),
[["width", "4cm"] for j in range(0, 2)])
titleCells = [[0, 0] , [0, 1]]
nameCells = [[i, 0] for i in range(1, len(memMap.addressBlock) + 1)]
addrCells = [[i, 1] for i in range(1, len(memMap.addressBlock) + 1)]
nameVals = [block.displayName for block in memMap.addressBlock]
addrVals = ["0x{:03X}".format(block.baseAddress) for block in memMap.addressBlock]
titleVals = ["Memory region", "Address offset"]