forked from khchenTW/MissRateSimulator
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimulator.py
More file actions
238 lines (198 loc) · 8.09 KB
/
simulator.py
File metadata and controls
238 lines (198 loc) · 8.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
from __future__ import division
import random
import math
import numpy as np
import operator
# for simulator initialization
class MissRateSimulator:
def __init__( self, n, tasks ):
self.statusTable = [[0 for x in range(4)] for y in range(n)]
self.eventList = []
self.tasks = tasks
self.stampSIM = []
self.h = -1
self.n = n
self.initState()
self.c = 0
#print("statusTable: " + str(self.statusTable))
#print("eventList: " + str(self.eventList))
#print("taks: " + str(self.tasks))
#print("n: " + str(self.n))
class eventClass( object ):
# This is the class of events
def __init__( self, case, delta, idx ):
self.eventType = case
self.delta = delta
self.idx = idx
def case(self):
if self.eventType == 0:
return "release"
else:
return "deadline"
def updateDelta( self, elapsedTime ):
self.delta = self.delta - elapsedTime
"""
The status table for the simulator
per col with 4 rows:
workload
# of release
# of misses
# of deadlines = this should be less than release
"""
def tableReport( self ):
for i, e in enumerate(self.eventList):
print("Event "+str(i)+" from task "+str(e.idx))
print(e.case())
print(e.delta)
for x in range(self.n):
print("task"+str(x)+": ")
for y in range(4):
print(self.statusTable[x][y])
def findTheHighestWithWorkload( self ):
# Assume that the fixed priority is given in the task set.
# if there is no workload in the table, returns -1
hidx = -1
for i in range(self.n):
if self.statusTable[i][0] != 0:
hidx = i
break
else:
pass
return hidx
def release( self, idx, fr ):
# create deadline event to the event list
#print("Add deadline event for "+str(idx))
#print(idx)
#print(self.tasks[idx]['deadline'])
self.eventList.append(self.eventClass(1, self.tasks[idx]['deadline'], idx))
# create release event to the event list
#print("Add release event for "+str(idx))
# sporadic randomness
#spor=self.tasks[idx]['period']+self.tasks[idx]['period']*random.randint(0,20)/100
#eventList.append(eventClass(0, spor, idx))
# periodic setup
self.eventList.append(self.eventClass(0, self.tasks[idx]['period'], idx))
# sort the eventList
self.eventList = sorted(self.eventList, key=operator.attrgetter('delta'))
# add the workload to the table corresponding entry
# fault inject
#if random.randint(0,int(1/fr))>int(1/fr)-1:
if fr == 0:
self.statusTable[ idx ][ 0 ] += self.tasks[idx]['execution']
elif fr == 1:
self.statusTable[ idx ][ 0 ] += self.tasks[idx]['abnormal_exe']
else:
#print("com " + str(int(1/fr)-1))
#print(random.randint(0,int(1/fr)-1))
#print(int(1/fr)-2)
if random.randint(0,int(1/fr)-1)>int(1/fr)-2:
self.statusTable[ idx ][ 0 ] += self.tasks[idx]['abnormal_exe']
else:
self.statusTable[ idx ][ 0 ] += self.tasks[idx]['execution']
# decide the highest priority task in the system
self.h = self.findTheHighestWithWorkload()
if self.h == -1:
print("BUG: after release, there must be at least one task with workload.")
self.statusTable[ idx ][ 1 ]+=1
#print("Table in task"+str(idx)+" release event with h"+str(self.h))
#self.tableReport()
def deadline( self, idx, fr ):
# check if the targeted task in the table has workload.
#print("Table in task"+str(idx)+" deadline event with h"+str(self.h))
#self.tableReport()
if self.workload( idx ) != 0:
print("task"+str(idx)+" misses deadline")
self.statusTable[ idx ][ 2 ] += 1
self.statusTable[ idx ][ 3 ]+=1
#If there is no backlog in the lowest priority task,
#init the simulator again to force the worst release pattern.
#TODO this should be done in the release of higher priority task
if idx == len(self.tasks)-1 and self.workload( idx ) == 0:
#print("Relase the worst pattern")
self.eventList = []
self.c = self.c + 1
self.initState()
def event_to_dispatch( self, event, fr ):
# take out the delta from the event
self.elapsedTime( event )
# execute the corresponding event functions
switcher = {
0: self.release,
1: self.deadline,
}
func = switcher.get( event.eventType, lambda: "ERROR" )
# execute the event
func( event.idx, fr )
def elapsedTime( self, event ):
delta = event.delta
# update the deltas of remaining events in the event list.
if len(self.eventList) == 0:
print("BUG: there is no event in the list to be updated.")
for e in self.eventList:
e.updateDelta( delta )
# update the workloads in the table
while (delta):
self.h = self.findTheHighestWithWorkload()
if self.h == -1:
# processor Idle
delta = 0
elif delta >= self.statusTable[self.h][0]:
delta = delta - self.statusTable[self.h][0]
self.statusTable[ self.h ][ 0 ] = 0
elif delta < self.statusTable[self.h][0]:
self.statusTable[ self.h ][ 0 ] -= delta
delta = 0
def getNextEvent(self):
# get the next event from the event list
event = self.eventList.pop(0)
#print("Get Event: "+event.case() + " from " + str(event.idx))
return event
def missRate( self, idx):
# return the miss rate of task idx
return self.statusTable[ idx ][ 2 ] / self.statusTable[ idx ][ 1 ]
def totalMissRate( self ):
# return the total miss rate of the system
sumRelease = 0
sumMisses = 0
for idx in range(n):
sumRelease += self.statusTable[ idx ][ 1 ]
sumMisses += self.statusTable[ idx ][ 2 ]
return sumMisses/sumRelease
def releasedJobs( self, idx ):
# return the number of released jobs of idx task in the table
#print("Released jobs of " + str(idx) + " is " + str(self.statusTable[ idx ][ 1 ]))
return self.statusTable[ idx ][ 1 ]
def numDeadlines( self, idx ):
# return the number of past deadlines of idx task in the table
#print("Deadlines of " + str(idx) + " is " + str(self.statusTable[ idx ][ 3 ]))
return self.statusTable[ idx ][ 3 ]
def releasedMisses( self, idx ):
# return the number of misses of idx task in the table
return self.statusTable[ idx ][ 2 ]
def workload( self, idx ):
# return the remaining workload of idx task in the table
return self.statusTable[ idx ][ 0 ]
def initState( self ):
# init
#print(self.tasks)
self.eventList = []
# task release together at 0 without delta / release from the lowest priority task
tmp=range(len(self.tasks))
tmp = tmp[::-1]
for idx in tmp:
self.statusTable[ idx ][ 0 ] = 0
self.statusTable[ idx ][ 3 ] = self.statusTable[ idx ][ 1 ]
self.eventList.append(self.eventClass(0,0,idx))
#self.tableReport()
def dispatcher(self, targetedNumber, fr):
# Stop when the number of released jobs in the lowest priority task is equal to the targeted number.
while( targetedNumber != self.numDeadlines( self.n - 1 )):
if len(self.eventList) == 0:
print("BUG: there is no event in the dispatcher")
break
else:
e = self.getNextEvent()
self.event_to_dispatch(e, fr )
print("Stop at task "+str(e.idx))
print(self.c)
#self.tableReport()