diff --git a/application/Makefile b/application/Makefile index 0c4f96858db660a80cd0601d67b9a7f163ef39bc..63a2de68b175d87f02cfb4647781032780b46b89 100644 --- a/application/Makefile +++ b/application/Makefile @@ -1,17 +1,24 @@ #cflags pour tout compiler CXXFLAGS=`otawa-config otawa/display --cflags` -LDLIBS2=`otawa-config otawa/display otawa/classic_ecb otawa/ucb_otawa --libs` +LDLIBS2=`otawa-config otawa/display otawa/classic_ecb otawa/ucb_otawa otawa/etime --libs` -Wl,-rpath,"/home/fabien/cristal/otawa/lib/otawa/otawa/" + CXXFLAGS += -std=c++11 -O0 -g -I ../include ARMCC=arm-none-eabi-gcc -all: application basic big_function +all: application basic big_function application_task application: application.o - $(CXX) -o application application.o $(LDLIBS2) + $(CXX) -o application application.o $(LDLIBS2) $(CXXFLAGS) application.o: application.cpp application.h + +application_task: application_task.o + $(CXX) -o application_task application_task.o $(LDLIBS2) $(CXXFLAGS) + +application_task.o: application_task.cpp application.h + basic: basic_f_l_c.c $(ARMCC) -nostdlib -nostdinc -static -o basic basic_f_l_c.c diff --git a/application/application.cpp b/application/application.cpp index 0d0665b64e733dd7e6c9654aeb5c5d7e77b14c46..f02785d7974cf3feb65a0f6b548636b6993bbd7e 100644 --- a/application/application.cpp +++ b/application/application.cpp @@ -14,9 +14,12 @@ #include <otawa/display/CFGOutput.h> #include <otawa/cache/features.h> #include <otawa/cache/cat2/CAT2Builder.h> +// edge time processors +#include <otawa/etime/features.h> + #include <elm/io/OutFileStream.h> #include <otawa/flowfact/features.h> -#include <multiset.h> +//#include <multiset.h> #include "../classic_ecb/include/classic_ecb.h" #include "../ucb_otawa/include/ucb_otawa.h" #include "application.h" @@ -29,7 +32,27 @@ using namespace Mathset; int main(int argc, char **argv) { - + if (argc < 5) { + fprintf(stderr, "usage: %s <binary> <cache> <flow facts> <sortie>\n", argv[0]); + exit(1); + } + + // //----------------------------- TRIVIAL + WorkSpace *ws_trivial = NULL; + PropList conf_trivial; + Manager manager_trivial; + NO_SYSTEM(conf_trivial) = true; + TASK_ENTRY(conf_trivial) = "main"; + VERBOSE(conf_trivial) = true; + FLOW_FACTS_PATH(conf_trivial) = argv[3]; + + ws_trivial = manager_trivial.load(argv[1], conf_trivial); + ws_trivial->run("otawa::Virtualizer", conf_trivial); + + ws_trivial->require(otawa::ipet::WCET_FEATURE, conf_trivial); + long wcet_trivial = ipet::WCET(ws_trivial); + + // //------------------------------------------------------------- WorkSpace *ws = NULL; PropList conf; Manager manager; @@ -37,35 +60,50 @@ int main(int argc, char **argv) { TASK_ENTRY(conf) = "main"; VERBOSE(conf) = true; - if (argc < 5) { - fprintf(stderr, "usage: %s <binary> <cache> <flow facts> <sortie>\n", argv[0]); - exit(1); - } + CACHE_CONFIG_PATH(conf) = argv[2]; FLOW_FACTS_PATH(conf) = argv[3]; - - ws = manager.load(argv[1], conf); + PROCESSOR_PATH(conf) = "/home/fabien/cristal/otawa-plugins/application/hardware/pipeline/lpc2138.xml"; + MEMORY_PATH(conf) = "/home/fabien/cristal/otawa-plugins/application/hardware/memory/lpc2138.xml"; + otawa::etime::RECORD_TIME(conf) = true; + // Platform description + //CACHE_CONFIG_PATH(conf) = "/home/fabien/cristal/otawa-plugins/application/xmc4500/cache.xml"; + //PROCESSOR_PATH(conf) = "/home/fabien/cristal/otawa-plugins/application/xmc4500/pipeline.xml"; + + ws = manager.load(argv[1], conf); + ws->run("otawa::Virtualizer", conf); + ws->require(otawa::ICACHE_CONSTRAINT2_FEATURE, conf); + //ws->require(otawa::ICACHE_ONLY_CONSTRAINT2_FEATURE, conf); + ws->require(otawa::etime::EDGE_TIME_FEATURE, conf); + ws->require(otawa::ipet::WCET_FEATURE, conf); + ws->require(DynFeature("otawa::ucb_otawa::UCB_OTAWA_FEATURE"), conf); ws->require(DynFeature("otawa::classic_ecb::CLASSIC_ECB_PROCESSOR"), conf); //ws->require(otawa::ipet::ILP_SYSTEM_FEATURE, conf); - ws->require(otawa::ICACHE_CONSTRAINT2_FEATURE, conf); - ws->require(otawa::ipet::WCET_FEATURE, conf); - - long wcet = ipet::WCET(ws); + + + long wcet = ipet::WCET(ws) - wcet_trivial; Multiset<int> ucbs = TOTAL_UCB(ws); Multiset<int> *ecbs = ECBS(ws); - + if(wcet > 1000000) { + return 0; + } std::ofstream f(argv[4], std::ofstream::app); - f <<"(" << wcet << ", 10, 10 ," << std::endl << "{"; + + + f <<"(" << argv[1] << "," << wcet << ", 10, 10 ," << std::endl << "{"; ecbs->to_string(f); + + f << "}," << std::endl << "{"; ucbs.to_string(f); f << "}," << std::endl << "{"; - + + const CFGCollection *coll = INVOLVED_CFGS(ws); Mathset::Multiset<Mathset::Multiset<int>> ucb_list = UCB_OTAWA(ws); @@ -78,7 +116,6 @@ int main(int argc, char **argv) { f << "})" << endl; f.close(); - const otawa::hard::CacheConfiguration *cf = otawa::hard::CACHE_CONFIGURATION_FEATURE.get(ws); const otawa::hard::Cache* cache = cf->instCache(); diff --git a/application/bin/Makefile b/application/bin/Makefile index ef9274e1f0d7ce1f83fa3e3b2c1f7c12713212b0..77363746b57be87c236a8fc4d9b64503e288e44a 100644 --- a/application/bin/Makefile +++ b/application/bin/Makefile @@ -1,11 +1,11 @@ -ARMCC=arm-none-eabi-gcc +ARMCC=arm-linux-gnueabi-gcc -all: bs.exe cover.exe crc.exe fdct.exe fibcall.exe insertsort.exe janne_complex.exe jfdctint.exe lcdnum.exe matmult.exe ndes.exe nsichneu.exe +all: bs.elf cover.elf crc.elf fdct.elf fibcall.elf insertsort.elf janne_complex.elf jfdctint.elf lcdnum.elf matmult.elf ndes.elf nsichneu.elf -%.exe: %.c - $(ARMCC) -nostdlib -nostdinc -static -g -O0 -o $@ $< +%.elf: %.c + $(ARMCC) -nostdlib -nostdinc -static -g3 -O0 -o $@ $< orange --auto $< main -o $*.backup.ffx @@ -20,5 +20,5 @@ clean-backup: rm -f *.backup.ffx clean-binary: - rm -f *.exe + rm -f *.elf diff --git a/application/bin/fdct.ffx b/application/bin/fdct.ffx index 5831b7b3049c396cfb12fce199627245e9b7420a..ef90b8ffbe1605c4eca21de13e117a2ed3b6d8f0 100644 --- a/application/bin/fdct.ffx +++ b/application/bin/fdct.ffx @@ -8,7 +8,7 @@ WARNING: otawa::FlowFactLoader 1.4.0:no flow fact file for fdct.exe <function label="fdct"> <!-- 0x00008000 (fdct.c:68) --> <loop label="fdct" offset="0x45c" maxcount="8" totalcount="8"> <!-- 0x0000845c (fdct.c:83) --> </loop> - <loop label="fdct" offset="0xa28" maxcount="8" totalcount="8"> <!-- 0x00008a28 (fdct.c:161) --> + <loop label="fdct" offset="0xa10" maxcount="8" totalcount="8"> <!-- 0x00008a28 (fdct.c:161) --> </loop> </function> diff --git a/explo/application.cpp b/explo/application.cpp index dab9dff7f04a680ff6fca62920ef01fbc9865104..e3183e8bb7a4e65dd0f991f33761efd9f12afc56 100644 --- a/explo/application.cpp +++ b/explo/application.cpp @@ -39,15 +39,23 @@ int main(int argc, char **argv) { WorkSpace *ws = NULL; + //WorkSpace *ws_trivial = NULL; PropList conf; + //PropList conf_trivial; Manager manager; + //Manager manager_trivial; NO_SYSTEM(conf) = true; TASK_ENTRY(conf) = "main"; VERBOSE(conf) = true; + // NO_SYSTEM(conf_trivial) = true; + // TASK_ENTRY(conf_trivial) = "main"; + // VERBOSE(conf_trivial) = true; + // Flow fact std::cout << "-------------------- Configuration paths ----------------------" << std::endl; FLOW_FACTS_PATH(conf) = argv[2]; + //FLOW_FACTS_PATH(conf_trivial) = argv[2]; // Platform description CACHE_CONFIG_PATH(conf) = "xmc4500/cache.xml"; @@ -59,23 +67,29 @@ int main(int argc, char **argv) { std::cout << "----------------------------Workspace building----------------------------------" << std::endl; ws = manager.load(argv[1], conf); - + //ws_trivial = manager_trivial.load(argv[1], conf_trivial); // CFG Building std::cout << "----------------------------run virtualizer--------------------------------------" << std::endl; ws->run("otawa::Virtualizer", conf); + //ws_trivial->run("otawa::Virtualizer", conf_trivial); std::cout << "-------------------------------cache configuration-----------------------------------------" << std::endl; - ws->require(otawa::ICACHE_ONLY_CONSTRAINT2_FEATURE , conf); + // ws->require(otawa::ICACHE_ONLY_CONSTRAINT2_FEATURE , conf); std::cout << "-------------------------------edge time-----------------------------------------" << std::endl; otawa::etime::RECORD_TIME(conf) = true; - // ws->require(otawa::ICACHE_CONSTRAINT2_FEATURE , conf); - ws->require(otawa::ICACHE_ONLY_CONSTRAINT2_FEATURE, conf); + + //ws->require(otawa::ICACHE_ONLY_CONSTRAINT2_FEATURE, conf); + //ws->require(otawa::ICACHE_CONSTRAINT2_FEATURE , conf); ws->require(otawa::etime::EDGE_TIME_FEATURE, conf); - + std::cout << "-------------------------------wcet----------------------------------------------" << std::endl; ws->require(otawa::ipet::WCET_FEATURE, conf); ws->require(DynFeature("otawa::explo::EXPLO_FEATURE"), conf); + + + //ws_trivial->require(otawa::ipet::WCET_FEATURE, conf_trivial); std::cout << "WCET:" << ipet::WCET(ws) << std::endl; + // std::cout << "WCET:" << ipet::WCET(ws_trivial) << std::endl; return 0; } diff --git a/explo/explo.cpp b/explo/explo.cpp index f00e6c08c535ee2f8d505e2a6b7aab4b1ca2d749..caf24618597264b3543a904efe5261628cc6d360 100644 --- a/explo/explo.cpp +++ b/explo/explo.cpp @@ -261,12 +261,6 @@ namespace otawa { for(CFGCollection::Iter cfg_iter(*coll); cfg_iter(); cfg_iter++) { CFG* tmp = *cfg_iter; explo_cfg(tmp); - /*std::cout << "EXIT: "; - std::vector<Block*> vector_blocks = get_last_blocks(tmp); - for(int i = 0; i < vector_blocks.size(); i++) { - std::cout << vector_blocks[i]->id() << " "; - } - */ std::cout << std::endl; } } diff --git a/vulnerability/Makefile b/vulnerability/Makefile index a6319fd28ee676c7e340c190a8dc7be5f9649564..578818c9304b43f0e68275f24a4b95ab46f54a6e 100644 --- a/vulnerability/Makefile +++ b/vulnerability/Makefile @@ -26,8 +26,8 @@ application: application.o application.o: application.cpp -vulnerability.so: vulnerability.cpp include/vulnerability.h - $(CXX) -fPIC -shared $(CXXFLAGS) -o vulnerability.so vulnerability.cpp $(LDLIBS) +vulnerability.so: vulnerability.cpp include/vulnerability.h include/type.h + $(CXX) -fPIC -shared $(CXXFLAGS) -o vulnerability.so vulnerability.cpp $(LDLIBS) ##fin diff --git a/vulnerability/application b/vulnerability/application index 785d2bbca25dadf861edea64957c6bd70470e25f..f9dde2cd4aa23b1d5518fa96a02c63235db93c8d 100755 Binary files a/vulnerability/application and b/vulnerability/application differ diff --git a/vulnerability/application.cpp b/vulnerability/application.cpp index e4c27cf273ad93d46bf749c5dd34d8c5a0be2220..cd97c8b7a7ca1c71f5cc21917d6cc98d6d518b5b 100644 --- a/vulnerability/application.cpp +++ b/vulnerability/application.cpp @@ -40,7 +40,7 @@ int main(int argc, char **argv) { ws->run("otawa::Virtualizer", conf); ws->require(otawa::ICACHE_CONSTRAINT2_FEATURE, conf); - ws->require(otawa::etime::EDGE_TIME_FEATURE, conf); + ws->require(otawa::etime::EDGE_TIME_FEATURE, conf); ws->require(otawa::ipet::WCET_FEATURE, conf); ws->require(DynFeature("otawa::vulnerability::VULNERABILITY_FEATURE"), conf); std::cout << "vulnerability:" << VUL(ws) << " WCET:" << ipet::WCET(ws) << std::endl; diff --git a/vulnerability/application.o b/vulnerability/application.o index 1a25d082a1fdee7d674f304d87033911ce58a4ab..1e8f90bd0399e1d996bdaa88b1a1902d44858669 100644 Binary files a/vulnerability/application.o and b/vulnerability/application.o differ diff --git a/vulnerability/include/vulnerability.h b/vulnerability/include/vulnerability.h index d609b6def5757f63e4f905792a8be38433cbccad..282efde6f4c56e41612a574ea0bafca32a0b92c2 100644 --- a/vulnerability/include/vulnerability.h +++ b/vulnerability/include/vulnerability.h @@ -14,6 +14,9 @@ #include <otawa/proc/ProcessorPlugin.h> #include <otawa/cfg/Dominance.h> #include <otawa/otawa.h> + +#include "type.h" + namespace otawa { namespace vulnerability { class VulnerabilityProcessor : public Processor { public: @@ -35,5 +38,9 @@ extern Identifier<DAGHNode*> DAG_HNODE; extern Identifier<unsigned long> VUL; extern Identifier<std::vector<Address>*> UCB_IN; extern Identifier<std::vector<Address>*> UCB_OUT; -} } + + void start_rmb_lmb_computation(WorkSpace *ws); + extern Identifier<struct Memory_block *> MB_STRUCT; + } +} #endif diff --git a/vulnerability/vulnerability.cpp b/vulnerability/vulnerability.cpp index 06a1089fc12cec117c0823767a25c23c5b3bedfb..8d291871e82b9b6e334213e09434af70ccdfcd8c 100644 --- a/vulnerability/vulnerability.cpp +++ b/vulnerability/vulnerability.cpp @@ -1,4 +1,3 @@ -#include "../initialize_RMB_LMB/include/initialize_RMB_LMB.h" #include "include/vulnerability.h" #include <cmath> #include <otawa/proc/DynFeature.h> @@ -18,412 +17,1216 @@ #include <otawa/flowfact/features.h> #include <otawa/cfg/Loop.h> #include <otawa/etime/features.h> -using namespace otawa::initialize_RMB_LMB; + +#include <otawa/cache/LBlock.h> + +using namespace otawa::vulnerability; using namespace otawa::lblock_time; namespace otawa { - namespace vulnerability { - - // Declaration du plugin - - class Plugin : public ProcessorPlugin { - public: - Plugin() : ProcessorPlugin("otawa::vulnerability", Version(1, 0, 0), OTAWA_PROC_VERSION) {} - }; - - otawa::vulnerability::Plugin vulnerability_plugin; - ELM_PLUGIN(vulnerability_plugin, OTAWA_PROC_HOOK); - - p::declare VulnerabilityProcessor::reg = p::init("otawa::vulnerability::VulnerabilityProcessor", Version(1, 0, 0)) - .require(COLLECTED_CFG_FEATURE) - .require(LOOP_INFO_FEATURE) - .require(ICACHE_CONSTRAINT2_FEATURE) - .require(etime::EDGE_TIME_FEATURE) - .require(INITIALIZE_RMB_LMB_FEATURE) - .require(otawa::lblock_time::LBLOCK_TIME_FEATURE) - .require(ipet::ILP_SYSTEM_FEATURE) - .require(ipet::WCET_FEATURE) - .provide(VULNERABILITY_FEATURE); - //.require(otawa::lblock_time::LBLOCK_TIME_FEATURE) - //INITIALIZE_RMB_LMB_FEATURE + namespace vulnerability { + + // Declaration du plugin + + class Plugin : public ProcessorPlugin { + public: + Plugin() : ProcessorPlugin("otawa::vulnerability", Version(1, 0, 0), OTAWA_PROC_VERSION) {} + }; + + otawa::vulnerability::Plugin vulnerability_plugin; + ELM_PLUGIN(vulnerability_plugin, OTAWA_PROC_HOOK); + + p::declare VulnerabilityProcessor::reg = p::init("otawa::vulnerability::VulnerabilityProcessor", Version(1, 0, 0)) + .require(COLLECTED_CFG_FEATURE) + .require(LOOP_INFO_FEATURE) + .require(ICACHE_CONSTRAINT2_FEATURE) + .require(etime::EDGE_TIME_FEATURE) + .require(otawa::lblock_time::LBLOCK_TIME_FEATURE) + .require(ipet::ILP_SYSTEM_FEATURE) + .require(ipet::WCET_FEATURE) + .provide(VULNERABILITY_FEATURE); + //.require(otawa::lblock_time::LBLOCK_TIME_FEATURE) + //INITIALIZE_RMB_LMB_FEATURE - // definition feature - p::feature VULNERABILITY_FEATURE("otawa::vulnerability::VULNERABILITY_FEATURE", new Maker<VulnerabilityProcessor>()); + // definition feature + p::feature VULNERABILITY_FEATURE("otawa::vulnerability::VULNERABILITY_FEATURE", new Maker<VulnerabilityProcessor>()); - VulnerabilityProcessor::VulnerabilityProcessor(p::declare &r) : Processor(r) {} + VulnerabilityProcessor::VulnerabilityProcessor(p::declare &r) : Processor(r) {} - void VulnerabilityProcessor::configure(const PropList &props) { - Processor::configure(props); - } + void VulnerabilityProcessor::configure(const PropList &props) { + Processor::configure(props); + } - void print_mb(std::vector<std::vector<Address>> *multi, int nb_index) { - //std::cout << "{"; - for(int i = 0; i < nb_index; i++) { + + void print_mb(std::vector<std::vector<Address>> *multi, int nb_index) { + //std::cout << "{"; + for(int i = 0; i < nb_index; i++) { - std::vector<std::vector<Address>> tmp = multi[i]; - std::cout << "[" << i << "]"; + std::vector<std::vector<Address>> tmp = multi[i]; + std::cout << "[" << i << "]"; - for(int j = 0; j < tmp.size(); j++) { - std::cout << " {"; - for(int k = 0; k < tmp[j].size(); k++) { - std::cout << tmp[j][k].page() << ":" << tmp[j][k].offset() << " "; - } - std::cout << "}"; + for(int j = 0; j < tmp.size(); j++) { + std::cout << " {"; + for(int k = 0; k < tmp[j].size(); k++) { + std::cout << tmp[j][k].page() << ":" << tmp[j][k].offset() << " "; + } + std::cout << "}"; + } + std::cout << std::endl; + } + // std::cout << "}"; } - std::cout << std::endl; - } - // std::cout << "}"; - } - // vector are modified - std::vector<Address> lru_cache_sim(std::vector<Address> rmb, std::vector<Address> lmb, int nb_way) { - std::vector<Address> ucb; - for(int i = 0; i < lmb.size(); i++) { - // check if a hit ? - bool hit = false; - for(int j = 0; j < rmb.size(); j++) { - if(rmb[j] == lmb[i]) { - hit = true; - // remove block from the cache to add it at the back - rmb.erase(rmb.begin() + j); - rmb.push_back(lmb[i]); - break; - } - } - // add block to ucb if hit - if(hit) { - ucb.push_back(lmb[i]); - } else { - rmb.push_back(lmb[i]); - if(rmb.size() > nb_way) { - rmb.erase(rmb.begin()); - } + // vector are modified + std::vector<Address> lru_cache_sim(std::vector<Address> rmb, std::vector<Address> lmb, int nb_way) { + std::vector<Address> ucb; + for(int i = 0; i < lmb.size(); i++) { + // check if a hit ? + bool hit = false; + for(int j = 0; j < rmb.size(); j++) { + if(rmb[j] == lmb[i]) { + hit = true; + // remove block from the cache to add it at the back + rmb.erase(rmb.begin() + j); + rmb.push_back(lmb[i]); + break; + } + } + // add block to ucb if hit + if(hit) { + ucb.push_back(lmb[i]); + } else { + rmb.push_back(lmb[i]); + if(rmb.size() > nb_way) { + rmb.erase(rmb.begin()); + } + } + } + return ucb; } - } - return ucb; - } - std::vector<Address> compute_ucb(std::vector<std::vector<Address>> rmb, std::vector<std::vector<Address>> lmb, int nb_way) { - std::vector<Address> ucb; - for(int i = 0; i < rmb.size(); i++) { - for(int j = 0; j < lmb.size(); j++) { - std::vector<Address> tmp_ucb = lru_cache_sim(rmb[i], lmb[j], nb_way); - for(int k = 0; k < tmp_ucb.size(); k++) { - if(find(ucb.begin(), ucb.end(), tmp_ucb[k]) == ucb.end()) { - ucb.push_back(tmp_ucb[k]); - } - } + std::vector<Address> compute_ucb(std::vector<std::vector<Address>> rmb, std::vector<std::vector<Address>> lmb, int nb_way) { + std::vector<Address> ucb; + for(int i = 0; i < rmb.size(); i++) { + for(int j = 0; j < lmb.size(); j++) { + std::vector<Address> tmp_ucb = lru_cache_sim(rmb[i], lmb[j], nb_way); + for(int k = 0; k < tmp_ucb.size(); k++) { + if(find(ucb.begin(), ucb.end(), tmp_ucb[k]) == ucb.end()) { + ucb.push_back(tmp_ucb[k]); + } + } + } + } + return ucb; } - } - return ucb; - } - unsigned long compute_total_iteration(Block *b) { - // if the loop header exist return the nb of iteration - Block *bh = Loop::of(b)->header(); - if(bh->isBasic()) { - return TOTAL_ITERATION(bh->toBasic()->first()); - } + unsigned long compute_total_iteration(Block *b) { + // if the loop header exist return the nb of iteration + Block *bh = Loop::of(b)->header(); + if(bh->isBasic()) { + return TOTAL_ITERATION(bh->toBasic()->first()); + } - // if the CFG is the main function - if(b->cfg()->callers().count() == 0) { - return 1; - } + // if the CFG is the main function + if(b->cfg()->callers().count() == 0) { + return 1; + } - // if the CFG is a function then we sum the nb of iteration from all of synth block that call it - unsigned int total = 0; - for(int i = 0; i < b->cfg()->callers().count(); i++) { - total += compute_total_iteration(b->cfg()->callers()[i]); - } - return total; - } + // if the CFG is a function then we sum the nb of iteration from all of synth block that call it + unsigned int total = 0; + for(int i = 0; i < b->cfg()->callers().count(); i++) { + total += compute_total_iteration(b->cfg()->callers()[i]); + } + return total; + } - unsigned long compute_vul_block_out(BasicBlock *bb, std::vector<Address> ucb_out, const otawa::hard::Cache* cache, std::vector<unsigned long> lblock_time_array) { - - AllocArray<LBlock *> *lblock_array = BB_LBLOCKS(bb); - double vul = 0; - for(int i = 0; i < ucb_out.size(); i++) { - bool found = false; - for (int j = 0; j < lblock_array->count(); j++) { - LBlock *lb = (*lblock_array)[j]; - if(found) { - vul += lblock_time_array[j]; - } - if(cache->round(lb->address()) == ucb_out[i]) { - found = true; - } - } - } + unsigned long compute_vul_block_out(BasicBlock *bb, std::vector<Address> ucb_out, const otawa::hard::Cache* cache, std::vector<unsigned long> lblock_time_array) { - return vul * cache->blockSize(); - } + AllocArray<LBlock *> *lblock_array = BB_LBLOCKS(bb); + double vul = 0; + for(int i = 0; i < ucb_out.size(); i++) { + bool found = false; + for (int j = 0; j < lblock_array->count(); j++) { + LBlock *lb = (*lblock_array)[j]; + if(found) { + vul += lblock_time_array[j]; + } + if(cache->round(lb->address()) == ucb_out[i]) { + found = true; + } + } + } - unsigned long compute_vul_block_in(BasicBlock *bb, std::vector<Address> ucb_in, const otawa::hard::Cache* cache, std::vector<unsigned long> lblock_time_array) { - - AllocArray<LBlock *> *lblock_array = BB_LBLOCKS(bb); - double vul = 0; - for(int i = 0; i < ucb_in.size(); i++) { - for (int j = 0; j < lblock_array->count(); j++) { - LBlock *lb = (*lblock_array)[j]; - if(cache->round(lb->address()) == ucb_in[i]) { - break; - } - vul += lblock_time_array[j]; + return vul * cache->blockSize(); } - } - return vul * cache->blockSize(); - } + unsigned long compute_vul_block_in(BasicBlock *bb, std::vector<Address> ucb_in, const otawa::hard::Cache* cache, std::vector<unsigned long> lblock_time_array) { + + AllocArray<LBlock *> *lblock_array = BB_LBLOCKS(bb); + double vul = 0; + for(int i = 0; i < ucb_in.size(); i++) { + for (int j = 0; j < lblock_array->count(); j++) { + LBlock *lb = (*lblock_array)[j]; + if(cache->round(lb->address()) == ucb_in[i]) { + break; + } + vul += lblock_time_array[j]; + } + } + + return vul * cache->blockSize(); + } - unsigned long compute_vul_block(BasicBlock *bb, std::vector<Address> ucb_in, std::vector<Address> ucb_out, const otawa::hard::Cache* cache, ilp::System* sys) { + unsigned long compute_vul_block(BasicBlock *bb, std::vector<Address> ucb_in, std::vector<Address> ucb_out, const otawa::hard::Cache* cache, ilp::System* sys) { - // Compute average instruction time + // Compute average instruction time - unsigned long bb_time = ipet::TIME(bb); - unsigned long instr_time = ceil(bb_time / bb->count()); + unsigned long bb_time = ipet::TIME(bb); + unsigned long instr_time = ceil(bb_time / bb->count()); - // --- compute vulnerability during execution --- + // --- compute vulnerability during execution --- - unsigned long vul = 0; - auto iter = bb->begin(); - AllocArray<LBlock *> *lblock_array = BB_LBLOCKS(bb); - std::vector<unsigned long> lblock_time_array; - for (int i = 0; i < lblock_array->count(); i++) { - LBlock *lb = (*lblock_array)[i]; - unsigned long time_lblock = 0; - for(int j = 0; j < lb->countInsts(); j++) { - time_lblock += instr_time; - iter++; - } - lblock_time_array.push_back(time_lblock); - vul += time_lblock * lb->size(); - } + unsigned long vul = 0; + auto iter = bb->begin(); + AllocArray<LBlock *> *lblock_array = BB_LBLOCKS(bb); + std::vector<unsigned long> lblock_time_array; + for (int i = 0; i < lblock_array->count(); i++) { + LBlock *lb = (*lblock_array)[i]; + unsigned long time_lblock = 0; + for(int j = 0; j < lb->countInsts(); j++) { + time_lblock += instr_time; + iter++; + } + lblock_time_array.push_back(time_lblock); + vul += time_lblock * lb->size(); + } - // compute vulnerability ucb_in bb - vul += compute_vul_block_in(bb, ucb_in, cache, lblock_time_array); - //compute vulnerability ucb_out bb - vul += compute_vul_block_out(bb, ucb_out, cache, lblock_time_array); - - unsigned long head_iteration = 0; - if(Loop::isHeader(bb)) { - head_iteration = 1; - } - vul *= WEIGHT(bb) + head_iteration; + // compute vulnerability ucb_in bb + vul += compute_vul_block_in(bb, ucb_in, cache, lblock_time_array); + //compute vulnerability ucb_out bb + vul += compute_vul_block_out(bb, ucb_out, cache, lblock_time_array); + + unsigned long head_iteration = 0; + if(Loop::isHeader(bb)) { + head_iteration = 1; + } + vul *= WEIGHT(bb) + head_iteration; - // --- compute vulnerability during miss --- + // --- compute vulnerability during miss --- - std::vector<unsigned long> lblock_miss_time_array; - double miss_cost = 0; - for (int i = 0; i < lblock_array->count(); i++) { - LBlock *lb = (*lblock_array)[i]; - lblock_miss_time_array.push_back(sys->valueOf(MISS_VAR(lb)) * cache->missPenalty()); - } + std::vector<unsigned long> lblock_miss_time_array; + double miss_cost = 0; + for (int i = 0; i < lblock_array->count(); i++) { + LBlock *lb = (*lblock_array)[i]; + lblock_miss_time_array.push_back(sys->valueOf(MISS_VAR(lb)) * cache->missPenalty()); + } - // compute vulnerability ucb_in bb - vul += compute_vul_block_in(bb, ucb_in, cache, lblock_miss_time_array); - //compute vulnerability ucb_out bb - vul += compute_vul_block_out(bb, ucb_out, cache, lblock_miss_time_array); + // compute vulnerability ucb_in bb + vul += compute_vul_block_in(bb, ucb_in, cache, lblock_miss_time_array); + //compute vulnerability ucb_out bb + vul += compute_vul_block_out(bb, ucb_out, cache, lblock_miss_time_array); - return vul; - } + return vul; + } - unsigned long compute_edge_time(Edge *edge, ilp::System* sys) { - unsigned long time_edge = etime::LTS_TIME(edge); + // unsigned long compute_edge_time(Edge *edge, ilp::System* sys) { + // unsigned long time_edge = etime::LTS_TIME(edge); - elm::Pair<long int, otawa::ilp::Var*> p_s = etime::HTS_CONFIG(edge); - if(p_s.snd != NULL) { - time_edge += p_s.fst * sys->valueOf(p_s.snd); - } - return time_edge; - } + // elm::Pair<long int, otawa::ilp::Var*> p_s = etime::HTS_CONFIG(edge); + // if(p_s.snd != NULL) { + // time_edge += p_s.fst * sys->valueOf(p_s.snd); + // } + // return time_edge; + // } - unsigned long compute_edge_between(Block* bb_in, Block* bb_out, ilp::System* sys, bool &found) { - found = false; - - for(Block::EdgeIter iter_suc(bb_in->outs()); iter_suc(); iter_suc++) { - Edge *edge = *iter_suc; + std::pair<unsigned long, unsigned long> compute_edge_time(Edge *edge, ilp::System* sys) + { + std::pair<unsigned long, unsigned long> time_edge; + time_edge.first = etime::LTS_TIME(edge); + time_edge.second = 0; + elm::Pair<long int, otawa::ilp::Var*> p_s = etime::HTS_CONFIG(edge); + if(p_s.snd != NULL) { + time_edge.second += p_s.fst * sys->valueOf(p_s.snd); + } + return time_edge; + } + // //------------------------------------ + // // Function compute_edge_between + // // compute the value of a set of edge between two basic block separates by synth blocks. + // //------------------------------------ + // unsigned long compute_edge_between(Block* bb_in, Block* bb_out, ilp::System* sys, bool &found) { + // found = false; + // // for all edge to a block child of bb_in + // for(Block::EdgeIter iter_suc(bb_in->outs()); iter_suc(); iter_suc++) { + // Edge *edge = *iter_suc; - unsigned long time_edge = compute_edge_time(edge, sys); - if(time_edge < 0) { - time_edge = 0; - } - - Block *target = edge->target(); + // // compute time on edge + // unsigned long time_edge = compute_edge_time(edge, sys); + // if(time_edge < 0) { + // time_edge = 0; + // } - if(target == bb_out) { - found = true; - return time_edge; - } + // Block *target = edge->target(); + // // if the target is corresponding to basic block bb_out + // if(target == bb_out) { + // found = true; + // return time_edge; + // } - if(target->isBasic()) { - return 0; - } + // // if the block is another basic block then wrong way + // if(target->isBasic()) { + // return 0; + // } + + // // If the block si synth we are looking for the next one + // unsigned long tmp_time = compute_edge_between(target, bb_out, sys, found); + // if(found) { + // return tmp_time + time_edge; + // } - unsigned long tmp_time = compute_edge_between(target, bb_out, sys, found); - if(found) { - return tmp_time + time_edge; - } + // } + + // return 0; + // } + + //------------------------------------ + // Function compute_edge_between + // compute the value of a set of edge between two basic block separates by synth blocks. + // first BB time and second edge additional value + //------------------------------------ + // std::pair<unsigned long, unsigned long> compute_edge_between(Block* bb_in, Block* bb_out, ilp::System* sys, bool &found) + // { + // found = false; + // // for all edge to a block child of bb_in + // for(Block::EdgeIter iter_suc(bb_in->outs()); iter_suc(); iter_suc++) { + // Edge *edge = *iter_suc; + + // // compute time on edge + // std::pair<unsigned long, unsigned long> time_edge = compute_edge_time(edge, sys); + // if(time_edge.first < 0) { + // time_edge.first = 0; + // } + // if(time_edge.second < 0) { + // time_edge.second = 0; + // } - } + // Block *target = edge->target(); + // // if the target is corresponding to basic block bb_out + // if(target == bb_out) { + // found = true; + // return time_edge; + // } - return 0; - } + // // if the block is another basic block then wrong way + // if(target->isBasic()) { + // std::pair<unsigned long, unsigned long> tmp_return; + // tmp_return.first = 0; + // tmp_return.second = 0; + // return tmp_return; + // } + + // // If the block si synth we are looking for the next one + // std::pair<unsigned long, unsigned long> tmp_time = compute_edge_between(target, bb_out, sys, found); + // if(found) { + // std::pair<unsigned long, unsigned long> tmp_return; + // tmp_return.first = tmp_time.first + time_edge.first; + // tmp_return.second = tmp_time.second + time_edge.second; + // return tmp_return; + // } + + // } + // std::pair<unsigned long, unsigned long> tmp_return; + // tmp_return.first = 0; + // tmp_return.second = 0; + // return tmp_return; + // } - unsigned long compute_vul_edge(BasicBlock* bb_in, BasicBlock* bb_out, std::vector<Address> ucb_in, std::vector<Address> ucb_out, const otawa::hard::Cache* cache, ilp::System* sys) { - bool found = false; - unsigned long vul_edge = compute_edge_between((Block*)bb_in, (Block*)bb_out, sys, found); + // unsigned long compute_vul_edge(BasicBlock* bb_in, BasicBlock* bb_out, std::vector<Address> ucb_in, std::vector<Address> ucb_out, const otawa::hard::Cache* cache, ilp::System* sys) { + // bool found = false; + // unsigned long vul_edge = compute_edge_between((Block*)bb_in, (Block*)bb_out, sys, found); - vul_edge *= std::min(ucb_in.size(), ucb_out.size()) * cache->blockSize(); - return vul_edge; + // vul_edge *= std::min(ucb_in.size(), ucb_out.size()) * cache->blockSize(); + // return vul_edge; - } - // long compute_vul_block(BasicBlock *bb, std::vector<Address> ucb_in, std::vector<Address> ucb_out, const otawa::hard::Cache* cache) { - - // long vul = 0; - - // // get LBlocks from bb - // AllocArray<LBlock *> *lblock_array = BB_LBLOCKS(bb); - // for (int i = 0; i < lblock_array->count(); i++) { - // LBlock *lb = (*lblock_array)[i]; - // otawa::Address lb_id = cache->round(lb->address()); - // // for all the lb not in ucb in and out - // if(find(ucb_out.begin(), ucb_out.end(), lb_id) == ucb_out.end() && - // find(ucb_in.begin(), ucb_in.end(), lb_id) == ucb_in.end()) { - // vul += (LBLOCK_TIME(lb) * lb->size()); - // category_t status = cache::CATEGORY(lb); - // if(status != ALWAYS_MISS) { - // std::cout << "Strange category, classed as always miss by may analysis and hit by otawa analysis" << std::endl; - // vul += cache->missPenalty() * WEIGHT(bb); - // } else { + // } + + // long compute_vul_block(BasicBlock *bb, std::vector<Address> ucb_in, std::vector<Address> ucb_out, const otawa::hard::Cache* cache) { + + // long vul = 0; + + // // get LBlocks from bb + // AllocArray<LBlock *> *lblock_array = BB_LBLOCKS(bb); + // for (int i = 0; i < lblock_array->count(); i++) { + // LBlock *lb = (*lblock_array)[i]; + // otawa::Address lb_id = cache->round(lb->address()); + // // for all the lb not in ucb in and out + // if(find(ucb_out.begin(), ucb_out.end(), lb_id) == ucb_out.end() && + // find(ucb_in.begin(), ucb_in.end(), lb_id) == ucb_in.end()) { + // vul += (LBLOCK_TIME(lb) * lb->size()); + // category_t status = cache::CATEGORY(lb); + // if(status != ALWAYS_MISS) { + // std::cout << "Strange category, classed as always miss by may analysis and hit by otawa analysis" << std::endl; + // vul += cache->missPenalty() * WEIGHT(bb); + // } else { - // } - // } - // } + // } + // } + // } - // for(int i = 0; i < ucb_in.size(); i++) { - // // In UCB IN only? - // if(find(ucb_out.begin(), ucb_out.end(), ucb_in[i]) == ucb_out.end()) { - // bool found = false; - // // for each lblocks - // for (int j = 0; j < lblock_array->count(); j++) { - // LBlock *lb = (*lblock_array)[j]; - // // we consider as vulnerable during lblock execution if we have not found yet the cache block - // if(!found) { - // vul += (LBLOCK_TIME(lb) * cache->blockSize()); - // category_t status = cache::CATEGORY(lb); - // if(status != ALWAYS_MISS) { - // vul += cache->missPenalty() * WEIGHT(bb); - // } - // } - // otawa::Address lb_id = cache->round(lb->address()); - // if(lb_id == ucb_in[i]) { - // found = true; - // } - // } - // } else { - // // In UCB IN and UCB out? - // vul += (ipet::TIME(bb) * cache->blockSize()); - // category_t status = cache::CATEGORY(lb); - // if(status != ALWAYS_MISS) { - // vul += cache->missPenalty() * WEIGHT(bb); - // } - // } - // } + // for(int i = 0; i < ucb_in.size(); i++) { + // // In UCB IN only? + // if(find(ucb_out.begin(), ucb_out.end(), ucb_in[i]) == ucb_out.end()) { + // bool found = false; + // // for each lblocks + // for (int j = 0; j < lblock_array->count(); j++) { + // LBlock *lb = (*lblock_array)[j]; + // // we consider as vulnerable during lblock execution if we have not found yet the cache block + // if(!found) { + // vul += (LBLOCK_TIME(lb) * cache->blockSize()); + // category_t status = cache::CATEGORY(lb); + // if(status != ALWAYS_MISS) { + // vul += cache->missPenalty() * WEIGHT(bb); + // } + // } + // otawa::Address lb_id = cache->round(lb->address()); + // if(lb_id == ucb_in[i]) { + // found = true; + // } + // } + // } else { + // // In UCB IN and UCB out? + // vul += (ipet::TIME(bb) * cache->blockSize()); + // category_t status = cache::CATEGORY(lb); + // if(status != ALWAYS_MISS) { + // vul += cache->missPenalty() * WEIGHT(bb); + // } + // } + // } - // // In UCB OUT only? - // // For each UCB only in UCB out - // for(int i = 0; i < ucb_out.size(); i++) { - // if(find(ucb_in.begin(), ucb_in.end(), ucb_out[i]) == ucb_in.end()) { - // bool found = false; - // // for each lblocks - // for (int j = 0; j < lblock_array->count(); j++) { - // LBlock *lb = (*lblock_array)[j]; - // otawa::Address lb_id = cache->round(lb->address()); - // if(lb_id == ucb_out[i]) { - // found = true; - // } - // // we consider as vulnerable during lblock execution if we have found the cache block - // if(found) { - // vul += (LBLOCK_TIME(lb) * cache->blockSize()); - // category_t status = cache::CATEGORY(lb); - // if(status != ALWAYS_MISS) { - // vul += cache->missPenalty() * WEIGHT(bb); - // } - // } - // } + // // In UCB OUT only? + // // For each UCB only in UCB out + // for(int i = 0; i < ucb_out.size(); i++) { + // if(find(ucb_in.begin(), ucb_in.end(), ucb_out[i]) == ucb_in.end()) { + // bool found = false; + // // for each lblocks + // for (int j = 0; j < lblock_array->count(); j++) { + // LBlock *lb = (*lblock_array)[j]; + // otawa::Address lb_id = cache->round(lb->address()); + // if(lb_id == ucb_out[i]) { + // found = true; + // } + // // we consider as vulnerable during lblock execution if we have found the cache block + // if(found) { + // vul += (LBLOCK_TIME(lb) * cache->blockSize()); + // category_t status = cache::CATEGORY(lb); + // if(status != ALWAYS_MISS) { + // vul += cache->missPenalty() * WEIGHT(bb); + // } + // } + // } - // } - // } + // } + // } - // vul *= compute_total_iteration(bb); - // return vul; - // } + // vul *= compute_total_iteration(bb); + // return vul; + // } + + + //------------------------------------------------------------- + //OLD Initialize RMB LMB plugin + //------------------------------------------------------------- + + bool not_present_in_vect(std::vector<Block *> visited, Block *b) + { + for (int i = 0; i < visited.size(); i++) + { + if (visited[i] == b) + { + return false; + } + } + return true; + } + + int get_exit_id_of_cfg(CFG *cfg) + { + for (CFG::BlockIter block_iter = cfg->blocks(); block_iter(); block_iter++) + { + Block *b = *block_iter; + bool found = true; + for ( + Block::EdgeIter iter_suc(b->outs()); + iter_suc(); + iter_suc++) + { + found = false; + break; + } + if (found) + { + return b->id(); + } + } + return -1; + } + + std::vector<Block *> get_last_blocks(CFG *cfg) + { + std::vector<Block *> tmp_v; + int id_last = get_exit_id_of_cfg(cfg); + if (id_last == -1) + { + return tmp_v; + } + for (CFG::BlockIter block_iter = cfg->blocks(); block_iter(); block_iter++) + { + Block *b = *block_iter; + + for ( + Block::EdgeIter iter_suc(b->outs()); + iter_suc(); + iter_suc++) + { + Edge *edge = *iter_suc; + Block *target = edge->target(); + if (target->id() == id_last) + { + tmp_v.push_back(b); + break; + } + } + } + return tmp_v; + } + + + void mark_first_bb(Block *b_fct_entry, struct Memory_block *mb, std::vector<Block *> visited) + { + visited.push_back(b_fct_entry); + if (b_fct_entry->isBasic()) + { + struct Memory_block *mb_suc = MB_STRUCT(b_fct_entry); + mb->suc.push_back(mb_suc); + mb_suc->pred.push_back(mb); + } + else + { + + if (b_fct_entry->isSynth()) + { + std::vector<Block *> v_tmp; + mark_first_bb(b_fct_entry->toSynth()->callee()->entry(), mb, v_tmp); + } + else + { + + for (Block::EdgeIter iter_suc(b_fct_entry->outs()); + iter_suc(); + iter_suc++) + { + + Edge *edge = *iter_suc; + Block *target = edge->target(); + if (not_present_in_vect(visited, target)) + { + mark_first_bb(target, mb, visited); + } + } + } + } + } + + void mark_last_bb_bis(Block *b_fct_exit, struct Memory_block *mb, std::vector<Block *> visited) + { + visited.push_back(b_fct_exit); + //std::cout << "Block: " << b_fct_exit->id() << std::endl; + if (b_fct_exit->isBasic()) + { + struct Memory_block *mb_pred = MB_STRUCT(b_fct_exit); + //std::cout << "----------------------------- FOUND pred" << std::endl; + mb_pred->suc.push_back(mb); + mb->pred.push_back(mb_pred); + } + else + { + if (b_fct_exit->isSynth()) + { + //std::cout << "is synth" << std::endl; + std::vector<Block *> v_tmp; + mark_last_bb_bis(b_fct_exit->toSynth()->callee()->exit(), mb, v_tmp); + } + else + { + + for (Block::EdgeIter iter_pred(b_fct_exit->ins()); + iter_pred(); + iter_pred++) + { + //std::cout << "here" << std::endl; + Edge *edge = *iter_pred; + Block *target = edge->source(); + //std::cout << "Block: " << target->id() << std::endl; + if (not_present_in_vect(visited, target)) + { + //std::cout << "not present" << std::endl; + mark_last_bb_bis(target, mb, visited); + } + else + { + //std::cout << "present in list" << std::endl; + } + } + } + } + } + + void mark_last_bb(Block *b_fct_exit, Block *main_suc, std::vector<Block *> visited) + { + visited.push_back(main_suc); + if (main_suc->isBasic()) + { + struct Memory_block *mb = MB_STRUCT(main_suc); + std::vector<Block *> v_tmp; + //std::cout << "----------------------------- FOUND suc" << std::endl; + mark_last_bb_bis(b_fct_exit, mb, v_tmp); + } + else + { + if (main_suc->isSynth()) + { + std::vector<Block *> v_tmp; + mark_last_bb(b_fct_exit, main_suc->toSynth()->callee()->entry(), v_tmp); + } + else + { + + for (Block::EdgeIter iter_suc(main_suc->outs()); + iter_suc(); + iter_suc++) + { + Edge *edge = *iter_suc; + Block *target = edge->target(); + if (not_present_in_vect(visited, target)) + { + + mark_last_bb(b_fct_exit, target, visited); + } + } + } + } + } + + void add_links(Block *b, struct Memory_block *mb, std::vector<Block *> visited) + { + visited.push_back(b); + + if (b->isBasic()) + { + BasicBlock *bb = b->toBasic(); + struct Memory_block *mb_suc = MB_STRUCT(b); + mb->suc.push_back(mb_suc); + mb_suc->pred.push_back(mb); + } + else + { + if (b->isSynth()) + { + SynthBlock *sb = b->toSynth(); + CFG *cfg_fct = sb->callee(); + + Block *b_fct_entry = cfg_fct->entry(); + //Block *b_fct_exit = cfg_fct->exit(); + std::vector<Block *> exits = get_last_blocks(cfg_fct); + std::vector<Block *> v_tmp; + mark_first_bb(b_fct_entry, mb, v_tmp); + + for (Block::EdgeIter iter_suc(b->outs()); + iter_suc(); + iter_suc++) + { + Edge *edge = *iter_suc; + Block *target = edge->target(); + std::vector<Block *> v_tmp_bis; + for (int i = 0; i < exits.size(); i++) + { + mark_last_bb(exits[i], target, v_tmp_bis); + } + } + } + else + { + + for (Block::EdgeIter iter_suc(b->outs()); + iter_suc(); + iter_suc++) + { + Edge *edge = *iter_suc; + Block *target = edge->target(); + if (not_present_in_vect(visited, target)) + { + add_links(target, mb, visited); + } + } + } + } + } + + //---------------------------------------------------------------- + + // TRUE LRU + + std::vector<Address> add_LRU(std::vector<Address> cache, Address elem, int nb_way) { + + // if elem already in cache + bool is_present = false; + for(int i = 0; i < cache.size(); i++) { + if(cache[i] == elem) { + cache.erase(cache.begin() + i); + break; + } + } + + cache.push_back(elem); + while(cache.size() > nb_way) { + cache.erase(cache.begin()); + } + + return cache; + - void VulnerabilityProcessor::processWorkSpace(WorkSpace *ws) { - const CFGCollection *coll = INVOLVED_CFGS(ws); - const otawa::hard::CacheConfiguration *cf = otawa::hard::CACHE_CONFIGURATION_FEATURE.get(ws); - const otawa::hard::Cache* cache = cf->instCache(); + } - int nb_index = cache->rowCount(); - int nb_way = cache->wayCount(); + std::vector<Address> add_LRU_bis(std::vector<Address> cache, Address elem, int nb_way) { - unsigned long vul = 0; + // if elem already in cache + bool is_present = false; + for(int i = 0; i < cache.size(); i++) { + if(cache[i] == elem) { + cache.erase(cache.begin() + i); + break; + } + } - ilp::System* sys = otawa::ipet::SYSTEM(ws); + cache.insert(cache.begin(), elem); + while(cache.size() > nb_way) { + cache.pop_back(); + } - for(CFGCollection::Iter cfg_iter(*coll); cfg_iter(); cfg_iter++) { - for(CFG::BlockIter block_iter = cfg_iter->blocks(); block_iter(); block_iter++) { - if(block_iter->isBasic()) { - BasicBlock *bb = block_iter->toBasic(); - struct Memory_block *mb = MB_STRUCT(bb); + return cache; + } + + std::vector<Address> rmb_LRU(std::vector<Address> gen, std::vector<Address> rmb, int nb_way) + { + for(int i = 0; i < gen.size(); i++) { + rmb = add_LRU(rmb, gen[i], nb_way); + } + return rmb; + } - std::vector<Address> ucb_in = compute_ucb(*(mb->rmb_in), *(mb->lmb_in), nb_way); - std::vector<Address> ucb_out = compute_ucb(*(mb->rmb_out), *(mb->lmb_out), nb_way); + std::vector<Address> lmb_LRU(std::vector<Address> gen, std::vector<Address> lmb, int nb_way) + { - unsigned long vul_tmp = compute_vul_block(bb, ucb_in, ucb_out, cache, sys); - vul += vul_tmp; - } + for(int i = (gen.size()-1); i >= 0; i--) { + lmb = add_LRU_bis(lmb, gen[i], nb_way); + } + return lmb; } - } + + void init_gen(BasicBlock *bb, int nb_index, int nb_way, const otawa::hard::Cache *cache) { + Memory_block *mb = MB_STRUCT(bb); + std::vector<Address> vect[nb_index]; + AllocArray<LBlock *> *lblock_array = BB_LBLOCKS(bb); - for(CFGCollection::Iter cfg_iter(*coll); cfg_iter(); cfg_iter++) { - for(CFG::BlockIter block_iter = cfg_iter->blocks(); block_iter(); block_iter++) { - if(block_iter->isBasic()) { - BasicBlock *bb = block_iter->toBasic(); - + for (int i = 0; i < lblock_array->count(); i++) { + LBlock *lb = (*lblock_array)[i]; + otawa::Address lb_id = cache->round(lb->address()); + vect[cache->line(lb->address())].push_back(lb_id); + } + + for (int index_tmp = 0; index_tmp < nb_index; index_tmp++) { + for (int i = 0; i < nb_way; i++) { + if (i < vect[index_tmp].size()) { + mb->lmb_gen[index_tmp].push_back(vect[index_tmp][i]); + } + int j = vect[index_tmp].size() - 1 - i; + if (j >= 0) { + mb->rmb_gen[index_tmp].insert(mb->rmb_gen[index_tmp].begin(), vect[index_tmp][j]); + } + } + + if(mb->lmb_gen[index_tmp].size() != 0) + mb->lmb_in[index_tmp].push_back(mb->lmb_gen[index_tmp]); + + if(mb->rmb_gen[index_tmp].size() != 0) + mb->rmb_out[index_tmp].push_back(mb->rmb_gen[index_tmp]); + } + } + + + //------------------------------------------------------------- + // RMB LMB + //------------------------------------------------------------- + + + void create_structure(const CFGCollection *coll, int nb_index, int nb_way) { + for (CFGCollection::Iter cfg_iter(*coll); cfg_iter(); cfg_iter++) + { + for (CFG::BlockIter block_iter = cfg_iter->blocks(); block_iter(); block_iter++) + { + if (block_iter->isBasic()) + { + BasicBlock *bb = block_iter->toBasic(); + MB_STRUCT(bb) = new Memory_block(nb_index, nb_way, bb); + } + } + } + + } + + void link_structure(const CFGCollection *coll, int nb_way, int nb_index) { + for (CFGCollection::Iter cfg_iter(*coll); cfg_iter(); cfg_iter++) + { + for (CFG::BlockIter block_iter = cfg_iter->blocks(); block_iter(); block_iter++) + { + if (block_iter->isBasic()) + { + BasicBlock *bb = block_iter->toBasic(); + + Memory_block *mb = MB_STRUCT(bb); + mb->block_id = bb->id(); + for ( + Block::EdgeIter iter_suc(bb->outs()); + iter_suc(); + iter_suc++) + { + + Edge *edge = *iter_suc; + Block *target = edge->target(); + std::vector<Block *> visited; + add_links(target, mb, visited); + } + } + } + } + + } + + void initialize_structure(const CFGCollection *coll, int nb_way, int nb_index, const hard::Cache *cache) { + for (CFGCollection::Iter cfg_iter(*coll); cfg_iter(); cfg_iter++) + { + for (CFG::BlockIter block_iter = cfg_iter->blocks(); block_iter(); block_iter++) + { + if (block_iter->isBasic()) + { + BasicBlock *bb = block_iter->toBasic(); + Memory_block *mb = MB_STRUCT(bb); + + + init_gen(bb, nb_index, nb_way, cache); + } + } + } + } + + void compute_rmb(const CFGCollection *coll, int nb_way, int nb_index) { + bool change = true; + while(change) { + + change = false; + + for(CFGCollection::Iter cfg_iter(*coll); cfg_iter(); cfg_iter++) { + for(CFG::BlockIter block_iter = cfg_iter->blocks(); block_iter(); block_iter++) { + + // ----- for each BB ----- + if(block_iter->isBasic()) { + BasicBlock *bb = block_iter->toBasic(); + Memory_block *mb = MB_STRUCT(bb); + + // ----- for each row ----- + for (int index = 0; index < nb_index; index++) { + + // RMB IN + mb->rmb_in[index].clear(); + for (int pred_mb = 0; pred_mb < mb->pred.size(); pred_mb++) { + mb->rmb_in[index] = + get_set(vector_union(mb->rmb_in[index], + mb->pred[pred_mb]->rmb_out[index])); + } + + // RMB OUT + std::vector<std::vector<Address>> oldout(mb->rmb_out[index]); + mb->rmb_out[index].clear(); + + std::vector<std::vector<Address>> rmb_in = mb->rmb_in[index]; + if(rmb_in.size() == 0) { + // TODO: Need to modify this part to take into account empty gen + //if(mb->rmb_gen[index].size() != 0) { + mb->rmb_out[index].push_back(mb->rmb_gen[index]); + //} + } else { + for (int tmp_rmb = 0; tmp_rmb < rmb_in.size(); tmp_rmb++) { + std::vector<Address> tmp_vect = mb->rmb_gen[index]; + rmb_in[tmp_rmb] = get_set(rmb_LRU(tmp_vect, rmb_in[tmp_rmb], nb_way)); + mb->rmb_out[index].push_back(rmb_in[tmp_rmb]); + } + } + + mb->rmb_out[index] = get_set(mb->rmb_out[index]); + + // UPDATE END CONDITION + if (oldout != mb->rmb_out[index]) { + change = true; + } + + } + } + } + } + } + } + + void compute_lmb(const CFGCollection *coll, int nb_way, int nb_index) { + bool change = true; + while (change) { + + change = false; + + for (CFGCollection::Iter cfg_iter(*coll); cfg_iter(); cfg_iter++) { + for (CFG::BlockIter block_iter = cfg_iter->blocks(); block_iter(); block_iter++) { + + // ----- for each BB ----- + if (block_iter->isBasic()) { + BasicBlock *bb = block_iter->toBasic(); + Memory_block *mb = MB_STRUCT(bb); + + // ----- for each row ----- + + for (int index = 0; index < nb_index; index++) { + + // LMB OUT + mb->lmb_out[index].clear(); + for (int suc_mb = 0; suc_mb < mb->suc.size(); suc_mb++) { + mb->lmb_out[index] = + get_set(vector_union(mb->lmb_out[index], + mb->suc[suc_mb]->lmb_in[index])); + } + + // LMB IN + std::vector<std::vector<Address>> oldout(mb->lmb_in[index]); + mb->lmb_in[index].clear(); + + std::vector<std::vector<Address>> lmb_out = get_set(mb->lmb_out[index]); + if(lmb_out.size() == 0) { + // TODO: Need to modify this part to take into account empty gen + //if(mb->lmb_gen[index].size() != 0) { + mb->lmb_in[index].push_back(mb->lmb_gen[index]); + //} + } else { + for (int tmp_lmb = 0; tmp_lmb < lmb_out.size(); tmp_lmb++) { + std::vector<Address> tmp_vect = mb->lmb_gen[index]; + lmb_out[tmp_lmb] = get_set(lmb_LRU(tmp_vect, lmb_out[tmp_lmb], nb_way)); + mb->lmb_in[index].push_back(lmb_out[tmp_lmb]); + } + } + + mb->lmb_in[index] = get_set(mb->lmb_in[index]); + + // UPDATE END CONDITION + if (oldout != mb->lmb_in[index]) { + change = true; + } + } + } + } + } + } + + } + + void start_rmb_lmb_computation(WorkSpace *ws) + { + + const CFGCollection *coll = INVOLVED_CFGS(ws); + + const otawa::hard::CacheConfiguration *cf = otawa::hard::CACHE_CONFIGURATION_FEATURE.get(ws); + const otawa::hard::Cache* cache = cf->instCache(); + + int nb_index = cache->rowCount(); + int nb_way = cache->wayCount(); + + // create structures + create_structure(coll, nb_index, nb_way); + + // links structures + link_structure(coll, nb_way, nb_index); + + // Initialize all structures + initialize_structure(coll, nb_way, nb_index, cache); + + // RMB + + compute_rmb(coll, nb_way, nb_index); + + // LMB + + compute_lmb(coll, nb_way, nb_index); + + for (CFGCollection::Iter cfg_iter(*coll); cfg_iter(); cfg_iter++) { + for (CFG::BlockIter block_iter = cfg_iter->blocks(); block_iter(); block_iter++) { + if (block_iter->isBasic()) { + + BasicBlock *bb = block_iter->toBasic(); + Memory_block *mb = MB_STRUCT(bb); + } + } + } + + } + + //------------------------------------------------------------- + // Vulnerability + //------------------------------------------------------------- + + + long data_vulnerable(LBlock *lb, const otawa::hard::Cache* cache) { + BasicBlock* bb = lb->bb(); struct Memory_block *mb = MB_STRUCT(bb); + std::vector<Address> ucb_out = compute_ucb(*(mb->rmb_out), *(mb->lmb_out), cache->wayCount()); + otawa::Address lb_id = cache->round(lb->address()); + for(int i = 0; i < ucb_out.size(); i++) { + if(ucb_out[i] == lb_id) { + return lb->size(); + } + } + return cache->blockSize(); + } + + + long data_vulnerability_on_path_ex(otawa::Address cb, Block *b, const otawa::hard::Cache* cache, std::vector<Block*> current_path, ilp::System* sys) { + struct Memory_block *mb = MB_STRUCT(b); + std::vector<Address> ucb_out = compute_ucb(*(mb->rmb_out), *(mb->lmb_out), cache->wayCount()); + std::vector<Address> ucb_in = compute_ucb(*(mb->rmb_in), *(mb->lmb_in), cache->wayCount()); + bool is_present = false; + // If not present in exit ucb of the block + for(int i = 0; i < ucb_out.size(); i++) { + if(ucb_out[i] == cb) { + is_present = true; + } + } + if(!is_present) { + return -1; + } + + // If no present in the entry ucb of the block (call during the block) + is_present = false; + // If not present in exit ucb of the block + for(int i = 0; i < ucb_in.size(); i++) { + if(ucb_in[i] == cb) { + is_present = true; + } + } + if(!is_present) { + return 0; + } - std::vector<Address> ucb_in = compute_ucb(*(mb->rmb_out), *(mb->lmb_out), nb_way); + // Explore different paths - for(int i = 0; i < mb->suc.size(); i++) { - struct Memory_block *mb_suc = MB_STRUCT(bb); - std::vector<Address> ucb_out = compute_ucb(*(mb_suc->rmb_in), *(mb_suc->lmb_in), nb_way); - unsigned long vul_tmp = compute_vul_edge(bb, mb_suc->bb_ptr, ucb_in, ucb_out, cache, sys); - vul += vul_tmp; + current_path.push_back(b); + unsigned long iteration = compute_total_iteration(b); + long longuest_path = 0; + for(Block::EdgeIter iter_pred(b->ins()); iter_pred(); iter_pred++) { + Edge *edge = *iter_pred; + Block *source = edge->source(); + if(find(current_path.begin(), current_path.end(), source) == current_path.end()) { + long tmp = data_vulnerability_on_path_ex(cb, source, cache, current_path, sys); + if(tmp != -1) { + elm::Pair<long int, otawa::ilp::Var*> p = etime:: HTS_CONFIG(edge); + tmp += p.fst * sys->valueOf(p.snd); + tmp += iteration * etime::LTS_TIME(edge); + longuest_path = max(longuest_path, tmp); + + } + } + } + return longuest_path; + } + + long data_vulnerability_on_path(LBlock *lb, const otawa::hard::Cache* cache, ilp::System* sys) { + // Look if the cache block of the lblock is present in the Useful Cache Block at the entry of the Basic Block + BasicBlock *bb = lb->bb(); + struct Memory_block *mb = MB_STRUCT(bb); + std::vector<Address> ucb_in = compute_ucb(*(mb->rmb_in), *(mb->lmb_in), cache->wayCount()); + otawa::Address lb_id = cache->round(lb->address()); + bool is_present = false; + for(int i = 0; i < ucb_in.size(); i++) { + if(ucb_in[i] == lb_id) { + is_present = true; + } + } + // If it is not the case then it means that the lblock is not vulnerable on a path. + if(!is_present) { + return 0; + } + // If it is the case we have to list all the path and take the longest. + + // TODO !!! + std::vector<Block*> current_path; + long max_value = 0; + for (Block::EdgeIter iter_pred(bb->ins()); iter_pred(); iter_pred++) { + Edge *edge = *iter_pred; + Block *source = edge->source(); + max_value = max(max_value, data_vulnerability_on_path_ex(cache->round(lb->address()), source, cache, current_path, sys)); } + return max_value; + } + + long maximum_execution_time_bb(BasicBlock *bb, ilp::System* sys) { + long execution_time = 0; + unsigned long iteration = compute_total_iteration(bb); + + for (Block::EdgeIter iter_pred(bb->ins()); iter_pred(); iter_pred++) { + Edge *edge = *iter_pred; + Block *source = edge->source(); + // 3 cases + // - basic block: execution time is on edge before + // - synth block: execution time is on exit fct edge + // - other: 0 + if(source->isBasic()) { + elm::Pair<long int, otawa::ilp::Var*> p = etime:: HTS_CONFIG(edge); + long time_tmp = p.fst * sys->valueOf(p.snd); + time_tmp += iteration * etime::LTS_TIME(edge); + execution_time = max(execution_time, time_tmp); + } else { + if(source->isSynth()) { + SynthBlock* sb = bb->toSynth(); + Block* ex = sb->callee()->exit(); + long time_tmp_ex = 0; + for (Block::EdgeIter iter_pred_ex(ex->ins()); iter_pred_ex(); iter_pred_ex++) { + Edge *edge_ex = *iter_pred_ex; + long tmp = 0; + elm::Pair<long int, otawa::ilp::Var*> p_ex = etime:: HTS_CONFIG(edge_ex); + tmp = p_ex.fst * sys->valueOf(p_ex.snd); + tmp += iteration * etime::LTS_TIME(edge_ex); + time_tmp_ex = max(time_tmp_ex, tmp); + } + execution_time = max(execution_time, time_tmp_ex); + } + } + } + return execution_time; + } + + long data_vulnerability(LBlock *lb, const otawa::hard::Cache* cache, ilp::System* sys) { + long data_size = data_vulnerable(lb, cache); + long v = maximum_execution_time_bb(lb->bb(), sys); + v += data_vulnerability_on_path(lb, cache, sys); + return data_size * v; + } + + + + //------------------------------------------------------------- + // PROCESS WORKSPACE + //------------------------------------------------------------- + + void VulnerabilityProcessor::processWorkSpace(WorkSpace *ws) { + // Initialize RMB LMB + vulnerability::start_rmb_lmb_computation(ws); + + //Get cache configuration + const CFGCollection *coll = INVOLVED_CFGS(ws); + const otawa::hard::CacheConfiguration *cf = otawa::hard::CACHE_CONFIGURATION_FEATURE.get(ws); + const otawa::hard::Cache* cache = cf->instCache(); + + int nb_index = cache->rowCount(); + int nb_way = cache->wayCount(); + + // Initialization of vulnerability cost to 0 + unsigned long vul = 0; + std::vector<Cache_Miss> miss_collection; + ilp::System* sys = otawa::ipet::SYSTEM(ws); + + // For all basic block of any CFG + for(CFGCollection::Iter cfg_iter(*coll); cfg_iter(); cfg_iter++) { + for(CFG::BlockIter block_iter = cfg_iter->blocks(); block_iter(); block_iter++) { + if(block_iter->isBasic()) { + BasicBlock *bb = block_iter->toBasic(); + AllocArray<LBlock *> *lblock_array = BB_LBLOCKS(bb); + for (int i = 0; i < lblock_array->count(); i++) { + LBlock *lb = (*lblock_array)[i]; + vul += data_vulnerability(lb, cache, sys); + } + } + } + } + VUL(ws) = vul; + // // For all basic block of any CFG + // for(CFGCollection::Iter cfg_iter(*coll); cfg_iter(); cfg_iter++) { + // for(CFG::BlockIter block_iter = cfg_iter->blocks(); block_iter(); block_iter++) { + // if(block_iter->isBasic()) { - - } + // BasicBlock *bb = block_iter->toBasic(); + // struct Memory_block *mb = MB_STRUCT(bb); + + // // Get UCB (in and out) sets + // std::vector<Address> ucb_in = compute_ucb(*(mb->rmb_in), *(mb->lmb_in), nb_way); + // std::vector<Address> ucb_out = compute_ucb(*(mb->rmb_out), *(mb->lmb_out), nb_way); + + // // Compute the vulnerability of the basic block with these value + // unsigned long vul_tmp = compute_vul_block(bb, ucb_in, ucb_out, cache, sys); + // vul += vul_tmp; + + // } + // } + // } + + + // // For all basic block of any CFG + // for(CFGCollection::Iter cfg_iter(*coll); cfg_iter(); cfg_iter++) { + // for(CFG::BlockIter block_iter = cfg_iter->blocks(); block_iter(); block_iter++) { + // if(block_iter->isBasic()) { + + // BasicBlock *bb = block_iter->toBasic(); + // struct Memory_block *mb = MB_STRUCT(bb); + + // // Get UCB (in) set + // std::vector<Address> ucb_in = compute_ucb(*(mb->rmb_out), *(mb->lmb_out), nb_way); + + // for(int i = 0; i < mb->suc.size(); i++) { + // struct Memory_block *mb_suc = MB_STRUCT(bb); + // std::vector<Address> ucb_out = compute_ucb(*(mb_suc->rmb_in), *(mb_suc->lmb_in), nb_way); + // unsigned long vul_tmp = compute_vul_edge(bb, mb_suc->bb_ptr, ucb_in, ucb_out, cache, sys); + // vul += vul_tmp; + // } + // } + // } + // } + + // VUL(ws) = vul; } - } - VUL(ws) = vul; - } + // definition propriete + /* + Identifier<DAGHNode*> DAG_HNODE("otawa::vulnerability::DAG_HNODE"); + */ + + Identifier<std::vector<Address>*> UCB_IN("otawa::vulnerability::UCB_IN"); + Identifier<std::vector<Address>*> UCB_OUT("otawa::vulnerability::UCB_OUT"); + Identifier<unsigned long> VUL("otowa::vulnerability::VUL"); - // definition propriete - /* - Identifier<DAGHNode*> DAG_HNODE("otawa::vulnerability::DAG_HNODE"); - */ - Identifier<std::vector<Address>*> UCB_IN("otawa::initialize_RMB_LMB::UCB_IN"); - Identifier<std::vector<Address>*> UCB_OUT("otawa::initialize_RMB_LMB::UCB_OUT"); - Identifier<unsigned long> VUL("otowa::initialize_RMB_LMB::VUL"); - } + //---------------------------------------------------- + // Initialize RMB LMB old plugin + //---------------------------------------------------- + + Identifier<struct Memory_block *> MB_STRUCT("otawa::vulnerability::MB_STRUCT"); + } } diff --git a/vulnerability/vulnerability.so b/vulnerability/vulnerability.so index 3e236d85990519abc3fc056c291818dee61da5ad..8f37dffed3728e82eef436f8c8fb6230f21d0fda 100755 Binary files a/vulnerability/vulnerability.so and b/vulnerability/vulnerability.so differ