summaryrefslogtreecommitdiff
path: root/lib/codegen.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/codegen.py')
-rw-r--r--lib/codegen.py389
1 files changed, 281 insertions, 108 deletions
diff --git a/lib/codegen.py b/lib/codegen.py
index e0bf45f..62776fd 100644
--- a/lib/codegen.py
+++ b/lib/codegen.py
@@ -60,38 +60,46 @@ class ClassFunction:
self.body = body
def get_definition(self):
- return '{} {}({});'.format(self.return_type, self.name, ', '.join(self.arguments))
+ return "{} {}({});".format(
+ self.return_type, self.name, ", ".join(self.arguments)
+ )
def get_implementation(self):
if self.body is None:
- return ''
- return '{} {}::{}({}) {{\n{}}}\n'.format(self.return_type, self.class_name, self.name, ', '.join(self.arguments), self.body)
+ return ""
+ return "{} {}::{}({}) {{\n{}}}\n".format(
+ self.return_type,
+ self.class_name,
+ self.name,
+ ", ".join(self.arguments),
+ self.body,
+ )
def get_accountingmethod(method):
"""Return AccountingMethod class for method."""
- if method == 'static_state_immediate':
+ if method == "static_state_immediate":
return StaticStateOnlyAccountingImmediateCalculation
- if method == 'static_state':
+ if method == "static_state":
return StaticStateOnlyAccounting
- if method == 'static_statetransition_immediate':
+ if method == "static_statetransition_immediate":
return StaticAccountingImmediateCalculation
- if method == 'static_statetransition':
+ if method == "static_statetransition":
return StaticAccounting
- raise ValueError('Unknown accounting method: {}'.format(method))
+ raise ValueError("Unknown accounting method: {}".format(method))
def get_simulated_accountingmethod(method):
"""Return SimulatedAccountingMethod class for method."""
- if method == 'static_state_immediate':
+ if method == "static_state_immediate":
return SimulatedStaticStateOnlyAccountingImmediateCalculation
- if method == 'static_statetransition_immediate':
+ if method == "static_statetransition_immediate":
return SimulatedStaticAccountingImmediateCalculation
- if method == 'static_state':
+ if method == "static_state":
return SimulatedStaticStateOnlyAccounting
- if method == 'static_statetransition':
+ if method == "static_statetransition":
return SimulatedStaticAccounting
- raise ValueError('Unknown accounting method: {}'.format(method))
+ raise ValueError("Unknown accounting method: {}".format(method))
class SimulatedAccountingMethod:
@@ -104,7 +112,18 @@ class SimulatedAccountingMethod:
* variable size for accounting of durations, power and energy values
"""
- def __init__(self, pta: PTA, timer_freq_hz, timer_type, ts_type, power_type, energy_type, ts_granularity=1e-6, power_granularity=1e-6, energy_granularity=1e-12):
+ def __init__(
+ self,
+ pta: PTA,
+ timer_freq_hz,
+ timer_type,
+ ts_type,
+ power_type,
+ energy_type,
+ ts_granularity=1e-6,
+ power_granularity=1e-6,
+ energy_granularity=1e-12,
+ ):
"""
Simulate Online Accounting for a given PTA.
@@ -121,7 +140,7 @@ class SimulatedAccountingMethod:
self.ts_class = simulate_int_type(ts_type)
self.power_class = simulate_int_type(power_type)
self.energy_class = simulate_int_type(energy_type)
- self.current_state = pta.state['UNINITIALIZED']
+ self.current_state = pta.state["UNINITIALIZED"]
self.ts_granularity = ts_granularity
self.power_granularity = power_granularity
@@ -137,7 +156,13 @@ class SimulatedAccountingMethod:
Does not use Module types and therefore does not consider overflows or data-type limitations"""
if self.energy_granularity == self.power_granularity * self.ts_granularity:
return power * time
- return int(power * self.power_granularity * time * self.ts_granularity / self.energy_granularity)
+ return int(
+ power
+ * self.power_granularity
+ * time
+ * self.ts_granularity
+ / self.energy_granularity
+ )
def _sleep_duration(self, duration_us):
u"""
@@ -202,11 +227,11 @@ class SimulatedStaticAccountingImmediateCalculation(SimulatedAccountingMethod):
def sleep(self, duration_us):
time = self._sleep_duration(duration_us)
- print('sleep duration is {}'.format(time))
+ print("sleep duration is {}".format(time))
power = int(self.current_state.power.value)
- print('power is {}'.format(power))
+ print("power is {}".format(power))
energy = self._energy_from_power_and_time(time, power)
- print('energy is {}'.format(energy))
+ print("energy is {}".format(energy))
self.energy += energy
def pass_transition(self, transition: Transition):
@@ -232,7 +257,7 @@ class SimulatedStaticAccounting(SimulatedAccountingMethod):
self.time_in_state[state_name] = self.ts_class(0)
self.transition_count = list()
for transition in pta.transitions:
- self.transition_count.append(simulate_int_type('uint16_t')(0))
+ self.transition_count.append(simulate_int_type("uint16_t")(0))
def sleep(self, duration_us):
self.time_in_state[self.current_state.name] += self._sleep_duration(duration_us)
@@ -245,7 +270,9 @@ class SimulatedStaticAccounting(SimulatedAccountingMethod):
pta = self.pta
energy = self.energy_class(0)
for state in pta.state.values():
- energy += self._energy_from_power_and_time(self.time_in_state[state.name], int(state.power.value))
+ energy += self._energy_from_power_and_time(
+ self.time_in_state[state.name], int(state.power.value)
+ )
for i, transition in enumerate(pta.transitions):
energy += self.transition_count[i] * int(transition.energy.value)
return energy.val
@@ -275,7 +302,9 @@ class SimulatedStaticStateOnlyAccounting(SimulatedAccountingMethod):
pta = self.pta
energy = self.energy_class(0)
for state in pta.state.values():
- energy += self._energy_from_power_and_time(self.time_in_state[state.name], int(state.power.value))
+ energy += self._energy_from_power_and_time(
+ self.time_in_state[state.name], int(state.power.value)
+ )
return energy.val
@@ -290,32 +319,50 @@ class AccountingMethod:
self.public_functions = list()
def pre_transition_hook(self, transition):
- return ''
+ return ""
def init_code(self):
- return ''
+ return ""
def get_includes(self):
return map(lambda x: '#include "{}"'.format(x), self.include_paths)
class StaticStateOnlyAccountingImmediateCalculation(AccountingMethod):
- def __init__(self, class_name: str, pta: PTA, ts_type='unsigned int', power_type='unsigned int', energy_type='unsigned long'):
+ def __init__(
+ self,
+ class_name: str,
+ pta: PTA,
+ ts_type="unsigned int",
+ power_type="unsigned int",
+ energy_type="unsigned long",
+ ):
super().__init__(class_name, pta)
self.ts_type = ts_type
- self.include_paths.append('driver/uptime.h')
- self.private_variables.append('unsigned char lastState;')
- self.private_variables.append('{} lastStateChange;'.format(ts_type))
- self.private_variables.append('{} totalEnergy;'.format(energy_type))
- self.private_variables.append(array_template.format(
- type=power_type,
- name='state_power',
- length=len(pta.state),
- elements=', '.join(map(lambda state_name: '{:.0f}'.format(pta.state[state_name].power), pta.get_state_names()))
- ))
+ self.include_paths.append("driver/uptime.h")
+ self.private_variables.append("unsigned char lastState;")
+ self.private_variables.append("{} lastStateChange;".format(ts_type))
+ self.private_variables.append("{} totalEnergy;".format(energy_type))
+ self.private_variables.append(
+ array_template.format(
+ type=power_type,
+ name="state_power",
+ length=len(pta.state),
+ elements=", ".join(
+ map(
+ lambda state_name: "{:.0f}".format(pta.state[state_name].power),
+ pta.get_state_names(),
+ )
+ ),
+ )
+ )
get_energy_function = """return totalEnergy;"""
- self.public_functions.append(ClassFunction(class_name, energy_type, 'getEnergy', list(), get_energy_function))
+ self.public_functions.append(
+ ClassFunction(
+ class_name, energy_type, "getEnergy", list(), get_energy_function
+ )
+ )
def pre_transition_hook(self, transition):
return """
@@ -323,30 +370,50 @@ class StaticStateOnlyAccountingImmediateCalculation(AccountingMethod):
totalEnergy += (now - lastStateChange) * state_power[lastState];
lastStateChange = now;
lastState = {};
- """.format(self.pta.get_state_id(transition.destination))
+ """.format(
+ self.pta.get_state_id(transition.destination)
+ )
def init_code(self):
return """
totalEnergy = 0;
lastStateChange = 0;
lastState = 0;
- """.format(num_states=len(self.pta.state))
+ """.format(
+ num_states=len(self.pta.state)
+ )
class StaticStateOnlyAccounting(AccountingMethod):
- def __init__(self, class_name: str, pta: PTA, ts_type='unsigned int', power_type='unsigned int', energy_type='unsigned long'):
+ def __init__(
+ self,
+ class_name: str,
+ pta: PTA,
+ ts_type="unsigned int",
+ power_type="unsigned int",
+ energy_type="unsigned long",
+ ):
super().__init__(class_name, pta)
self.ts_type = ts_type
- self.include_paths.append('driver/uptime.h')
- self.private_variables.append('unsigned char lastState;')
- self.private_variables.append('{} lastStateChange;'.format(ts_type))
- self.private_variables.append(array_template.format(
- type=power_type,
- name='state_power',
- length=len(pta.state),
- elements=', '.join(map(lambda state_name: '{:.0f}'.format(pta.state[state_name].power), pta.get_state_names()))
- ))
- self.private_variables.append('{} timeInState[{}];'.format(ts_type, len(pta.state)))
+ self.include_paths.append("driver/uptime.h")
+ self.private_variables.append("unsigned char lastState;")
+ self.private_variables.append("{} lastStateChange;".format(ts_type))
+ self.private_variables.append(
+ array_template.format(
+ type=power_type,
+ name="state_power",
+ length=len(pta.state),
+ elements=", ".join(
+ map(
+ lambda state_name: "{:.0f}".format(pta.state[state_name].power),
+ pta.get_state_names(),
+ )
+ ),
+ )
+ )
+ self.private_variables.append(
+ "{} timeInState[{}];".format(ts_type, len(pta.state))
+ )
get_energy_function = """
{energy_type} total_energy = 0;
@@ -354,8 +421,14 @@ class StaticStateOnlyAccounting(AccountingMethod):
total_energy += timeInState[i] * state_power[i];
}}
return total_energy;
- """.format(energy_type=energy_type, num_states=len(pta.state))
- self.public_functions.append(ClassFunction(class_name, energy_type, 'getEnergy', list(), get_energy_function))
+ """.format(
+ energy_type=energy_type, num_states=len(pta.state)
+ )
+ self.public_functions.append(
+ ClassFunction(
+ class_name, energy_type, "getEnergy", list(), get_energy_function
+ )
+ )
def pre_transition_hook(self, transition):
return """
@@ -363,7 +436,9 @@ class StaticStateOnlyAccounting(AccountingMethod):
timeInState[lastState] += now - lastStateChange;
lastStateChange = now;
lastState = {};
- """.format(self.pta.get_state_id(transition.destination))
+ """.format(
+ self.pta.get_state_id(transition.destination)
+ )
def init_code(self):
return """
@@ -372,30 +447,59 @@ class StaticStateOnlyAccounting(AccountingMethod):
}}
lastState = 0;
lastStateChange = 0;
- """.format(num_states=len(self.pta.state))
+ """.format(
+ num_states=len(self.pta.state)
+ )
class StaticAccounting(AccountingMethod):
- def __init__(self, class_name: str, pta: PTA, ts_type='unsigned int', power_type='unsigned int', energy_type='unsigned long'):
+ def __init__(
+ self,
+ class_name: str,
+ pta: PTA,
+ ts_type="unsigned int",
+ power_type="unsigned int",
+ energy_type="unsigned long",
+ ):
super().__init__(class_name, pta)
self.ts_type = ts_type
- self.include_paths.append('driver/uptime.h')
- self.private_variables.append('unsigned char lastState;')
- self.private_variables.append('{} lastStateChange;'.format(ts_type))
- self.private_variables.append(array_template.format(
- type=power_type,
- name='state_power',
- length=len(pta.state),
- elements=', '.join(map(lambda state_name: '{:.0f}'.format(pta.state[state_name].power), pta.get_state_names()))
- ))
- self.private_variables.append(array_template.format(
- type=energy_type,
- name='transition_energy',
- length=len(pta.get_unique_transitions()),
- elements=', '.join(map(lambda transition: '{:.0f}'.format(transition.energy), pta.get_unique_transitions()))
- ))
- self.private_variables.append('{} timeInState[{}];'.format(ts_type, len(pta.state)))
- self.private_variables.append('{} transitionCount[{}];'.format('unsigned int', len(pta.get_unique_transitions())))
+ self.include_paths.append("driver/uptime.h")
+ self.private_variables.append("unsigned char lastState;")
+ self.private_variables.append("{} lastStateChange;".format(ts_type))
+ self.private_variables.append(
+ array_template.format(
+ type=power_type,
+ name="state_power",
+ length=len(pta.state),
+ elements=", ".join(
+ map(
+ lambda state_name: "{:.0f}".format(pta.state[state_name].power),
+ pta.get_state_names(),
+ )
+ ),
+ )
+ )
+ self.private_variables.append(
+ array_template.format(
+ type=energy_type,
+ name="transition_energy",
+ length=len(pta.get_unique_transitions()),
+ elements=", ".join(
+ map(
+ lambda transition: "{:.0f}".format(transition.energy),
+ pta.get_unique_transitions(),
+ )
+ ),
+ )
+ )
+ self.private_variables.append(
+ "{} timeInState[{}];".format(ts_type, len(pta.state))
+ )
+ self.private_variables.append(
+ "{} transitionCount[{}];".format(
+ "unsigned int", len(pta.get_unique_transitions())
+ )
+ )
get_energy_function = """
{energy_type} total_energy = 0;
@@ -406,8 +510,16 @@ class StaticAccounting(AccountingMethod):
total_energy += transitionCount[i] * transition_energy[i];
}}
return total_energy;
- """.format(energy_type=energy_type, num_states=len(pta.state), num_transitions=len(pta.get_unique_transitions()))
- self.public_functions.append(ClassFunction(class_name, energy_type, 'getEnergy', list(), get_energy_function))
+ """.format(
+ energy_type=energy_type,
+ num_states=len(pta.state),
+ num_transitions=len(pta.get_unique_transitions()),
+ )
+ self.public_functions.append(
+ ClassFunction(
+ class_name, energy_type, "getEnergy", list(), get_energy_function
+ )
+ )
def pre_transition_hook(self, transition):
return """
@@ -416,7 +528,10 @@ class StaticAccounting(AccountingMethod):
transitionCount[{}]++;
lastStateChange = now;
lastState = {};
- """.format(self.pta.get_unique_transition_id(transition), self.pta.get_state_id(transition.destination))
+ """.format(
+ self.pta.get_unique_transition_id(transition),
+ self.pta.get_state_id(transition.destination),
+ )
def init_code(self):
return """
@@ -428,28 +543,53 @@ class StaticAccounting(AccountingMethod):
}}
lastState = 0;
lastStateChange = 0;
- """.format(num_states=len(self.pta.state), num_transitions=len(self.pta.get_unique_transitions()))
+ """.format(
+ num_states=len(self.pta.state),
+ num_transitions=len(self.pta.get_unique_transitions()),
+ )
class StaticAccountingImmediateCalculation(AccountingMethod):
- def __init__(self, class_name: str, pta: PTA, ts_type='unsigned int', power_type='unsigned int', energy_type='unsigned long'):
+ def __init__(
+ self,
+ class_name: str,
+ pta: PTA,
+ ts_type="unsigned int",
+ power_type="unsigned int",
+ energy_type="unsigned long",
+ ):
super().__init__(class_name, pta)
self.ts_type = ts_type
- self.include_paths.append('driver/uptime.h')
- self.private_variables.append('unsigned char lastState;')
- self.private_variables.append('{} lastStateChange;'.format(ts_type))
- self.private_variables.append('{} totalEnergy;'.format(energy_type))
- self.private_variables.append(array_template.format(
- type=power_type,
- name='state_power',
- length=len(pta.state),
- elements=', '.join(map(lambda state_name: '{:.0f}'.format(pta.state[state_name].power), pta.get_state_names()))
- ))
+ self.include_paths.append("driver/uptime.h")
+ self.private_variables.append("unsigned char lastState;")
+ self.private_variables.append("{} lastStateChange;".format(ts_type))
+ self.private_variables.append("{} totalEnergy;".format(energy_type))
+ self.private_variables.append(
+ array_template.format(
+ type=power_type,
+ name="state_power",
+ length=len(pta.state),
+ elements=", ".join(
+ map(
+ lambda state_name: "{:.0f}".format(pta.state[state_name].power),
+ pta.get_state_names(),
+ )
+ ),
+ )
+ )
get_energy_function = """
return totalEnergy;
- """.format(energy_type=energy_type, num_states=len(pta.state), num_transitions=len(pta.get_unique_transitions()))
- self.public_functions.append(ClassFunction(class_name, energy_type, 'getEnergy', list(), get_energy_function))
+ """.format(
+ energy_type=energy_type,
+ num_states=len(pta.state),
+ num_transitions=len(pta.get_unique_transitions()),
+ )
+ self.public_functions.append(
+ ClassFunction(
+ class_name, energy_type, "getEnergy", list(), get_energy_function
+ )
+ )
def pre_transition_hook(self, transition):
return """
@@ -458,21 +598,26 @@ class StaticAccountingImmediateCalculation(AccountingMethod):
totalEnergy += {};
lastStateChange = now;
lastState = {};
- """.format(transition.energy, self.pta.get_state_id(transition.destination))
+ """.format(
+ transition.energy, self.pta.get_state_id(transition.destination)
+ )
def init_code(self):
return """
lastState = 0;
lastStateChange = 0;
- """.format(num_states=len(self.pta.state), num_transitions=len(self.pta.get_unique_transitions()))
+ """.format(
+ num_states=len(self.pta.state),
+ num_transitions=len(self.pta.get_unique_transitions()),
+ )
class MultipassDriver:
"""Generate C++ header and no-op implementation for a multipass driver based on a DFA model."""
def __init__(self, name, pta, class_info, enum=dict(), accounting=AccountingMethod):
- self.impl = ''
- self.header = ''
+ self.impl = ""
+ self.header = ""
self.name = name
self.pta = pta
self.class_info = class_info
@@ -484,35 +629,53 @@ class MultipassDriver:
private_variables = list()
public_variables = list()
- public_functions.append(ClassFunction(self.name, '', self.name, list(), accounting.init_code()))
+ public_functions.append(
+ ClassFunction(self.name, "", self.name, list(), accounting.init_code())
+ )
for transition in self.pta.get_unique_transitions():
- if transition.name == 'getEnergy':
+ if transition.name == "getEnergy":
continue
# XXX right now we only verify whether both functions have the
# same number of arguments. This breaks in many overloading cases.
function_info = self.class_info.function[transition.name]
for function_candidate in self.class_info.functions:
- if function_candidate.name == transition.name and len(function_candidate.argument_types) == len(transition.arguments):
+ if function_candidate.name == transition.name and len(
+ function_candidate.argument_types
+ ) == len(transition.arguments):
function_info = function_candidate
function_arguments = list()
for i in range(len(transition.arguments)):
- function_arguments.append('{} {}'.format(function_info.argument_types[i], transition.arguments[i]))
+ function_arguments.append(
+ "{} {}".format(
+ function_info.argument_types[i], transition.arguments[i]
+ )
+ )
function_body = accounting.pre_transition_hook(transition)
- if function_info.return_type != 'void':
- function_body += 'return 0;\n'
+ if function_info.return_type != "void":
+ function_body += "return 0;\n"
- public_functions.append(ClassFunction(self.name, function_info.return_type, transition.name, function_arguments, function_body))
+ public_functions.append(
+ ClassFunction(
+ self.name,
+ function_info.return_type,
+ transition.name,
+ function_arguments,
+ function_body,
+ )
+ )
enums = list()
for enum_name in self.enum.keys():
- enums.append('enum {} {{ {} }};'.format(enum_name, ', '.join(self.enum[enum_name])))
+ enums.append(
+ "enum {} {{ {} }};".format(enum_name, ", ".join(self.enum[enum_name]))
+ )
if accounting:
includes.extend(accounting.get_includes())
@@ -522,11 +685,21 @@ class MultipassDriver:
public_variables.extend(accounting.public_variables)
self.header = header_template.format(
- name=self.name, name_lower=self.name.lower(),
- includes='\n'.join(includes),
- private_variables='\n'.join(private_variables),
- public_variables='\n'.join(public_variables),
- public_functions='\n'.join(map(lambda x: x.get_definition(), public_functions)),
- private_functions='',
- enums='\n'.join(enums))
- self.impl = implementation_template.format(name=self.name, name_lower=self.name.lower(), functions='\n\n'.join(map(lambda x: x.get_implementation(), public_functions)))
+ name=self.name,
+ name_lower=self.name.lower(),
+ includes="\n".join(includes),
+ private_variables="\n".join(private_variables),
+ public_variables="\n".join(public_variables),
+ public_functions="\n".join(
+ map(lambda x: x.get_definition(), public_functions)
+ ),
+ private_functions="",
+ enums="\n".join(enums),
+ )
+ self.impl = implementation_template.format(
+ name=self.name,
+ name_lower=self.name.lower(),
+ functions="\n\n".join(
+ map(lambda x: x.get_implementation(), public_functions)
+ ),
+ )