Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
las3_pub
/
simso
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
51cc596f
authored
Jun 29, 2021
by
Michael Schmid
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Much work on faults and fault events
parent
b2352129
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
148 additions
and
64 deletions
+148
-64
simso/configuration/Configuration.py
+13
-9
simso/core/Fault.py
+93
-46
simso/core/FaultEvent.py
+26
-0
simso/core/Model.py
+9
-8
simso/core/ProcEvent.py
+4
-0
simso/core/Processor.py
+3
-1
No files found.
simso/configuration/Configuration.py
View file @
51cc596f
...
...
@@ -9,7 +9,7 @@ from simso.core.Scheduler import SchedulerInfo
from
simso.core
import
Scheduler
from
simso.core.Task
import
TaskInfo
from
simso.core.Processor
import
ProcInfo
from
simso.core.Fault
import
FaultInfo
,
FaultF
unction
from
simso.core.Fault
import
FaultInfo
,
FaultF
actory
from
simso.generator.task_generator
import
gen_probabilistic_arrivals
from
simso.generator.task_generator
import
cdf
...
...
@@ -63,6 +63,7 @@ class Configuration(object):
self
.
penalty_preemption
=
parser
.
penalty_preemption
self
.
penalty_migration
=
parser
.
penalty_migration
self
.
fault_info_list
=
parser
.
fault_info_list
self
.
fault_data_fields
=
parser
.
fault_data_fields
else
:
self
.
etm
=
"wcet"
self
.
duration
=
100000000
...
...
@@ -75,6 +76,7 @@ class Configuration(object):
self
.
_proc_info_list
=
[]
self
.
proc_data_fields
=
{}
self
.
fault_info_list
=
[]
self
.
fault_data_fields
=
{}
self
.
memory_access_time
=
100
self
.
_scheduler_info
=
SchedulerInfo
()
self
.
calc_penalty_cache
()
...
...
@@ -193,20 +195,20 @@ class Configuration(object):
"Activation date must be positive."
# Period >= 0:
assert
task
.
period
>
=
0
,
"Tasks' periods must be positives."
assert
task
.
period
>
0
,
"Tasks' periods must be positives."
# Deadline >= 0:
assert
task
.
deadline
>
=
0
,
"Tasks' deadlines must be positives."
assert
task
.
deadline
>
0
,
"Tasks' deadlines must be positives."
# N_instr >= 0:
assert
task
.
n_instr
>=
0
,
\
"A number of instructions must be positive."
# WCET >= 0:
assert
task
.
wcet
>
=
0
,
"WCET must be positive."
assert
task
.
wcet
>
0
,
"WCET must be positive."
# ACET >= 0:
assert
task
.
acet
>
=
0
,
"ACET must be positive."
assert
task
.
acet
>
0
,
"ACET must be positive."
# ET-STDDEV >= 0:
assert
task
.
et_stddev
>=
0
,
\
...
...
@@ -286,7 +288,7 @@ class Configuration(object):
def
add_task
(
self
,
name
,
identifier
,
task_type
=
"Periodic"
,
abort_on_miss
=
True
,
period
=
10
,
activation_date
=
0
,
n_instr
=
0
,
mix
=
0.5
,
stack_file
=
""
,
wcet
=
0
,
acet
=
0
,
pwcet
=
(
0
,
1.0
),
pmit
=
(
0
,
1.0
),
n_instr
=
0
,
mix
=
0.5
,
stack_file
=
""
,
wcet
=
1
,
acet
=
1
,
pwcet
=
(
1
,
1.0
),
pmit
=
(
0
,
1.0
),
et_stddev
=
0
,
deadline
=
10
,
base_cpi
=
1.0
,
followed_by
=
None
,
list_activation_dates
=
[],
preemption_cost
=
0
,
data
=
None
):
"""
...
...
@@ -320,9 +322,11 @@ class Configuration(object):
self
.
proc_info_list
.
append
(
proc
)
return
proc
def
add_fault
(
self
,
fault_
function
,
start_time
,
end_tim
e
):
def
add_fault
(
self
,
fault_
type
:
str
,
start_time
,
end_time
,
target
,
value
=
None
,
parameter
=
Non
e
):
"""
Helper method to create a FaultInfo and add it to the list of faults.
"""
fault
=
FaultInfo
(
start_time
,
end_time
,
fault_function
)
self
.
fault_info_list
.
append
(
fault
)
fault_info
=
FaultInfo
(
fault_type
,
start_time
,
end_time
,
target
,
value
,
parameter
)
self
.
fault_info_list
.
append
(
fault_info
)
return
fault_info
simso/core/Fault.py
View file @
51cc596f
from
simpy
import
Environment
from
typing
import
Callable
from
simso.core.Processor
import
ProcInfo
from
simso.core.Monitor
import
Monitor
from
simso.core.FaultEvent
import
ProcessorFailureEvent
,
VoltageChangeEvent
,
TimingChangeEvent
class
FaultFunction
:
...
...
@@ -18,72 +20,91 @@ class FaultInfo:
The FaultType class is responsible for causing the error.
"""
def
__init__
(
self
,
start_time
:
float
,
end_time
:
float
,
fault_function
:
FaultFunction
):
def
__init__
(
self
,
fault_type
:
str
,
start_time
:
float
,
end_time
:
float
,
fault_target
,
value
,
parameter
:
str
):
self
.
fault_type
=
fault_type
self
.
start_time
=
start_time
self
.
end_time
=
end_time
self
.
fault_function
=
fault_function
self
.
fault_target
=
fault_target
self
.
value
=
value
self
.
parameter
=
parameter
class
Fault
:
"""
The Fault class is the simpy process for triggering a certain error.
The Fault
base
class is the simpy process for triggering a certain error.
"""
def
__init__
(
self
,
sim
,
fault_type
:
FaultInfo
):
self
.
_fault_type
=
fault_type
def
__init__
(
self
,
sim
,
fault_info
:
FaultInfo
,
start_function
:
Callable
,
end_function
:
Callable
):
self
.
_start_function
=
start_function
self
.
_end_function
=
end_function
self
.
_fault_info
=
fault_info
self
.
_sim
=
sim
self
.
_monitor
=
Monitor
(
name
=
"Monitor"
+
fault_info
.
fault_type
,
env
=
sim
)
self
.
process
=
self
.
_sim
.
process
(
self
.
release
())
@property
def
fault_info
(
self
):
return
self
.
_fault_info
@property
def
duration_ms
(
self
):
return
self
.
_fault_info
.
start_time
-
self
.
_fault_info
.
end_time
@property
def
duration_cycles
(
self
):
return
(
self
.
_fault_info
.
start_time
-
self
.
_fault_info
.
end_time
)
*
self
.
_sim
.
cycles_per_ms
def
release
(
self
):
yield
self
.
_sim
.
timeout
(
self
.
_fault_
type
.
start_time
)
yield
self
.
_sim
.
timeout
(
self
.
_fault_
info
.
start_time
*
self
.
_sim
.
cycles_per_ms
)
self
.
_
fault_type
.
fault_function
.
start_function
(
self
.
_sim
)
self
.
_start_function
(
self
.
_sim
)
yield
self
.
_sim
.
timeout
(
self
.
_fault_type
.
end_time
-
self
.
_fault_type
.
start_time
)
yield
self
.
_sim
.
timeout
(
(
self
.
_fault_info
.
end_time
-
self
.
_fault_info
.
start_time
)
*
self
.
_sim
.
y
)
self
.
_
fault_type
.
fault_function
.
end_function
(
self
.
_sim
)
self
.
_end_function
(
self
.
_sim
)
class
ProcessorFailure
(
FaultFunction
):
# TODO: Does not work when only 1 processor in model, maybe use speed = 0 ?
class
ProcessorFailure
(
Fault
):
"""
The ProcessorFailure class simulates a complete stoppage of a processor.
"""
fields
=
[
'fault_target'
]
def
__init__
(
self
,
proc_info
:
ProcInfo
):
super
()
.
__init__
(
self
.
stop_processor
,
self
.
start_processor
)
self
.
_proc_info
=
proc_info
def
__init__
(
self
,
sim
,
fault_info
):
super
()
.
__init__
(
sim
,
fault_info
,
self
.
stop_processor
,
self
.
start_processor
)
self
.
_processor
=
None
def
stop_processor
(
self
,
model
):
self
.
_processor
=
next
(
p
for
p
in
model
.
processors
if
p
.
identifier
==
self
.
_
proc_info
.
identifier
)
p
for
p
in
model
.
processors
if
p
.
identifier
==
self
.
_
fault_info
.
fault_target
.
identifier
)
self
.
_processor
.
fail
(
self
)
self
.
_monitor
.
observe
(
ProcessorFailureEvent
(
self
))
def
start_processor
(
self
,
model
):
self
.
_processor
.
fail
()
class
VoltageChange
(
Fault
Function
):
class
VoltageChange
(
Fault
):
def
__init__
(
self
,
proc_info_list
,
scaling
:
float
):
super
()
.
__init__
(
self
.
start_voltage_change
,
self
.
end_voltage_change
)
self
.
_proc_info_list
=
proc_info_list
s
elf
.
_processor_list
=
[]
self
.
_
scaling
=
scaling
fields
=
[
'fault_target'
,
'value'
]
def
__init__
(
self
,
sim
,
fault_info
):
s
uper
()
.
__init__
(
sim
,
fault_info
,
self
.
start_voltage_change
,
self
.
end_voltage_change
)
self
.
_
processor
=
None
def
start_voltage_change
(
self
,
model
):
affected_ids
=
[
p
.
identifier
for
p
in
self
.
_proc_info_list
]
self
.
_processor_list
=
[
p
for
p
in
model
.
processors
if
p
.
identifier
in
affected_ids
]
for
p
in
self
.
_processor_list
:
p
.
set_speed
(
self
.
_scaling
*
p
.
speed
)
self
.
_processor
=
next
(
p
for
p
in
model
.
processors
if
p
.
identifier
==
self
.
_fault_info
.
fault_target
.
identifier
)
self
.
_processor
.
set_speed
(
self
.
_fault_info
.
value
*
self
.
_processor
.
speed
)
self
.
_monitor
.
observe
(
VoltageChangeEvent
(
self
)
)
def
end_voltage_change
(
self
,
model
):
for
p
in
self
.
_processor_list
:
speed
=
next
(
pi
for
pi
in
self
.
_proc_info_list
if
pi
.
identifier
==
p
.
identifier
)
.
speed
p
.
set_speed
(
speed
)
self
.
_processor
.
set_speed
(
self
.
_fault_info
.
fault_target
.
speed
)
class
VoltageDrop
(
VoltageChange
):
...
...
@@ -91,9 +112,9 @@ class VoltageDrop(VoltageChange):
The VoltageDrop class simulates the slowdown of one or more processors due to voltage drops.
"""
def
__init__
(
self
,
proc_info_list
,
scaling
:
float
):
assert
scaling
>=
0
and
scaling
<=
1.0
,
"Voltage drop reduces the speed of a processor, i.e. scaling has to be >= 0 and <= 1"
super
()
.
__init__
(
proc_info_list
,
scaling
)
def
__init__
(
self
,
sim
,
fault_info
):
assert
fault_info
.
value
>=
0
and
fault_info
.
value
<=
1.0
,
"Voltage drop reduces the speed of a processor, i.e. scaling has to be >= 0 and <= 1"
super
()
.
__init__
(
sim
,
fault_info
)
# TODO: rethink this class
...
...
@@ -126,23 +147,26 @@ class PriorityInversion(FaultFunction):
pass
class
TimingChange
(
Fault
Function
):
class
TimingChange
(
Fault
):
"""
The TimingError class simulates changes in the timing parameters, e.g. deadline, period etc.
"""
def
__init__
(
self
,
task_info
,
parameter
:
str
,
value
:
float
):
super
()
.
__init__
(
self
.
start_timing_change
,
self
.
end_timing_change
)
self
.
_task_info
=
task_info
s
elf
.
_parameter
=
parameter
self
.
_
value
=
value
self
.
_old_value
=
getattr
(
self
.
_task_info
,
parameter
)
fields
=
[
'fault_target'
,
'parameter'
,
'value'
]
def
__init__
(
self
,
sim
,
fault_info
):
s
uper
()
.
__init__
(
sim
,
fault_info
,
self
.
start_timing_change
,
self
.
end_timing_change
)
self
.
_
old_value
=
getattr
(
self
.
_fault_info
.
fault_target
,
fault_info
.
parameter
)
def
start_timing_change
(
self
,
model
):
setattr
(
self
.
_task_info
,
self
.
_parameter
,
self
.
_value
)
setattr
(
self
.
_fault_info
.
fault_target
,
self
.
_fault_info
.
parameter
,
self
.
_fault_info
.
value
)
self
.
_monitor
.
observe
(
TimingChangeEvent
(
self
))
def
end_timing_change
(
self
,
model
):
setattr
(
self
.
_task_info
,
self
.
_parameter
,
self
.
_old_value
)
setattr
(
self
.
_fault_info
.
fault_target
,
self
.
_fault_info
.
parameter
,
self
.
_old_value
)
class
TimingError
(
TimingChange
):
...
...
@@ -150,11 +174,34 @@ class TimingError(TimingChange):
The TimingError class simulates changes in the timing parameters, e.g. deadline, period etc.
"""
def
__init__
(
self
,
task_info
,
parameter
:
str
,
value
:
float
):
super
()
.
__init__
(
task_info
,
parameter
,
value
)
def
__init__
(
self
,
sim
,
fault_info
):
super
()
.
__init__
(
sim
,
fault_info
)
class
Redundancy
(
TimingChange
):
def
__init__
(
self
,
task_info
,
value
:
float
):
super
()
.
__init__
(
task_info
,
"wcet"
,
task_info
.
wcet
+
value
)
def
__init__
(
self
,
sim
,
fault_info
):
fault_info
.
parameter
=
"wcet"
fault_info
.
value
=
fault_info
.
fault_target
.
wcet
+
fault_info
.
value
super
()
.
__init__
(
sim
,
fault_info
)
fault_types
=
{
"TimingError"
:
TimingError
,
"TimingChange"
:
TimingChange
,
"Redundancy"
:
Redundancy
,
"VoltageChange"
:
VoltageChange
,
"VoltageDrop"
:
VoltageDrop
,
"ProcessorFailure"
:
ProcessorFailure
}
fault_types_names
=
[
"TimingError"
,
"TimingChange"
,
"Redundancy"
,
"VoltageChange"
,
"VoltageDrop"
,
"ProcessorFailure"
]
def
FaultFactory
(
sim
,
fault_info
):
"""
Task factory. Return and instantiate the correct class according to the
task_info.
"""
return
fault_types
[
fault_info
.
fault_type
](
sim
,
fault_info
)
simso/core/FaultEvent.py
0 → 100644
View file @
51cc596f
class
FaultEvent
:
PROCESSOR_FAILURE
=
1
VOLTAGE_DROP
=
2
VOLTAGE_CHANGE
=
3
TIMING_ERROR
=
4
TIMING_CHANGE
=
5
REDUNDANCY
=
6
def
__init__
(
self
,
event
=
0
,
args
=
None
):
self
.
event
=
event
self
.
args
=
args
class
ProcessorFailureEvent
(
FaultEvent
):
def
__init__
(
self
,
fault
):
FaultEvent
.
__init__
(
self
,
FaultEvent
.
PROCESSOR_FAILURE
,
fault
)
class
VoltageChangeEvent
(
FaultEvent
):
def
__init__
(
self
,
fault
):
FaultEvent
.
__init__
(
self
,
FaultEvent
.
VOLTAGE_CHANGE
,
fault
)
class
TimingChangeEvent
(
FaultEvent
):
def
__init__
(
self
,
fault
):
FaultEvent
.
__init__
(
self
,
FaultEvent
.
TIMING_CHANGE
,
fault
)
simso/core/Model.py
View file @
51cc596f
...
...
@@ -8,7 +8,7 @@ from simso.core.Timer import Timer
from
simso.core.etm
import
execution_time_models
from
simso.core.Logger
import
Logger
from
simso.core.results
import
Results
from
simso.core.Fault
import
Fault
from
simso.core.Fault
import
Fault
Factory
class
Model
(
Environment
):
...
...
@@ -63,7 +63,7 @@ class Model(Environment):
self
.
_fault_list
=
[]
for
fault_info
in
fault_info_list
:
self
.
_fault_list
.
append
(
Fault
(
self
,
fault_info
))
self
.
_fault_list
.
append
(
Fault
Factory
(
self
,
fault_info
))
# XXX: too specific.
self
.
penalty_preemption
=
configuration
.
penalty_preemption
...
...
@@ -124,6 +124,13 @@ class Model(Environment):
return
self
.
_task_list
@property
def
fault_list
(
self
):
"""
List of all faults
"""
return
self
.
_fault_list
@property
def
duration
(
self
):
"""
Duration of the simulation.
...
...
@@ -140,12 +147,6 @@ class Model(Environment):
self
.
scheduler
.
init
()
self
.
progress
.
start
()
# for cpu in self._processors:
# self.process(cpu.run())
# for task in self._task_list:
# self.process(task.execute())
try
:
self
.
run
(
until
=
self
.
_duration
)
finally
:
...
...
simso/core/ProcEvent.py
View file @
51cc596f
...
...
@@ -5,6 +5,7 @@ class ProcEvent(object):
RUN
=
1
IDLE
=
2
OVERHEAD
=
3
FAILED
=
4
def
__init__
(
self
,
event
=
0
,
args
=
None
):
self
.
event
=
event
...
...
@@ -20,6 +21,9 @@ class ProcIdleEvent(ProcEvent):
def
__init__
(
self
):
ProcEvent
.
__init__
(
self
,
ProcEvent
.
IDLE
)
class
ProcFailedEvent
(
ProcEvent
):
def
__init__
(
self
,
fault
):
ProcEvent
.
__init__
(
self
,
ProcEvent
.
FAILED
,
fault
)
class
ProcOverheadEvent
(
ProcEvent
):
def
__init__
(
self
,
type_overhead
):
...
...
simso/core/Processor.py
View file @
51cc596f
...
...
@@ -3,7 +3,7 @@
from
collections
import
deque
from
simpy
import
Process
# from SimPy.Simulation import Process, Monitor, hold, waituntil
from
simso.core.ProcEvent
import
ProcRunEvent
,
ProcIdleEvent
,
\
from
simso.core.ProcEvent
import
ProcRunEvent
,
ProcIdleEvent
,
ProcFailedEvent
,
\
ProcOverheadEvent
,
ProcCxtSaveEvent
,
ProcCxtLoadEvent
from
simso.core.Monitor
import
Monitor
from
simso.core.EventQueue
import
EventQueue
...
...
@@ -210,6 +210,8 @@ class Processor:
elif
evt
[
0
]
==
FAIL
:
if
self
.
_fault
is
not
None
:
self
.
sched
.
processors
.
remove
(
self
)
self
.
monitor
.
observe
(
ProcFailedEvent
(
self
.
_fault
))
# self._model.timeout()
elif
not
self
in
self
.
sched
.
processors
:
self
.
sched
.
processors
.
append
(
self
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment