aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-03-30 11:30:01 -0400
committerJonathan Herman <hermanjl@cs.unc.edu>2013-04-15 11:38:30 -0400
commit7cef798367892aff5ae76780b15c3a0f135d0234 (patch)
tree406b88703d51b750c11180e1d9eaebd78a3edcda
parent625e0f2d3fd50f079c7eb84825992b70421bd78e (diff)
Added mixed-criticality generator.
-rw-r--r--gen/mc_generators.py205
1 files changed, 205 insertions, 0 deletions
diff --git a/gen/mc_generators.py b/gen/mc_generators.py
new file mode 100644
index 0000000..d6d8d90
--- /dev/null
+++ b/gen/mc_generators.py
@@ -0,0 +1,205 @@
1import gen.rv as rv
2
3from common import try_get_config_option
4from gen.generator import GenOption,Generator,NAMED_UTILIZATIONS,NAMED_PERIODS
5
6
7NAMED_SHARES = {
8 'weighted' : [1, 1, 8, 1],
9 'harmonic' : [1, 2, 4, 1],
10 'fair' : [1, 1, 1, 1],
11}
12
13TP_BASE = """#for $t in $lvl{0}
14{1}-g {0} -s $scale{0} $t.cost $t.period
15#end for"""
16TP_LVLA = """#if $lvla
17/proc/litmus/plugins/MC-CE/ce_file{
18#for $t in $lvla
19$t.cpu, $t.id, $t.budget
20#end for
21}
22#end if
23""" + TP_BASE.format("a", "-i $t.id -p $t.cpu ")
24TP_LVLB = TP_BASE.format("b", "-p $t.cpu ")
25TP_LVLC = TP_BASE.format("c", "")
26TP_LVLD = """#if $be
27#for $i in range($cpus)
28#if $d_fifo
29#set $fopt='-f'
30#else
31#set $fopt=''
32#end if
33#if d_nice
34#set $nopt='-n'
35#else
36#set $nopt=''
37#end if
38bespin -s $i -f $i.misses $be_opts -p $i $fopt $nopt
39#end for
40#end if"""
41
42TM_OPT = 'MERGE_TIMERS'
43SS_OPT = 'PLUGIN_MC_LINUX_SLACK_STEALING'
44RD_OPT = 'PLUGIN_MC_REDIRECT'
45MC_OPT = 'PLUGIN_MC'
46LEVELS = 3
47
48class McGenerator(Generator):
49 def __init__(self, params = {}):
50 super(McGenerator, self).__init__("MC",
51 [TP_LVLA, TP_LVLB, TP_LVLC, TP_LVLD],
52 self.__make_options(),
53 params)
54
55 def __make_options(self):
56 timer_merging = try_get_config_option(TM_OPT, False)
57 slack_stealing = try_get_config_option(SS_OPT, False)
58 redirect = try_get_config_option(RD_OPT, True)
59
60 return [GenOption('levels', range(1, LEVELS+1), [3],
61 'Number of criticality levels: C, BC, ABC'),
62 GenOption('be', [True,False], [False],
63 'Execute background work using bespin.'),
64
65 GenOption('timer_merging', [True,False], [timer_merging],
66 'Require timer-merging support.'),
67 GenOption('redirect', [True,False], [redirect],
68 'Redirect work to the interrupt master.'),
69 GenOption('slack_stealing', [True,False], [slack_stealing],
70 'Schedule linux tasks in the background.'),
71
72 GenOption('d_nice', [True,False], [False],
73 'Schedule level-D tasks using nice().'),
74 GenOption('d_fifo', [True, False], [False],
75 'Schedule level-D tasks under SCHED_FIFO.'),
76
77 GenOption('a_hyperperiod', float, 25.0,
78 'Level-A hyperperiod (ms).'),
79 Generator._dist_option('b_periods', ['harmonic'], NAMED_PERIODS,
80 'Level-B task periods. Harmonic is always used if level A is present.'),
81 Generator._dist_option('c_periods', ['harmonic'],
82 NAMED_PERIODS, 'Level-C task periods.'),
83
84 Generator._dist_option('a_utils', ['bimo-light'],
85 NAMED_UTILIZATIONS,
86 'Level-A task utilizations (at level A).'),
87 Generator._dist_option('b_utils', ['bimo-light'],
88 NAMED_UTILIZATIONS,
89 'Level-B task utilizations (at level B).'),
90 Generator._dist_option('c_utils', ['bimo-light'],
91 NAMED_UTILIZATIONS,
92 'Level-C task utilizations (at level C).'),
93
94 Generator._dist_option('shares', ['fair'], NAMED_SHARES,
95 'Distribution of actual utilizations.')]
96
97 def __partition_worst_fit(self, params, ts):
98 # Partition using worst-fit for most even distribution
99 utils = [0]*int(params['cpus'])
100 tasks = [0]*int(params['cpus'])
101 for t in ts:
102 t.cpu = utils.index(min(utils))
103 t.id = tasks[t.cpu]
104
105 utils[t.cpu] += t.utilization()
106 tasks[t.cpu] += 1
107
108 def __adjust(self, params, level):
109 # Adjust for levels which aren't used
110 ldiff = LEVELS - params['levels']
111 shares = self.shares[ldiff:]
112 level -= ldiff
113
114 return shares, level
115
116 def __get_max_util(self, params, level):
117 shares, level = self.__adjust(params, level)
118 return float(shares[level]) / sum(shares[:level]) * params['cpus']
119
120 def __get_scale(self, params, level):
121 shares, level = self.__adjust(params, level)
122 return float(shares[level]) / sum(shares)
123
124 def __create_lvla_sched(self, params):
125 if params['levels'] < 3:
126 return []
127
128 utils = self._create_dist('utilization', params['a_utils'],
129 NAMED_UTILIZATIONS)
130 periods = self._create_dist('period', params['a_hyperperiod'], None)
131
132 ts = self._create_taskset(params, periods, utils)
133
134 # Make the budget used by the cyclic executive larger than the
135 # actual WCET because of overheads
136 for t in ts:
137 t.budget = int(1.05 * 1000000 * t.cost)
138 t.wcet = int(t.cost)
139
140 self.__partition_worst_fit(params, ts)
141
142 return ts
143
144 def __create_lvlb_sched(self, params):
145 if params['levels'] < 2:
146 return []
147
148 utils = self._create_dist('utilization', params['b_utils'],
149 NAMED_UTILIZATIONS)
150
151 # Level-A is present, b must be harmonic with lvla hyperperiod
152 if params['levels'] > 2:
153 plist = [params['a_hyperperiod']*2**x for x in xrange(0, 4)]
154 periods = rv.uniform_choice(plist)
155 else:
156 periods = self._create_dist('period', params['b_periods'],
157 NAMED_PERIODS)
158 max_util = self.__get_max_util(params, 1)
159
160 ts = self._create_taskset(params, periods, utils, max_util)
161 self.__partition_worst_fit(params, ts)
162
163 return ts
164
165 def __create_lvlc_sched(self, params):
166 utils = self._create_dist('utilization', params['c_utils'],
167 NAMED_UTILIZATIONS)
168 periods = self._create_dist('period', params['c_periods'],
169 NAMED_PERIODS)
170 max_util = self.__get_max_util(params, 2)
171
172 return self._create_taskset(params, periods, utils, max_util)
173
174 def _create_exp(self, params):
175 # Ugly way of doing it
176 self.shares = self._create_dist('shares', params['shares'],
177 NAMED_SHARES)
178
179 tasks = {'lvla': self.__create_lvla_sched(params),
180 'lvlb': self.__create_lvlb_sched(params),
181 'lvlc': self.__create_lvlc_sched(params)}
182
183 conf_options = {MC_OPT : 'y'}
184 if params['timer_merging']:
185 conf_options[TM_OPT] = 'y'
186 if params['redirect']:
187 if not params['release_master']:
188 print("Forcing release master option to enable redirection.")
189 params['release_master'] = 'y'
190 conf_options[RD_OPT] = 'y'
191 if params['slack_stealing']:
192 conf_options[SS_OPT] = 'y'
193
194 scales = []
195 for index, level in enumerate('abc'):
196 scales += [('scale%s' % level, self.__get_scale(params, index))]
197
198 schedule_variables = params.items() + tasks.items() + scales
199 param_variables = params.items() + [('config-options',conf_options)]
200
201 self._write_schedule(dict(schedule_variables))
202 self._write_params(dict(param_variables))
203
204 # Ugly
205 del(self.shares)