Commit 7d05cde0 authored by Christian Dietrich's avatar Christian Dietrich

osek-v: wipe static alarms from software implementation

Static alarms are not managed by the timer interrupt. We wipe them from
the implementation. If a counter has no present alarms anymore, we wipe
it from the timer interrupt. If no counter has to be ticked, the timer
interrupt is disabled, the Counter::tick() method becomes empty.

Change-Id: I9438c8cfa511b5163bbb477c2d5b4f2e0f469697
parent 269d7dcc
......@@ -18,7 +18,7 @@ extern "C" {
//// Should be MIP_MSIE (same constant)
Machine::set_csr_bit(mie, MIP_MSIP);
arch::Timer::init();
// arch::Timer::init is called in StartOS
init_generic();
}
......
......@@ -128,7 +128,7 @@ class OILReadPass(Analysis):
# Counters
for conf in oil.getCounters():
graph._counters[conf.name] = Counter(conf.name, conf)
graph._counters[conf.name] = Counter(graph, conf.name, conf)
# Alarms
......
......@@ -6,8 +6,14 @@ class Counter(SystemObject):
"""SystemObject representing an counter. The .conf is an
OILObject(Counter) and the .impl is an DataObject.
"""
def __init__(self, name, configuration):
def __init__(self, system_graph, name, configuration):
super(Counter, self).__init__(name, configuration)
self.system_graph = system_graph
@property
def alarms(self):
return [x for x in self.system_graph.alarms
if x.conf.counter == self]
class SporadicEvent:
def __init__(self, system_graph, name, task, handler):
......
......@@ -70,7 +70,7 @@ class OSEKVArch(GenericArch):
exit_abb = self.system_graph.AlarmHandlerSubtask.exit_abb
for alarm in self.system_graph.AlarmHandlerSubtask.alarms:
if not alarm in static_alarm_pass.static_alarms:
if not static_alarm_pass.is_static(alarm):
continue
config = static_alarm_pass.static_alarms[alarm]
# namedtuple -> OrderedDict -> dict
......
......@@ -365,20 +365,35 @@ class FullSystemCalls(BaseCoder):
panic("Unsupported assert type %s", assertion)
class AlarmTemplate(CodeTemplate):
def __init__(self, rules):
def __init__(self, rules, alarm_filter = None):
CodeTemplate.__init__(self, rules.generator, "os/alarm.h.in")
self.rules = rules
self.alarm_filter = alarm_filter
self.system_graph = self.generator.system_graph
# Link the foreach_subtask method from the rules
self.foreach_subtask = self.rules.foreach_subtask
# Check if there are any counters/alarms which have to be implemented
self.subsystem_enabled = False
if self.alarm_filter:
if any(self.alarm_filter(x) for x in self.system_graph.alarms):
self.subsystem_enabled = True
else:
if len(self.system_graph.alarms) > 0:
self.subsystem_enabled = True
def increase_counters(self, snippet, args):
ret = []
for counter in self.system_graph.counters:
# Softcounters are ignored by the hardware interrupt
if counter.conf.softcounter:
continue
# Ignore all counters, that have no alarm attached, which
# is actually implemented
if self.alarm_filter:
if all(self.alarm_filter(x) is False for x in counter.alarms):
continue
ret += self.expand_snippet("increase_counter",
name = counter.impl.name)
return ret
......@@ -387,6 +402,8 @@ class AlarmTemplate(CodeTemplate):
def check_alarms(self, snippet, args):
if not self.system_graph.AlarmHandlerSubtask:
return []
if self.subsystem_enabled is False:
return []
ret = []
# The AlarmHandlerSubtask carries a _sorted_ list of alarms
kickoff = self.system_graph.AlarmHandlerSubtask.entry_abb
......@@ -394,6 +411,9 @@ class AlarmTemplate(CodeTemplate):
ret += [" " + kickoff.generated_function_name() + "();\n"]
for alarm in self.system_graph.AlarmHandlerSubtask.alarms:
# When the alarm filter says no, we do not add a check
if self.alarm_filter and self.alarm_filter(alarm) is False:
continue
ret += [" AlarmCheck%s();\n" % alarm.impl.name]
ret += [" " + iret.generated_function_name() + "();\n"]
return ret
......@@ -411,6 +431,10 @@ class AlarmTemplate(CodeTemplate):
def generate_check_alarms(self, snippet, args):
ret = []
for alarm in self.system_graph.alarms:
# If we have an alarm filter, and the alarm filter says
# no, we do not generate an CheckAlarm() function.
if self.alarm_filter and self.alarm_filter(alarm) is False:
continue
callback_name = "OSEKOS_ALARMCB_%s" % (alarm.name)
has_callback = (self.system_graph.find(GraphFunction, callback_name) != None)
args = {"alarm": alarm.impl.name}
......
......@@ -17,7 +17,6 @@ class WiredSystemCalls(BaseCoder):
def __init__(self, use_pla = False):
super(WiredSystemCalls, self).__init__()
self.syscall_map = {}
self.alarms = AlarmTemplate
def task_desc(self, subtask):
"""Returns a string that generates the task id"""
......@@ -32,12 +31,18 @@ class WiredSystemCalls(BaseCoder):
self.logic = self.system_graph.get_pass("LogicMinimizer")
self.fsm = self.logic.fsm
self.static_alarm_pass = self.system_graph.get_pass("StaticAlarms")
# Generate the transition table
for event in self.fsm.events:
self.syscall_map[event.name] = event
self.generator.source_file.declarations.append(self.alarms(self).expand())
# Remove all static and all useless alarm implementations
alarm_filter = lambda alarm: not (self.static_alarm_pass.is_static(alarm) or \
self.static_alarm_pass.is_useless(alarm))
self.alarm_subsystem = AlarmTemplate(self, alarm_filter)
self.generator.source_file.declarations.append(self.alarm_subsystem.expand())
def StartOS(self, kernelspace):
......@@ -63,7 +68,7 @@ class WiredSystemCalls(BaseCoder):
"void",
["(void *) (((char *)%s) + sizeof(%s) - 16)" % (sp, sp)])
WHILE = Block("while (1)")
wrapper.add(WHILE)
self.call_function(WHILE, subtask.function_name, "void", [])
......@@ -73,6 +78,10 @@ class WiredSystemCalls(BaseCoder):
"void",
[str(subtask.impl.task_id), "(void*) &" +wrapper.function_name])
# Enable the timer, if the alarm subsystem is enabled
if self.alarm_subsystem.subsystem_enabled:
self.generator.source_file.include("timer.h")
self.call_function(kernelspace, "arch::Timer::init")
StartOS = self.system_graph.get(GraphFunction, "StartOS")
self.fsm_schedule(StartOS.entry_abb, None, kernelspace)
......
# coding: utf-8
from generator.analysis.Analysis import Analysis
from generator.analysis.AtomicBasicBlock import E, S
from generator.coder.elements import DataObject, Include
......@@ -37,16 +39,21 @@ class StaticAlarms(Analysis):
static_alarms[alarm] = False
# Only the static alarms
alarms_static = [k for k,v in static_alarms.items() if v]
static_alarms = [k for k,v in static_alarms.items() if v]
base_period = None
self.useless_alarms = set()
for alarm in static_alarms:
if not alarm.conf.armed:
self.useless_alarms.add(alarm)
logging.info(" Remove Alarm %s, since is not armed and no syscall references it",
alarm.conf.name)
continue
if not base_period:
base_period = alarm.conf.reltime
base_period = gcd(base_period, alarm.conf.reltime)
base_period = gcd(base_period, alarm.conf.cycletime)
logging.info(" Static Alarm: %s (t0 + %d + n × %d)", alarm.conf.name, alarm.conf.reltime, alarm.conf.cycletime)
self.base_period = base_period
self.static_alarms = {}
......@@ -58,3 +65,9 @@ class StaticAlarms(Analysis):
cycletime = alarm.conf.cycletime//self.base_period,
)
# Accessors for the analysis results
def is_static(self, alarm):
return alarm in self.static_alarms
def is_useless(self, alarm):
return alarm in self.useless_alarms
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment