diff options
Diffstat (limited to 'lib/codegen.py')
-rw-r--r-- | lib/codegen.py | 389 |
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) + ), + ) |