From 19892699e2b6df0521b191e2daa7f70fe1c51623 Mon Sep 17 00:00:00 2001 From: "le.truong" <le.truong@telecom-paris.fr> Date: Mon, 23 Nov 2020 00:04:31 +0100 Subject: [PATCH] Fix variable initial condition and add the test for memory leak --- .../src_simulator/app/TMLSelectCommand.cpp | 2 +- simulators/c++2/src_simulator/app/TMLTask.cpp | 9 +- simulators/c++2/src_simulator/app/TMLTask.h | 6 +- simulators/c++2/src_simulator/arch/FPGA.cpp | 1 + .../c++2/src_simulator/sim/SimComponents.cpp | 8 +- .../c++2/src_simulator/sim/Simulator.cpp | 14 +- .../java/tmltranslator/MemoryLeakTest.java | 269 ++++++++++++++++++ 7 files changed, 294 insertions(+), 15 deletions(-) create mode 100644 ttool/src/test/java/tmltranslator/MemoryLeakTest.java diff --git a/simulators/c++2/src_simulator/app/TMLSelectCommand.cpp b/simulators/c++2/src_simulator/app/TMLSelectCommand.cpp index 3914ecaae7..5986246f83 100644 --- a/simulators/c++2/src_simulator/app/TMLSelectCommand.cpp +++ b/simulators/c++2/src_simulator/app/TMLSelectCommand.cpp @@ -44,7 +44,7 @@ Ludovic Apvrille, Renaud Pacalet #include <TMLTransaction.h> #include <Bus.h> -TMLSelectCommand::TMLSelectCommand(ID iID, TMLTask* iTask, TMLEventChannel** iChannel, unsigned int iNumbChannels, const char* iLiveVarList, bool iCheckpoint, ParamFuncPointer* iParamFuncs):TMLCommand(iID, iTask, WAIT_SEND_VLEN, iNumbChannels, iLiveVarList, iCheckpoint), _channel(iChannel), _paramFuncs(iParamFuncs), /*_numbChannels(iNumbChannels),*/ _indexNextCommand(0) { +TMLSelectCommand::TMLSelectCommand(ID iID, TMLTask* iTask, TMLEventChannel** iChannel, unsigned int iNumbChannels, const char* iLiveVarList, bool iCheckpoint, ParamFuncPointer* iParamFuncs):TMLCommand(iID, iTask, WAIT_SEND_VLEN, iNumbChannels, iLiveVarList, iCheckpoint), _channel(iChannel), _paramFuncs(iParamFuncs), /*_numbChannels(iNumbChannels),*/ _indexNextCommand(0), _maxChannelIndex(0) { _type=SEL; } diff --git a/simulators/c++2/src_simulator/app/TMLTask.cpp b/simulators/c++2/src_simulator/app/TMLTask.cpp index a2361081f3..ea645d4084 100755 --- a/simulators/c++2/src_simulator/app/TMLTask.cpp +++ b/simulators/c++2/src_simulator/app/TMLTask.cpp @@ -48,7 +48,7 @@ Ludovic Apvrille, Renaud Pacalet unsigned int TMLTask::_instanceCount=1; -TMLTask::TMLTask(ID iID, Priority iPriority, std::string iName, CPU** iCPU, unsigned int iNoOfCPUs, bool isDaemon): WorkloadSource(iPriority), _ID(iID), _name(iName), _endLastTransaction(0), _currCommand(0), _firstCommand(0), _currentCPU(0), _cpus(iCPU), _noOfCPUs(iNoOfCPUs), _isDaemon(isDaemon), _nextCellIndex(0), _comment(0), _busyCycles(0), _CPUContentionDelay(0), _noCPUTransactions(0), _justStarted(true), _myInstance(_instanceCount), /*_isScheduled(false),*/ _stateHash(0, 30) , _liveVarList(0), _hashInvalidated(true){ +TMLTask::TMLTask(ID iID, Priority iPriority, std::string iName, CPU** iCPU, unsigned int iNoOfCPUs, bool isDaemon): WorkloadSource(iPriority), _ID(iID), _name(iName), _endLastTransaction(0), _currCommand(0), _firstCommand(0), _currentCPU(0), _cpus(iCPU), _noOfCPUs(iNoOfCPUs), _isDaemon(isDaemon), _nextCellIndex(0), _comment(0), _busyCycles(0), _CPUContentionDelay(0), _noCPUTransactions(0), _justStarted(true), _myInstance(_instanceCount), /*_isScheduled(false),*/ _stateHash(0, 30) , _liveVarList(0), _hashInvalidated(true), _isFirstTranExecuted(false), _isCPUExist(true), _isFPGAExist(false){ for (unsigned int i=0; i< _noOfCPUs; i++) _cpus[i]->registerTask(this); #ifdef ADD_COMMENTS @@ -59,8 +59,7 @@ TMLTask::TMLTask(ID iID, Priority iPriority, std::string iName, CPU** iCPU, unsi if (_noOfCPUs==1) _currentCPU = _cpus[0]; } -TMLTask::TMLTask(ID iID, Priority iPriority, std::string iName, FPGA** iFPGA, unsigned int iNoOfFPGAs, bool isDaemon): WorkloadSource(iPriority), _ID(iID), _name(iName), _endLastTransaction(0), _currCommand(0), _firstCommand(0), _currentFPGA(0), _fpgas(iFPGA), _noOfFPGAs(iNoOfFPGAs), _isDaemon(isDaemon), _nextCellIndex(0),_comment(0), _busyCycles(0), _FPGAContentionDelay(0), _noFPGATransactions(0), _justStarted(true), _myInstance(_instanceCount), - _stateHash(0, 30) , _liveVarList(0), _hashInvalidated(true){ +TMLTask::TMLTask(ID iID, Priority iPriority, std::string iName, FPGA** iFPGA, unsigned int iNoOfFPGAs, bool isDaemon): WorkloadSource(iPriority), _ID(iID), _name(iName), _endLastTransaction(0), _currCommand(0), _firstCommand(0), _currentFPGA(0), _fpgas(iFPGA), _noOfFPGAs(iNoOfFPGAs), _isDaemon(isDaemon), _nextCellIndex(0),_comment(0), _busyCycles(0), _FPGAContentionDelay(0), _noFPGATransactions(0), _justStarted(true), _myInstance(_instanceCount), _stateHash(0, 30) , _liveVarList(0), _hashInvalidated(true), _isFirstTranExecuted(false), _isCPUExist(false), _isFPGAExist(true){ for (unsigned int i=0; i< _noOfFPGAs; i++) _fpgas[i]->registerTask(this); #ifdef ADD_COMMENTS @@ -78,8 +77,8 @@ TMLTask::~TMLTask(){ } #endif if (_comment!=0) delete [] _comment; - if(_cpus != 0) delete[] _cpus; // free the allocation of cpu array - if(_fpgas != 0) delete[] _fpgas; // free the allocation of fpga array + if(_isCPUExist) delete[] _cpus; // free the allocation of cpu array + if(_isFPGAExist) delete[] _fpgas; // free the allocation of fpga array } std::string TMLTask::toShortString() const{ diff --git a/simulators/c++2/src_simulator/app/TMLTask.h b/simulators/c++2/src_simulator/app/TMLTask.h index 8c8e40a1ac..030eb59c4a 100755 --- a/simulators/c++2/src_simulator/app/TMLTask.h +++ b/simulators/c++2/src_simulator/app/TMLTask.h @@ -242,6 +242,8 @@ public: bool getIsDaemon() {return _isDaemon;}; bool getIsFirstTranExecuted() {return _isFirstTranExecuted;}; inline void setIsFirstTranExecuted(bool x) {_isFirstTranExecuted = x;}; + bool getIsFPGAExist() {return _isFPGAExist;}; + bool getIsCPUExist() {return _isCPUExist;}; protected: ///ID of the task ID _ID; @@ -266,7 +268,6 @@ protected: ///Number of cores assigned to the task unsigned int _noOfFPGAs; bool _isDaemon; - bool _isFirstTranExecuted; unsigned int _nextCellIndex; #ifdef ADD_COMMENTS @@ -312,6 +313,9 @@ protected: HashAlgo _stateHash; const char* _liveVarList; bool _hashInvalidated; + bool _isFirstTranExecuted; + bool _isCPUExist; + bool _isFPGAExist; static void writeHTMLColumn( std::ofstream& myfile, const unsigned int colSpan, const std::string cellClass ); diff --git a/simulators/c++2/src_simulator/arch/FPGA.cpp b/simulators/c++2/src_simulator/arch/FPGA.cpp index b27e4a91ae..5a8b58e349 100644 --- a/simulators/c++2/src_simulator/arch/FPGA.cpp +++ b/simulators/c++2/src_simulator/arch/FPGA.cpp @@ -56,6 +56,7 @@ FPGA::FPGA( ID iID, unsigned int iCyclesPerExeci, unsigned int iCyclesPerExecc ) : SchedulableDevice(iID, iName, iScheduler) ,_reconfigTime(iReconfigTime) + ,_masterNextTransaction(0) ,_lastTransaction(0) ,_changeIdleModeCycles(iChangeIdleModeCycles) ,_cyclesBeforeIdle(iCyclesBeforeIdle) diff --git a/simulators/c++2/src_simulator/sim/SimComponents.cpp b/simulators/c++2/src_simulator/sim/SimComponents.cpp index 8ebc16f1a1..d267ac9083 100644 --- a/simulators/c++2/src_simulator/sim/SimComponents.cpp +++ b/simulators/c++2/src_simulator/sim/SimComponents.cpp @@ -76,10 +76,10 @@ SimComponents::~SimComponents(){ delete (*i); } - for(TaskList::const_iterator i=_taskList.begin(); i != _taskList.end(); ++i){ - //free tasks before terminate simulator - delete (*i); - } + for(TaskList::const_iterator i=_taskList.begin(); i != _taskList.end(); ++i){ + //free tasks before terminate simulator + delete (*i); + } #ifdef EBRDD_ENABLED for(EBRDDList::iterator i=_ebrddList.begin(); i != _ebrddList.end(); ++i){ diff --git a/simulators/c++2/src_simulator/sim/Simulator.cpp b/simulators/c++2/src_simulator/sim/Simulator.cpp index b40e873042..c4bfd2743e 100644 --- a/simulators/c++2/src_simulator/sim/Simulator.cpp +++ b/simulators/c++2/src_simulator/sim/Simulator.cpp @@ -1066,8 +1066,14 @@ bool Simulator::simulate(TMLTransaction*& oLastTrans){ #ifdef DEBUG_KERNEL std::cout << "kernel:simulate: dependent Task found" << std::endl; #endif - depCPU=depTask->getCPU(); - depFPGA=depTask->getFPGA(); + if(depTask->getIsCPUExist()) + depCPU=depTask->getCPU(); + else + depCPU = 0; + if(depTask->getIsFPGAExist()) + depFPGA=depTask->getFPGA(); + else + depFPGA = 0; if(depCPU){ #ifdef DEBUG_SIMULATE @@ -1119,7 +1125,7 @@ bool Simulator::simulate(TMLTransaction*& oLastTrans){ #ifdef DEBUG_SIMULATE std::cout<<"lets start fpga"<<std::endl; #endif - if (depFPGA!=deviceLET){ + if (depFPGA != 0 && depFPGA != deviceLET){ #ifdef DEBUG_KERNEL std::cout << "kernel:simulate: Tasks running on different FPGAs" << std::endl; #endif @@ -1412,7 +1418,7 @@ void Simulator::decodeCommand(std::string iCmd, std::ostream& iXmlOutStream){ std::cout<<"decodeCommand"<<std::endl; //std::cout << "Not crashed. I: " << iCmd << std::endl; //std::cout << iCmd << std::endl; - unsigned int aCmd, aParam1, aParam2, anErrorCode=0; + unsigned int aCmd = 0, aParam1 = 0, aParam2 = 0, anErrorCode = 0; //std::string anIssuedCmd(iCmd); std::istringstream aInpStream(iCmd); //std::cout << "Not crashed. II\n"; diff --git a/ttool/src/test/java/tmltranslator/MemoryLeakTest.java b/ttool/src/test/java/tmltranslator/MemoryLeakTest.java new file mode 100644 index 0000000000..b6aa2bfcb7 --- /dev/null +++ b/ttool/src/test/java/tmltranslator/MemoryLeakTest.java @@ -0,0 +1,269 @@ +package tmltranslator; + +import common.ConfigurationTTool; +import common.SpecConfigTTool; +import graph.AUTGraph; +import myutil.FileUtils; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import req.ebrdd.EBRDD; +import tepe.TEPE; +import tmltranslator.tomappingsystemc2.DiploSimulatorFactory; +import tmltranslator.tomappingsystemc2.IDiploSimulatorCodeGenerator; +import tmltranslator.tomappingsystemc2.Penalties; +import ui.AbstractUITest; +import ui.TDiagramPanel; +import ui.TMLArchiPanel; +import ui.TURTLEPanel; +import ui.tmldd.TMLArchiDiagramPanel; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertTrue; + +public class MemoryLeakTest extends AbstractUITest { + final String DIR_GEN = "test_diplo_simulator/"; + final String [] MODELS_MEMORY_LEAK = {"fpga_reconfig5", "fpga_reconfig6"}; + private String SIM_DIR; + final int [] NB_OF_ML_STATES = {20, 20}; + final int [] NB_OF_ML_TRANSTIONS = {19, 19}; + final int [] MIN_ML_CYCLES = {75, 76}; + final int [] MAX_ML_CYCLES = {75, 76}; + static String CPP_DIR = "../../../../simulators/c++2/"; + static String valgrindVersionCmd = "valgrind --version"; + static String valgrindExecCmd = "valgrind --leak-check=full --log-file="; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + RESOURCES_DIR = getBaseResourcesDir() + "/tmltranslator/simulator/"; + } + + public MemoryLeakTest() { + super(); + } + + @Before + public void setUp() throws Exception { + SIM_DIR = getBaseResourcesDir() + CPP_DIR; + } + + @Test + public void testMemoryLeak() throws Exception { + for (int i = 0; i < MODELS_MEMORY_LEAK.length; i++) { + String s = MODELS_MEMORY_LEAK[i]; + SIM_DIR = DIR_GEN + s + "_memoryLeak/"; + System.out.println("executing: checking syntax " + s); + // select architecture tab + mainGUI.openProjectFromFile(new File(RESOURCES_DIR + s + ".xml")); + for (TURTLEPanel _tab : mainGUI.getTabs()) { + if (_tab instanceof TMLArchiPanel) { + for (TDiagramPanel tdp : _tab.getPanels()) { + if (tdp instanceof TMLArchiDiagramPanel) { + mainGUI.selectTab(tdp); + break; + } + } + break; + } + } + + mainGUI.checkModelingSyntax(true); + TMLMapping tmap = mainGUI.gtm.getTMLMapping(); + TMLSyntaxChecking syntax = new TMLSyntaxChecking(tmap); + syntax.checkSyntax(); + assertTrue(syntax.hasErrors() == 0); + // Generate SystemC code + System.out.println("executing: sim code gen for " + s); + final IDiploSimulatorCodeGenerator tml2systc; + List<EBRDD> al = new ArrayList<EBRDD>(); + List<TEPE> alTepe = new ArrayList<TEPE>(); + tml2systc = DiploSimulatorFactory.INSTANCE.createCodeGenerator(tmap, al, alTepe); + tml2systc.setModelName(s); + String error = tml2systc.generateSystemC(false, true); + assertTrue(error == null); + + File directory = new File(SIM_DIR); + if (!directory.exists()) { + directory.mkdirs(); + } + + // Putting sim files + System.out.println("SIM executing: sim lib code copying for " + s); + ConfigurationTTool.SystemCCodeDirectory = getBaseResourcesDir() + CPP_DIR; + boolean simFiles = SpecConfigTTool.checkAndCreateSystemCDir(SIM_DIR); + + System.out.println("SIM executing: sim lib code copying done with result " + simFiles); + assertTrue(simFiles); + + System.out.println("SIM Saving file in: " + SIM_DIR); + tml2systc.saveFile(SIM_DIR, "appmodel"); + + // Compile it + System.out.println("executing: compile"); + Process proc; + BufferedReader proc_in; + String str; + boolean mustRecompileAll; + Penalties penalty = new Penalties(SIM_DIR + "src_simulator"); + int changed = penalty.handlePenalties(false); + + if (changed == 1) { + mustRecompileAll = true; + } else { + mustRecompileAll = false; + } + + if (mustRecompileAll) { + System.out.println("executing: " + "make -C " + SIM_DIR + " clean"); + try { + proc = Runtime.getRuntime().exec("make -C " + SIM_DIR + " clean"); + proc_in = new BufferedReader(new InputStreamReader(proc.getInputStream())); + while ((str = proc_in.readLine()) != null) { + // TraceManager.addDev( "Sending " + str + " from " + port + " to client..." ); + System.out.println("executing: " + str); + } + } catch (Exception e) { + // probably make is not installed + System.out.println("FAILED: executing: " + "make -C " + SIM_DIR + " clean"); + return; + } + } + + System.out.println("executing: " + "make -C " + SIM_DIR); + try { + proc = Runtime.getRuntime().exec("make -C " + SIM_DIR + ""); + proc_in = new BufferedReader(new InputStreamReader(proc.getInputStream())); + + monitorError(proc); + + while ((str = proc_in.readLine()) != null) { + // TraceManager.addDev( "Sending " + str + " from " + port + " to client..." ); + System.out.println("executing: " + str); + } + } catch (Exception e) { + // Probably make is not installed + System.out.println("FAILED: executing: " + "make -C " + SIM_DIR); + return; + } + + System.out.println("SUCCESS: executing: " + "make -C " + SIM_DIR); + // check if valgrind installed or not + boolean isValgrindInstalled = false; + try { + proc = Runtime.getRuntime().exec(valgrindVersionCmd); + proc_in = new BufferedReader(new InputStreamReader(proc.getInputStream())); + + monitorError(proc); + + while ((str = proc_in.readLine()) != null) { + // TraceManager.addDev( "Sending " + str + " from " + port + " to client..." ); + System.out.println("executing: " + str); + } + isValgrindInstalled = true; + } catch (Exception e) { + System.out.println("FAILED: valgrind is not installed"); + } + + //run test with valgrind + if(isValgrindInstalled) { + String logPath = SIM_DIR + "valgrind.log"; + proc = Runtime.getRuntime().exec(valgrindExecCmd + logPath + " ./" + SIM_DIR + "run.x" + " -cmd 1 0"); + proc_in = new BufferedReader(new InputStreamReader(proc.getInputStream())); + + monitorError(proc); + + while ((str = proc_in.readLine()) != null) { + // TraceManager.addDev( "Sending " + str + " from " + port + " to client..." ); + System.out.println("executing valgrind: " + str); + } + + int memoryLeakVerify = 0; + boolean errorFound = true; + String sCurrentLine = ""; + BufferedReader br = new BufferedReader(new FileReader(logPath)); + while ((sCurrentLine = br.readLine()) != null) + { + if(sCurrentLine.contains("definitely lost: 0 bytes in 0 blocks")) { + memoryLeakVerify++; + System.out.println(sCurrentLine); + } + + if(sCurrentLine.contains("indirectly lost: 0 bytes in 0 blocks")) { + memoryLeakVerify++; + System.out.println(sCurrentLine); + } + + if(sCurrentLine.contains("possibly lost: 0 bytes in 0 blocks")) { + memoryLeakVerify++; + System.out.println(sCurrentLine); + } + + if(sCurrentLine.contains("ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)")) { + errorFound = false; + System.out.println(sCurrentLine); + } + } + + assertTrue(memoryLeakVerify == 3); //no memory leak + assertTrue(!errorFound);// no error + + } else { + //valgrind is not installed, so run test without it + String graphPath = SIM_DIR + "testgraph_" + s; + try { + + String[] params = new String[3]; + + params[0] = "./" + SIM_DIR + "run.x"; + params[1] = "-cmd"; + params[2] = "1 0; 1 7 100 100 " + graphPath; + proc = Runtime.getRuntime().exec(params); + proc_in = new BufferedReader(new InputStreamReader(proc.getInputStream())); + + monitorError(proc); + + while ((str = proc_in.readLine()) != null) { + // TraceManager.addDev( "Sending " + str + " from " + port + " to client..." ); + System.out.println("executing: " + str); + } + } catch (Exception e) { + // Probably make is not installed + System.out.println("FAILED: executing simulation " + e.getCause()); + return; + } + + File graphFile = new File(graphPath + ".aut"); + String graphData = ""; + try { + graphData = FileUtils.loadFileData(graphFile); + } catch (Exception e) { + assertTrue(false); + } + + AUTGraph graph = new AUTGraph(); + graph.buildGraph(graphData); + + // States and transitions + System.out.println("executing: nb states of " + s + " " + graph.getNbOfStates()); + assertTrue(NB_OF_ML_STATES[i] == graph.getNbOfStates()); + System.out.println("executing: nb transitions of " + s + " " + graph.getNbOfTransitions()); + assertTrue(NB_OF_ML_TRANSTIONS[i] == graph.getNbOfTransitions()); + + // Min and max cycles + int minValue = graph.getMinValue("allCPUsFPGAsTerminated"); + System.out.println("executing: minvalue of " + s + " " + minValue); + assertTrue(MIN_ML_CYCLES[i] == minValue); + + int maxValue = graph.getMaxValue("allCPUsFPGAsTerminated"); + System.out.println("executing: maxvalue of " + s + " " + maxValue); + assertTrue(MAX_ML_CYCLES[i] == maxValue); + } + } + } +} -- GitLab