You've already forked Ada_Drivers_Library
mirror of
https://github.com/AdaCore/Ada_Drivers_Library.git
synced 2026-02-12 12:26:55 -08:00
305 lines
11 KiB
Python
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})
|