You've already forked gitified_old_clb_svn
Added errata module for correcting or bypassing board specific errors Improved makevars build script
480 lines
14 KiB
Python
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
|