Files
vincentb.nikhef.nl b879a961da Changed I2C bitrate to 90K for better AHRS compatibility
Added errata module for correcting or bypassing board specific errors
Improved makevars build script
2017-04-25 09:17:58 +00:00

480 lines
14 KiB
Python

#
# KM3NeT CLB v2 Firmware
#
# Copyright 2013-2014 KM3NeT Collaboration
#
# All Rights Reserved.
#
#
# File : makevars.py
# Created : 25 feb 2014
# Author : Vincent van Beveren
#
from __future__ import print_function
import os, sys
import makevar_tpls as tpls
import utpl
# ---------------------------------------------------------------------------------------------
# Subsystems
# ---------------------------------------------------------------------------------------------
SUBSYSCOUNT = 6
SYS, NET, OPT, INS, ACS, BSE = range(SUBSYSCOUNT)
_SUBSYS = {
'SYS' : SYS,
'NET' : NET,
'OPT' : OPT,
'INS' : INS,
'ACS' : ACS,
'BSE' : BSE
}
_SUBSYSNAMES = {v:k for k, v in _SUBSYS.items()}
_SUBSYS_NICE_NAMES = (
"System",
"Networking & IPMux",
"Optics",
"Instrumentation",
"Acoustics",
"Base"
)
# ---------------------------------------------------------------------------------------------
# Flags & Spec
# ---------------------------------------------------------------------------------------------
READ = 0x1
WRITE = 0x2
VIRTUAL = 0x4
CONFIG = 0x8
DEPRECATED = 0x10
_ACCESS = {
'R' : READ,
'W' : WRITE,
'RW' : READ | WRITE
}
_FLAGS = {
'V' : VIRTUAL,
'C' : CONFIG,
'D' : DEPRECATED
}
# ---------------------------------------------------------------------------------------------
# Variables
# ---------------------------------------------------------------------------------------------
class VarType:
def __init__(self, name, id_, size, jtype, ctype, descr):
self.name = name
self.id = id_
self.size = size
self.jtype = jtype
self.ctype = ctype
self.descr = descr
def __repr__(self):
return "%s" % self.name
_VARIABLES = [
VarType('U8', 0x0, 1, jtype = 'byte', ctype = 'uint8_t', descr = "Unsigned 8 bit integer"),
VarType('U16', 0x1, 2, jtype = 'short', ctype = 'uint16_t', descr = "Unsigned 16 bit integer"),
VarType('U32', 0x2, 4, jtype = 'int', ctype = 'uint32_t', descr = "Unsigned 32 bit integer"),
VarType('U64', 0x3, 8, jtype = 'long', ctype = 'uint64_t', descr = "Unsigned 64 bit integer"),
VarType('I8', 0x4, 1, jtype = 'byte', ctype = 'int8_t', descr = "Signed 8 bit integer"),
VarType('I16', 0x5, 2, jtype = 'short', ctype = 'int16_t', descr = "Signed 16 bit integer"),
VarType('I32', 0x6, 4, jtype = 'int', ctype = 'int32_t', descr = "Signed 32 bit integer"),
VarType('I64', 0x7, 8, jtype = 'long', ctype = 'int64_t', descr = "Signed 64 bit integer"),
VarType('BOOL',0x8, 1, jtype = 'boolean', ctype = 'bool' , descr = "Boolean"),
VarType('F32', 0xA, 4, jtype = 'float', ctype = 'f32_t', descr = "32 Bit floating point"),
VarType('F64', 0xB, 8, jtype = 'double', ctype = 'f64_r', descr = "64 Bit floating point"),
]
_VARMAPPING = {v.name:v for v in _VARIABLES }
# ---------------------------------------------------------------------------------------------
# Variable definition
# ---------------------------------------------------------------------------------------------
class VarDef(object):
# Defines a bit of a variable
class VarValue(object):
def __init__(self, varDef, fig, name, desc):
self.varDef = varDef
self.fig = fig
self.name = name
self.desc = desc
@staticmethod
def fromColumns(varDef, elements):
if len(elements) != 9:
raise RuntimeError("Expected 9 columns")
return VarDef.VarValue(varDef,
fig = elements[1],
name = elements[2],
desc = elements[8]
)
def fullcapname(self):
return "%s_%s" % (self.varDef.fullcapname(), self.name.upper())
def __init__(self, subsys, idx, name, typ, dims, access, cfgid, flags, desc):
self.subsys = subsys
self.idx = idx
self.values = []
self.name = name
if typ not in _VARMAPPING:
raise RuntimeError("Type %s is unknown" % typ)
self.typ = _VARMAPPING[typ]
if len(dims) > 1:
raise RuntimeError("Multidimenisonal arrays not supported")
if len(dims) == 1:
if dims[0] - 1 >= (1 << 12):
raise RuntimeError("Array to big")
if dims[0] <= 1:
raise RuntimeError("Array must be atleast of length 2")
self.dims = dims
self.cfgid = cfgid
self.desc = desc
self.flags = 0
if access not in _ACCESS:
raise RuntimeError("Incorrect access type %s, expect one of %s" %
(access, _ACCESS.keys()))
self.flags |= _ACCESS[access]
for k,v in _FLAGS.items():
if k in flags: self.flags |= v
@staticmethod
def _toDims(d1, d2):
if d1 == '': return []
if d2 == '': return [int(d1)]
return [int(d1),int(d2)]
@staticmethod
def fromColumns(elements):
if len(elements) != 9:
raise RuntimeError("Expected 9 columns")
return VarDef(
subsys = _SUBSYS[elements[0]],
idx = int(elements[1]),
name = elements[2],
typ = elements[3],
dims = VarDef._toDims(elements[4], ''),
access = elements[5],
cfgid = None if elements[6] =='' else int(elements[6]),
flags = elements[7],
desc = [ elements[8] ]
)
def addValue(self, line):
self.values.append(VarDef.VarValue.fromColumns(self, line))
def byteSize(self):
return self.typ.size * (1 if len(self.dims) == 0 else self.dims[0])
def var_id(self):
vid = self.subsys << 28 | self.idx << 20 | self.typ.id << 16
if self.flags & VIRTUAL: vid |= 1 << 15
if self.flags & READ: vid |= 1 << 14
if self.flags & WRITE: vid |= 1 << 13
if self.flags & CONFIG: vid |= 1 << 12
if len(self.dims) == 1:
vid |= self.dims[0] - 1
elif len(self.dims) == 2:
raise RuntimeError("2d arrays not yet supported (sorry)")
return vid;
def field_name(self):
return self.name.lower()
def fullcapname(self):
return "%s_%s" % (_SUBSYSNAMES[self.subsys].upper(), self.name.upper())
def get_virtualsigname(self):
return "%s_%s" % (_SUBSYSNAMES[self.subsys].lower(), self.name.lower())
def c_type(self):
return self.typ.ctype
def is_array(self):
return len(self.dims) > 0
def c_type_as_ptr(self):
return self.typ.ctype + " *" + "*" * len(self.dims)
def c_virtual_link(self):
virtualsigname = self.get_virtualsigname()
link = []
if self.flags & READ:
link.append(".rd = _%s_rd" % virtualsigname)
if self.flags & WRITE:
link.append(".wr = _%s_wr" % virtualsigname)
return "\t.%s = { %s }" % (self.name.lower(), ",".join(link))
def is_virtual(self):
return self.flags & VIRTUAL
def is_read(self):
return self.flags & READ
def is_write(self):
return self.flags & WRITE
def is_configurable(self):
return self.flags & CONFIG
def is_deprecated(self):
return self.flags & DEPRECATED;
def __repr__(self):
return "%s (%s)" % (self.name, self.typ)
class VarConfig(object):
def __init__(self):
self.subs = dict(zip(_SUBSYS.values(), [{} for _ in range(len(_SUBSYS))]))
self.varTotSize = 0
self.varTotCount = 0
self.varCfgSize = 0
self.varCfgCount = 0
def max_idx(self, subsys):
return max(self.subs[subsys].keys()) if len(self.subs[subsys]) > 1 else -1
def load(self, filename):
f = open(filename)
lineno = 0
varDef = None
for line in f:
lineno += 1
columns = [l.strip(' \t\r\n\0') for l in line.split(";")]
flatline = "".join(columns).strip()
if flatline == '': continue
if flatline.startswith('#'): continue
# add comment
if len(columns) == 9:
if columns[0] == "":
continue
if columns[0] == "?":
varDef.desc.append(columns[8])
continue
if columns[0] == "$":
varDef.addValue(columns)
continue
try:
varDef = VarDef.fromColumns(columns)
self.varTotSize += varDef.byteSize()
self.varTotCount += 1
if varDef.is_configurable():
self.varCfgSize += varDef.byteSize()
self.varCfgCount += 1
if varDef.idx in self.subs[varDef.subsys]:
raise RuntimeError("Variable in subsystem %s with index %d already exists" %
_SUBSYSNAMES[varDef.subsys], varDef.idx)
self.subs[varDef.subsys][varDef.idx] = varDef
except Exception as r:
raise Exception("Error at line %d in file %s: %s" % (lineno, os.path.basename(filename), r))
def get_vardefs_sorted(self, subsys):
# srt = lambda x, y : -1 if x.typ.size > y.typ.size else 1 if x.typ.size < y.typ.size else 0
srt = lambda x : -x.typ.size
return sorted(self.subs[subsys].values(), key=srt)
def subsys_context(self, subsys):
defs = self.get_vardefs_sorted(subsys)
virtsigs = []
for vardef in defs:
if vardef.flags & VIRTUAL:
virtsigs.append(vardef)
max_idx = self.max_idx(subsys)
subname = _SUBSYSNAMES[subsys].lower()
ptrs = ['0'] * ( max_idx + 1 )
varnames = ['0'] * ( max_idx + 1 )
varids = [0] * ( max_idx + 1 )
for i in range( max_idx + 1 ):
if i not in self.subs[subsys]:
continue
vardef = self.subs[subsys][i]
ptrs[i] = "&(%s.%s)" % (subname, vardef.name.lower());
varnames[i] = "%s_%s" % (_SUBSYSNAMES[subsys], vardef.name);
ctx = {
'nicename' : _SUBSYS_NICE_NAMES[subsys],
'bigname' : _SUBSYSNAMES[subsys],
'vardefs' : defs,
'virtsigs' : virtsigs,
'name' : _SUBSYSNAMES[subsys].lower(),
'ptr_count' : self.max_idx(subsys) + 1,
'ptrs' : ptrs,
'varnames' : varnames,
}
return ctx
def save_c_header(self, srcpath, subdir, basename, context):
fio = open(os.path.join(srcpath, subdir, "%s.h" % basename), "w")
utpl.merge(tpls.c_header_tpls, "file", context, fio)
fio.close()
def save_c_source(self, srcpath, subdir, basename, context):
fio = open(os.path.join(srcpath, subdir, "%s.c" % basename), "w")
utpl.merge(tpls.c_source_tpls, "file", context, fio)
fio.close()
def save_c(self, srcpath, subdir, basename):
context = {
'hdef' : "_" + basename.upper() + "_H_",
'subcount' : SUBSYSCOUNT,
'subdir' : subdir,
'basename' : basename,
'subcount' : SUBSYSCOUNT,
'tot_var_count' : self.varTotCount,
'tot_var_size' : self.varTotSize,
'tot_cfg_count' : self.varCfgCount,
'tot_cfg_size' : self.varCfgSize
}
context['subsystems'] = [None] * SUBSYSCOUNT
for subsys in range(SUBSYSCOUNT):
context['subsystems'][subsys] = self.subsys_context(subsys)
self.save_c_header(srcpath, subdir, basename, context)
self.save_c_source(srcpath, subdir, basename, context)
def save_java(self, srcpath, fullclass):
fullclass = fullclass.split(".")
package = fullclass[0:-1]
classname = fullclass[-1]
srcpath = os.path.join(srcpath, *package)
fio = open(os.path.join(srcpath, "%s.java" % classname), "w")
context = {
'classname' : classname,
'package' : ".".join(package)
}
context['subsystems'] = [None] * SUBSYSCOUNT
for subsys in range(SUBSYSCOUNT):
context['subsystems'][subsys] = self.subsys_context(subsys)
utpl.merge(tpls.j_source_tpls, "file", context, fio)
fio.close()
def save_html_report(self, targethtml):
fio = open(targethtml, "w")
context = {
}
context['subsystems'] = [None] * SUBSYSCOUNT
for subsys in range(SUBSYSCOUNT):
context['subsystems'][subsys] = self.subsys_context(subsys)
utpl.merge(tpls.html_source_tpls, "file", context, fio)
fio.close()
if __name__ == "__main__":
if len(sys.argv) != 8:
print("makevars.py <CSV-file> <c-src-root> <c-src-dir> <c-src-basename> <java-src-root> <java-class-name> <variables-html-file>")
exit(1)
filename = "vars/variables.csv"
srcpath = "src/app"
subdir = "pv"
basename = "vars"
#try:
cfg = VarConfig()
cfg.load(sys.argv[1])
cfg.save_c(sys.argv[2], sys.argv[3], sys.argv[4])
cfg.save_java(sys.argv[5], sys.argv[6])
cfg.save_html_report(sys.argv[7])
#except Exception as r:
#print("Failed: ", r)
#raise r