Files
Ada_Drivers_Library/scripts/config/__init__.py
2018-04-27 21:16:41 +02:00

305 lines
11 KiB
Python

#! /usr/bin/env python
import sys
from validation import Int_Validation, Float_Validation, \
Enum_Validation, String_Validation, Bool_Validation
class Database:
def __init__(self, interactive, use_default, user_input):
self.pre_defined_params = {}
self.configuration = {}
self.memories = []
self.src_dirs = []
self.interactive = interactive
self.use_default = use_default
self.user_input = user_input
def pre_define(self, key, value, origin):
self.pre_defined_params[key] = {'value': value,
'origin': origin}
def print_remaining_pre_defined(self):
for key in self.pre_defined_params:
origin = self.pre_defined_params[key]['origin']
print "warning: key '%s' from %s " % (key, origin) + \
"was not used in the configuration"
def add_to_configuration(self, key, kind, value, origin):
self.configuration[key] = {'value': value,
'kind': kind,
'origin': origin}
def get_config(self, key):
if key in self.configuration:
return self.configuration[key]['value']
else:
return None
def ada_configuration(self):
out = ""
for key in self.configuration:
origin = self.configuration[key]['origin']
value = self.configuration[key]['value']
kind = self.configuration[key]['kind']
if kind == "int" or kind == "float":
out += " %-30s : constant := %-20s -- From %s\n" % \
(key, str(value) + ";", origin)
elif kind == "enum" or kind == "string":
out += " %-30s : constant String := %-20s -- From %s\n" % \
(key, "\"" + str(value) + "\";", origin)
elif kind == "bool":
out += " %-30s : constant Boolean := %-20s -- From %s\n" % \
(key, str(value), origin)
else:
print "fatal error, unknown kind '%s' for config key '%s'" % \
(kind, key)
sys.exit(1)
return out
def gpr_configuration(self, src_root_dir, extra_source_dir):
out = ""
arch = self.get_config("Architecture")
runtime = self.get_config("Runtime_Name")
if arch is not None and arch != "Native":
if arch == "ARM":
target = "arm-eabi"
elif arch == "RISC-V":
target = "riscv32-elf"
out += " for Target use \"%s\";\n" % target
if runtime is not None:
out += " for Runtime (\"Ada\") use \"%s\";\n" % runtime
out += "\n"
for key in self.configuration:
origin = self.configuration[key]['origin']
value = self.configuration[key]['value']
out += " %-30s := %-20s -- From %s\n" % \
(key, '"' + str(value) + '";', origin)
out += "\n -- Project source directories\n"
out += " Src_Dirs_Root := \"%s\";\n" % src_root_dir
out += " for Source_Dirs use (\n"
for src in self.src_dirs:
out += " Src_Dirs_Root & \"/%s\", -- From %s\n" % \
(src['value'], src['origin'])
out += " \"%s/\");\n" % extra_source_dir
return out
def ask_the_user(self, key, validation, default):
origin = "user input"
kind = validation.kind()
if kind == "int":
value = self.user_input.query_int(key,
validation.min_value,
validation.max_value,
default)
elif kind == "enum":
value = self.user_input.query_choice(key,
validation.list_of_values,
default)
elif kind == "string":
value = self.user_input.query_string(key, default)
elif kind == "float":
value = self.user_input.query_float(key,
validation.min_value,
validation.max_value,
default)
elif kind == "bool":
value = self.user_input.query_bool(key, default)
self.add_to_configuration(key,
validation.kind(),
value,
origin)
def use_pre_defined_param(self, key, validation):
value = self.pre_defined_params[key]['value']
origin = self.pre_defined_params[key]['origin']
if validation(value):
self.add_to_configuration(key, validation.kind(), value, origin)
print "For key '%s', take value '%s' from %s" % \
(key, value, origin)
del self.pre_defined_params[key]
else:
print "Invalid value '%s' for key '%s' from %s" % \
(value, key, origin)
print "Valid values are : %s" % str(validation)
sys.exit(1)
def query_key(self, key, validation=None, default=None):
if key in self.pre_defined_params:
self.use_pre_defined_param(key, validation)
elif self.interactive:
self.ask_the_user(key, validation, default)
elif default is not None:
if self.use_default:
print "For key '%s', use default value '%s'" % (key, default)
self.add_to_configuration(key,
validation.kind(),
default,
"default value")
else:
print "fatal error, user doesn't want to use default " + \
"value for key '%s'" % key
sys.exit(1)
else:
print "fatal error, user input required for key '%s'" % key
sys.exit(1)
def query_integer_key(self,
key,
min_value=None,
max_value=None,
default=None):
self.query_key(key,
validation=Int_Validation(min_value, max_value),
default=default)
def query_float_key(self,
key,
min_value=None,
max_value=None,
default=None):
self.query_key(key,
validation=Float_Validation(min_value, max_value),
default=default)
def query_enum_key(self, key, list_of_values, default=None):
self.query_key(key,
validation=Enum_Validation(list_of_values),
default=default)
def query_string_key(self, key, default=None):
self.query_key(key, validation=String_Validation(), default=default)
def query_bool_key(self, key, default=None):
self.query_key(key, validation=Bool_Validation(), default=default)
def set_config_string_key(self, key, value, origin):
self.add_to_configuration(key, 'string', value, origin)
def set_config_key_int(self, key, value, origin):
self.add_to_configuration(key, 'int', value, origin)
def parse_input_config(self, file):
print "loading configuration keys from: '%s'" % file.name
line_cnt = 0
for line in file:
line_cnt += 1
key, val = line.partition("=>")[::2]
key = key.strip()
val = val.strip()
if key and val:
print "Add pre definition '%s' => '%s' from file '%s'" % \
(key, val, file.name)
self.pre_define(key, val, "%s:%d" % (file.name, line_cnt))
else:
print "invalid input configuration line at %s:%d" % \
(file.name, line_cnt)
# Memory layout config #
def add_memory(self, kind, name, addr, size):
self.memories += [{'kind': kind,
'name': name,
'addr': addr,
'size': size}]
def print_linker_script(self):
text_section = self.get_config("Linker_Text_Section")
rodata_section = self.get_config("Linker_RO_Data_Section")
data_section = self.get_config("Linker_Data_Section")
bss_section = self.get_config("Linker_BSS_Section")
print "MEMORY"
print "{"
for mem in self.memories:
if mem['kind'] == 'ROM':
print " %s (rxai!w) : ORIGIN = %s, LENGTH = %s" % \
(mem['name'], mem['addr'], mem['size'])
elif mem['kind'] == 'RAM':
print " %s (wxa!ri) : ORIGIN = %s, LENGTH = %s" % \
(mem['name'], mem['addr'], mem['size'])
else:
print "fatal error, unknown memory kind '%s'" % mem['kind']
sys.exit(1)
print "}"
print "\n.text:"
print "{"
print " *(.text.unlikely .text.unlikely.*)"
print " *(.text.startup .text.startup.*)"
print " *(.text .text.*)"
print " *(.gnu.linkonce.t.*)"
print "} > %s" % text_section
print "\n.rodata:"
print "{"
print " *(.rdata)"
print " *(.rodata .rodata.*)"
print " *(.gnu.linkonce.r.*)"
print "} > %s" % rodata_section
for mem in self.memories:
if mem['kind'] == 'RAM':
print "\n.%s_data:" % mem['name']
print "{"
print " *(.%s_data .%s_data.*)" % \
(mem['name'], mem['name'])
print "} > %s" % mem['name']
elif mem['kind'] == 'ROM':
print "\n.%s_rodata:" % mem['name']
print "{"
print " *(.%s_rodata .%s_rodata.*)" % \
(mem['name'], mem['name'])
print "} > %s" % mem['name']
print "\n.data:"
print "{"
print " *(.data .data.*)"
print " *(.gnu.linkonce.d.*)"
print "} > %s" % data_section
print "\n.sdata:"
print "{"
print " *(.sdata .sdata.*)"
print " *(.gnu.linkonce.s.*)"
print "} > %s" % data_section
print "\n.bss:"
print "{"
print " *(.bss .bss.*)"
print "} > %s" % bss_section
def memory_names(self):
list = []
for mem in self.memories:
list.append(mem['name'])
return list
def default_rom_area(self):
for mem in self.memories:
if mem['kind'] == 'ROM':
return mem['name']
return None
def default_ram_area(self):
for mem in self.memories:
if mem['kind'] == 'RAM':
return mem['name']
return None
# Source directories config #
def add_source_dir(self, relative_path, origin):
self.src_dirs.append({'value': relative_path,
'origin': origin})