This is a fork of the gem5 simulator. The main purpose of this project is to add a fault injection system to the simulation.
Currently only these kind of injection are possible:
- Branch Prediction Unit fault injection
- Register File fault injection
git clone https://github.com/cancro7/gem5.git
cd gem5
sudo apt-get update; sudo apt-get upgrade
sudo apt-get install scons swig gcc m4 python python-dev libgoogle-perftools-dev g++ protobuf-compiler protobuf-c-compiler zlib1g-dev libprotobuf-dev
A more detailed guide is available here
scons build/ALPHA/gem5.opt -j4
build/ALPHA/gem5.opt configs/example/se.py -c tests/test-progs/hello/bin/alpha/linux/hello
cd /opt
sudo wget http://www.m5sim.org/dist/current/alphaev67-unknown-linux-gnu.tar.bz2
sudo tar -jxf alphaev67-unknown-linux-gnu.tar.bz2
sudo chown $USER -R alphaev67-unknown-linux-gnu
sudo gedit /etc/environment
Add the following path to the PATH variable:
/opt/alphaev67-unknown-linux-gnu/bin
Save the file and reboot the machine
sudo apt-get install gcc-arm-linux-gnueabi
Currently only BTB (Branch Target Buffer) injections are possible.
We build a python script that firstly runs a simulation without any fault injection (golden) and then runs a simulation for each faults specified in a file.
The script is located in the main folder of gem5 and it's called fault-injection-simulation.py
This script has the following parameters:
- -b --benchmarks : specify the path of the desired testbench to be executed
- -i --fault-input : specify the path of the file containing all the desired fault to inject
- -o --options : if needed testbench arguments can be passed as a string (i.e. -o "arg1 arg2 ...")
The fault-input file must be formatted in the following way:
LABEL: STACK_AT, FIELD, ENTRY_NUMBER, BIT_POSITION, START_TICK, END_TICK
For sake of clarity an example is reported below:
FAULT0: 1 , 0 , 232 , 5 , 0 , -1
In this example it's specified a fault labelled "FAULT0" which will be stuck at 1 the 5-th bit of the tag field of the 232-th entry of the BTB. Field value must be 0,1 or 2 according to this list:
- 0 : tag field of the BTB
- 1 : target field of the BTB
- 2 : validity field of the BTB
If the start tick is equals to 0 and the end tick is equals to -1 then the fault is permanent.
After a simulation all the stats files are saved in the folder m5out\your_testbench
. In particular the generated files are the GOLDEN.txt
, which reports all the statistics related to the golden run, and for each fault specified in the fault-file it will be generated a file FAULT_LABEL.txt
.
It's also generated a file containing all the BTB access of the golden run in order to understand which entries must be excited to inject faults in an effectively way.
To view graphically this histogram simply execute the following command:
./util/btb_histogram.py m5out/btb-access-count.txt
After a simulation it is possible to plot a barchart to display some given statistics by simply executing the stats.py
script. Here is reported an execution command example which will plot two different barcharts (one for each specified statistic) for the test Hello World
program:
python stats.py -d m5out/hello -s system.cpu.branchPred.condPredicted sim_seconds -g
The stats.py
script requires an additional dependency which can be installed with the following command:
sudo apt-get install python-matplotlib
It has been added also a new functionality to gem5 in order to generate a trace file of a desired bus. To generate this file simply call gem5 with the new defined debug flag DataCommMonitor. For example, in order to sniff the instruction cache bus of a specific testbench, execute a simulation with the following command:
build/ARM/gem5.opt --debug-flag=DataCommMonitor configs/lapo/arm_mem_trace.py tests/test-progs/mem_set/bin/arm/mem_set.o
In this example the instruction cache bus is sniffed because in the file configs/lapo/arm_mem_trace.py
the following specification is present:
system.cpu.dcache_port = system.membus.slave
system.cpu.icache_port = system.cpu.monitor.slave
system.cpu.monitor.master = system.membus.slave
# dcache_port <-> membus
# icache_port <-> monitor <-> membus
In the m5out folder will be generated a mem_trace.txt
file which has the following structure:
- r/a to specify if it is a request or an acknowledgment packet
- instant of the sample expressed in pico-seconds
- r/w to specify if it is write or a read
- address expressed in hexadecimal form
- data expressed in heaxdecimal form
For sake of clarity an example is reported:
r 1333000ps r 0000000000000664 e1a05003
a 1388000ps r 0000000000000664 159c3000
Notice how an acknowledgment with the correct data is alsways present after a reqeust. This file format is already compatible as input for lapo.
It is also possible to inject a bit flip fault in the register file at a specified time.
In order to do this operation please edit the file configs/lapo/reg_fault.py
. At the end of this file is possible to set the injection parameters.
For example this configuration:
root.registerFault = RegisterFault()
root.registerFault.startTick = 143930180
root.registerFault.system = system
root.registerFault.registerCategory = 0
root.registerFault.faultRegister = 13
root.registerFault.bitPosition = 4
will flip the 4-th bit of the 13-th int register at the simulation tick 143930180. To understand an appropriate time to inject this fault we recommend to run gem5 with the Exec debug flag.
Please refer to src/***/registers.hh
file to understand which registers are available for the chosen architecture.
Control faults simulate an address decoder fault in the branch prediction unit. The fault is implemented by applying an Action onnly on selected addresses through the Trigger condition.
With a trigger it is possible to select a subset of address. A boolean expression can be specified using the following operators:
&
(bitwise and)|
(bitwise or)&&
(logic and)||
(logic or)!
(logic not)>
(greather than)<
(less than)>=
(greater or equal than)<=
(less or equal than)==
(equal)
Only two type of operands are available:
- constants using hexadecimal base (ex 0x01)
- index (to represent the address)
Notice: in order to access the i-th entry of the BTB since it takes the log2(N_BTB_ENTRIES) least significant bits of the Program Counter all index reference must be like this:
(index & 0xFF) //In case of a BTB size of 256 entries
Notice: Paranthesis must be always used!
With an action it's possible to specify the desired action to be performed on the selected addresses. The available operators are:
&
(bitwise and)|
(bitwise or)^
(bitwise xor)~
(bitwise not)<<
(left shift)>>
(right shift)
In the following is reported an example to calrify the concepts.
Suppose we want to select all addresses between 0 and 10 and to stuck at 1 the least significant bit.
Trigger:
((index & 0x1F) >= 0x1) && ((index & 0x1F) < 0xA)
Action:
index | 0x1