From 25321e5f3ff5bcbdc2f980bd56ec63536c3490ac Mon Sep 17 00:00:00 2001
From: dblouin <dominique.blouin@telecom-paristech.fr>
Date: Mon, 31 Jul 2017 20:21:53 +0200
Subject: [PATCH] Issue #4: Various issues in HTML trace generation.

---
 simulators/c++2/.cproject                     |   1 +
 .../launch_configurations/c++2 Debug.launch   |   4 +-
 .../launch_configurations/c++2 TTool.launch   |   3 +
 simulators/c++2/src_simulator/arch/Bus.cpp    |  66 +++--
 .../src_simulator/arch/SchedulableDevice.h    |  77 ++++++
 .../c++2/src_simulator/arch/SingleCoreCPU.cpp |  99 +++++---
 simulators/c++2/src_simulator/definitions.h   | 238 ++++++++++++++++--
 .../c++2/src_simulator/sim/Simulator.cpp      |  44 +++-
 8 files changed, 448 insertions(+), 84 deletions(-)

diff --git a/simulators/c++2/.cproject b/simulators/c++2/.cproject
index 0f7bfaa1f9..db29bc9eae 100644
--- a/simulators/c++2/.cproject
+++ b/simulators/c++2/.cproject
@@ -30,6 +30,7 @@
 								</option>
 								<option id="gnu.cpp.compiler.option.optimization.level.465894187" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
 								<option id="gnu.cpp.compiler.option.debugging.level.1015870594" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
+								<option id="gnu.cpp.compiler.option.dialect.std.261412162" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/>
 								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.466144189" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
 							</tool>
 							<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.1668138132" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
diff --git a/simulators/c++2/launch_configurations/c++2 Debug.launch b/simulators/c++2/launch_configurations/c++2 Debug.launch
index fe7bda9208..68416bbc7c 100644
--- a/simulators/c++2/launch_configurations/c++2 Debug.launch	
+++ b/simulators/c++2/launch_configurations/c++2 Debug.launch	
@@ -18,12 +18,12 @@
 <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_START_MODE" value="run"/>
 <booleanAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN" value="false"/>
 <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN_SYMBOL" value="main"/>
-<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_ARGUMENTS" value="-ohtml /home/dblouin/temp/vcddump.html"/>
+<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_ARGUMENTS" value="-ohtml ../simulators/c++2/issue_4_after.html"/>
 <stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="Debug/c++2"/>
 <stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="c++2"/>
 <booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="false"/>
 <stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="cdt.managedbuild.config.gnu.cygwin.exe.debug.999163173"/>
-<stringAttribute key="org.eclipse.cdt.launch.WORKING_DIRECTORY" value="${workspace_loc:bin}"/>
+<stringAttribute key="org.eclipse.cdt.launch.WORKING_DIRECTORY" value="${workspace_loc:libs}"/>
 <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
 <listEntry value="/c++2"/>
 </listAttribute>
diff --git a/simulators/c++2/launch_configurations/c++2 TTool.launch b/simulators/c++2/launch_configurations/c++2 TTool.launch
index d38defe60e..e46ddf5ae8 100644
--- a/simulators/c++2/launch_configurations/c++2 TTool.launch	
+++ b/simulators/c++2/launch_configurations/c++2 TTool.launch	
@@ -14,9 +14,11 @@
 <intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/>
 <stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
 <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_ID" value="gdb"/>
+<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_REGISTER_GROUPS" value=""/>
 <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_START_MODE" value="run"/>
 <booleanAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN" value="true"/>
 <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN_SYMBOL" value="main"/>
+<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_ARGUMENTS" value="-ohtml /home/dblouin/temp/vcddump"/>
 <stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="run.x"/>
 <stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="c++2"/>
 <booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="false"/>
@@ -27,5 +29,6 @@
 <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
 <listEntry value="4"/>
 </listAttribute>
+<stringAttribute key="org.eclipse.dsf.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;memoryBlockExpressionList context=&quot;reserved-for-future-use&quot;/&gt;&#10;"/>
 <stringAttribute key="process_factory_id" value="org.eclipse.cdt.dsf.gdb.GdbProcessFactory"/>
 </launchConfiguration>
diff --git a/simulators/c++2/src_simulator/arch/Bus.cpp b/simulators/c++2/src_simulator/arch/Bus.cpp
index 25b6a4375e..418898b7c2 100644
--- a/simulators/c++2/src_simulator/arch/Bus.cpp
+++ b/simulators/c++2/src_simulator/arch/Bus.cpp
@@ -146,34 +146,62 @@ std::string Bus::toShortString() const{
 
 //Writes a HTML representation of the schedule to an output file
 void Bus::schedule2HTML(std::ofstream& myfile) const{
-	TMLTime aCurrTime=0;
+	TMLTime aCurrTime = 0;
 	TMLTransaction* aCurrTrans;
 	unsigned int aBlanks,aLength,aColor;
-	if (_transactList.empty()) return;
+
+	if ( _transactList.empty( )) {
+		return;
+	}
+
 	myfile << "<h2><span>Scheduling for device: "<< _name <<"</span></h2>\n<table>\n<tr>";
+
 	for(TransactionList::const_iterator i=_transactList.begin(); i != _transactList.end(); ++i){
-		aCurrTrans=*i;
+		aCurrTrans = *i;
 		//if (aCurrTrans->getVirtualLength()==0) continue;
-		aBlanks=aCurrTrans->getStartTimeOperation()-aCurrTime;
-		if (aBlanks>0){
-			if (aBlanks==1)
-				myfile << "<td title=\"idle time\" class=\"not\"></td>\n";
-			else
-				myfile << "<td colspan=\""<< aBlanks <<"\" title=\"idle time\" class=\"not\"></td>\n";
+		aBlanks = aCurrTrans->getStartTimeOperation() - aCurrTime;
+
+		if ( aBlanks > 0 ) {
+			writeColums( myfile, aBlanks, "not", "idle time" );
+//			if (aBlanks==1)
+//				myfile << "<td title=\"idle time\" class=\"not\"></td>\n";
+//			else
+//				myfile << "<td colspan=\""<< aBlanks <<"\" title=\"idle time\" class=\"not\"></td>\n";
 		}
-		aLength=aCurrTrans->getOperationLength();
-		//aColor=(((unsigned int)(aCurrTrans->getCommand()->getTask())) & 15)+1;
-		aColor=aCurrTrans->getCommand()->getTask()->getInstanceNo() & 15;
-		if (aLength==1)
-			myfile << "<td title=\""<< aCurrTrans->toShortString() << "\" class=\"t"<< aColor <<"\"></td>\n";
-		else
-			myfile << "<td colspan=\"" << aLength << "\" title=\"" << aCurrTrans->toShortString() << "\" class=\"t"<< aColor <<"\"></td>\n";
-		aCurrTime=aCurrTrans->getEndTime();
+
+		aLength = aCurrTrans->getOperationLength();
+		unsigned int instNumber = aCurrTrans->getCommand()->getTask()->getInstanceNo() - 1;
+		aColor = instNumber % NB_HTML_COLORS;
+	    std::ostringstream cellClass;
+	    cellClass << "t" << aColor;
+
+		writeColums( myfile, aLength, cellClass.str(), aCurrTrans->toShortString() );
+//
+//		if ( aLength==1 ) {
+//			myfile << "<td title=\""<< aCurrTrans->toShortString() << "\" class=\"t"<< aColor <<"\"></td>\n";
+//		}
+//		else {
+//			myfile << "<td colspan=\"" << aLength << "\" title=\"" << aCurrTrans->toShortString() << "\" class=\"t"<< aColor <<"\"></td>\n";
+//		}
+
+		aCurrTime = aCurrTrans->getEndTime();
 	}
+
 	myfile << "</tr>\n<tr>";
-	for(aLength=0;aLength<aCurrTime;aLength++) myfile << "<th></th>";
+
+	for ( aLength = 0; aLength < aCurrTime; aLength++ ) {
+		myfile << "<th></th>";
+	}
+
 	myfile << "</tr>\n<tr>";
-	for(aLength=0;aLength<aCurrTime;aLength+=5) myfile << "<td colspan=\"5\" class=\"sc\">" << aLength << "</td>";
+
+	for ( aLength = 0; aLength <= aCurrTime; aLength += 5 ) {
+		std::ostringstream spanVal;
+		spanVal << aLength;
+		writeColums( myfile, 5, "sc", "", spanVal.str(), false );
+//		myfile << "<td colspan=\"5\" class=\"sc\">" << aLength << "</td>";
+	}
+
 	myfile << "</tr>\n</table>\n";
 }
 
diff --git a/simulators/c++2/src_simulator/arch/SchedulableDevice.h b/simulators/c++2/src_simulator/arch/SchedulableDevice.h
index 3a7823dcbb..410a599eed 100644
--- a/simulators/c++2/src_simulator/arch/SchedulableDevice.h
+++ b/simulators/c++2/src_simulator/arch/SchedulableDevice.h
@@ -205,6 +205,83 @@ protected:
         unsigned int _dynamic_consumPerCycle; 
 	static TMLTime _overallTransNo;
 	static TMLTime _overallTransSize;
+
+	// Issue #4: Some browsers (like Firefox) do not support column spans of more than 1000 columns
+	void writeColums(	std::ofstream& myfile,
+						const unsigned int colSpan,
+						const std::string cellClass ) const {
+		writeColums( myfile, colSpan, cellClass, "" );
+	}
+
+	void writeColums(	std::ofstream& myfile,
+						const unsigned int colSpan,
+						const std::string cellClass,
+						const std::string title ) const {
+		writeColums( myfile, colSpan, cellClass, title, "", true );
+	}
+
+	void writeColums(	std::ofstream& myfile,
+						const unsigned int colSpan,
+						const std::string cellClass,
+						const std::string title,
+						const std::string content,
+						const bool endline ) const {
+		std::string begLine( START_TD );
+
+		if ( !title.empty() ) {
+			begLine.append( " title=\"" );
+			begLine.append( title );
+			begLine.append( "\"" );
+		}
+
+		begLine.append( " class=\"" );
+
+		if ( colSpan == 1 ) {
+			begLine.append( cellClass );
+			begLine.append( "\"" );
+			myfile << begLine << ">" << END_TD;
+
+			if ( endline ) {
+				myfile << std::endl;
+			}
+		}
+		else {
+			int actualLength = colSpan;
+			bool first = true;
+			bool last = false;
+
+			do {
+				last = actualLength <= MAX_COL_SPAN;
+				std::string clasVal( cellClass );
+
+				if ( first && !last ) {
+					clasVal.append( "first" );
+					first = false;
+				}
+				else if ( last && !first ) {
+					clasVal.append( "last" );
+				}
+				else if ( !last && !first ) {
+					clasVal.append( "mid" );
+				}
+
+				clasVal.append( "\"" );
+
+				std::string colSpan( " colspan=\"" );
+				std::ostringstream spanVal;
+				spanVal << std::min( MAX_COL_SPAN, actualLength ) <<  "\"";
+				colSpan.append( spanVal.str() );
+
+				myfile << begLine << clasVal << colSpan << ">" << content << END_TD;
+
+				if ( last && endline ) {
+					myfile << std::endl;
+				}
+
+				actualLength -= MAX_COL_SPAN;
+			} while ( !last );
+		}
+	}
 };
 
 #endif
diff --git a/simulators/c++2/src_simulator/arch/SingleCoreCPU.cpp b/simulators/c++2/src_simulator/arch/SingleCoreCPU.cpp
index f54e810668..529af8a111 100644
--- a/simulators/c++2/src_simulator/arch/SingleCoreCPU.cpp
+++ b/simulators/c++2/src_simulator/arch/SingleCoreCPU.cpp
@@ -335,48 +335,79 @@ void SingleCoreCPU::schedule2HTML(std::ofstream& myfile) const{
   //if (_transactList.empty()) return;
   //std::cout << "0. size: " << _transactList.size() << '\n';
   myfile << "<h2><span>Scheduling for device: "<< _name <<"</span></h2>\n<table>\n<tr>";
+
   for(TransactionList::const_iterator i=_transactList.begin(); i != _transactList.end(); ++i){
     aCurrTrans=*i;
     //if (aCurrTrans->getVirtualLength()==0) continue;
     aBlanks=aCurrTrans->getStartTime()-aCurrTime;
     if (aBlanks>0){
-      if (aBlanks==1)
-        myfile << "<td title=\"idle time\" class=\"not\"></td>\n";
-      else
-        myfile << "<td colspan=\""<< aBlanks <<"\" title=\"idle time\" class=\"not\"></td>\n";
+
+    	// Issue #4
+		writeColums( myfile, aBlanks, "not", "idle time" );
+//      if (aBlanks==1)
+//        myfile << "<td title=\"idle time\" class=\"not\"></td>\n";
+//      else
+//        myfile << "<td colspan=\""<< aBlanks <<"\" title=\"idle time\" class=\"not\"></td>\n";
     }
-    aLength=aCurrTrans->getPenalties();
-    if (aLength!=0){
-      if (aLength==1){
-        //myfile << "<td title=\""<< aCurrTrans->toShortString() << "\" class=\"t15\"></td>\n";
-        //myfile << "<td title=\" idle:" << aCurrTrans->getIdlePenalty() << " switch:" << aCurrTrans->getTaskSwitchingPenalty() << " bran:" << aCurrTrans->getBranchingPenalty() << "\" class=\"t15\"></td>\n";
-        myfile << "<td title=\" idle:" << aCurrTrans->getIdlePenalty() << " switch:" << aCurrTrans->getTaskSwitchingPenalty() << "\" class=\"t15\"></td>\n";
-      }else{
-        //myfile << "<td colspan=\"" << aLength << "\" title=\" idle:" << aCurrTrans->getIdlePenalty() << " switch:" << aCurrTrans->getTaskSwitchingPenalty() << " bran:" << aCurrTrans->getBranchingPenalty() << "\" class=\"t15\"></td>\n";
-        myfile << "<td colspan=\"" << aLength << "\" title=\" idle:" << aCurrTrans->getIdlePenalty() << " switch:" << aCurrTrans->getTaskSwitchingPenalty() << "\" class=\"t15\"></td>\n";
-      }
+
+    aLength = aCurrTrans->getPenalties();
+
+    if ( aLength != 0 ) {
+    	// Issue #4
+        std::ostringstream title;
+        title << "idle:" << aCurrTrans->getIdlePenalty() << " switch:" << aCurrTrans->getTaskSwitchingPenalty();
+		writeColums( myfile, aLength, "not", title.str() );
+//      if (aLength==1){
+//        //myfile << "<td title=\""<< aCurrTrans->toShortString() << "\" class=\"t15\"></td>\n";
+//        //myfile << "<td title=\" idle:" << aCurrTrans->getIdlePenalty() << " switch:" << aCurrTrans->getTaskSwitchingPenalty() << " bran:" << aCurrTrans->getBranchingPenalty() << "\" class=\"t15\"></td>\n";
+//        myfile << "<td title=\" idle:" << aCurrTrans->getIdlePenalty() << " switch:" << aCurrTrans->getTaskSwitchingPenalty() << "\" class=\"t15\"></td>\n";
+//      }else{
+//        //myfile << "<td colspan=\"" << aLength << "\" title=\" idle:" << aCurrTrans->getIdlePenalty() << " switch:" << aCurrTrans->getTaskSwitchingPenalty() << " bran:" << aCurrTrans->getBranchingPenalty() << "\" class=\"t15\"></td>\n";
+//        myfile << "<td colspan=\"" << aLength << "\" title=\" idle:" << aCurrTrans->getIdlePenalty() << " switch:" << aCurrTrans->getTaskSwitchingPenalty() << "\" class=\"t15\"></td>\n";
+//      }
     }
-    aLength=aCurrTrans->getOperationLength();
-    aColor=aCurrTrans->getCommand()->getTask()->getInstanceNo() & 15;
-    if (aLength==1)
-      myfile << "<td title=\""<< aCurrTrans->toShortString() << "\" class=\"t"<< aColor <<"\"></td>\n";
-    else
-      myfile << "<td colspan=\"" << aLength << "\" title=\"" << aCurrTrans->toShortString() << "\" class=\"t"<< aColor <<"\"></td>\n";
 
+    aLength = aCurrTrans->getOperationLength();
+    aColor = aCurrTrans->getCommand()->getTask()->getInstanceNo() & NB_HTML_COLORS;
+    std::ostringstream cellClass;
+    cellClass << "t" << aColor;
 
-    aCurrTime=aCurrTrans->getEndTime();
+    writeColums( myfile, aLength, cellClass.str(), aCurrTrans->toShortString() );
+//
+//    if ( aLength == 1 )
+//      myfile << "<td title=\""<< aCurrTrans->toShortString() << "\" class=\"t"<< aColor <<"\"></td>\n";
+//    else
+//      myfile << "<td colspan=\"" << aLength << "\" title=\"" << aCurrTrans->toShortString() << "\" class=\"t"<< aColor <<"\"></td>\n";
+
+
+    aCurrTime = aCurrTrans->getEndTime();
     //std::cout << "end time: " << aCurrTrans->getEndTime() << std::endl;
   }
   //std::cout << "acurrTime: " << aCurrTime << std::endl;
   myfile << "</tr>\n<tr>";
-  for(aLength=0;aLength<aCurrTime;aLength++) myfile << "<th></th>";
+
+  for ( aLength = 0; aLength < aCurrTime; aLength++ ) {
+	  myfile << "<th></th>";
+  }
+
   myfile << "</tr>\n<tr>";
-  for(aLength=0;aLength<aCurrTime;aLength+=5) myfile << "<td colspan=\"5\" class=\"sc\">" << aLength << "</td>";
+
+  for ( aLength = 0; aLength <= aCurrTime; aLength += 5 ) {
+	  std::ostringstream spanVal;
+	  spanVal << aLength;
+	  writeColums( myfile, 5, "sc", "", spanVal.str(), false );
+	  //myfile << "<td colspan=\"5\" class=\"sc\">" << aLength << "</td>";
+  }
+
   myfile << "</tr>\n</table>\n<table>\n<tr>";
-  for(TaskList::const_iterator j=_taskList.begin(); j != _taskList.end(); ++j){
-    aColor=(*j)->getInstanceNo() & 15;
-    myfile << "<td class=\"t"<< aColor <<"\"></td><td>"<< (*j)->toString() << "</td><td class=\"space\"></td>\n";
+
+  for( TaskList::const_iterator j = _taskList.begin(); j != _taskList.end(); ++j ) {
+	  unsigned int instNumber = (*j)->getInstanceNo() - 1;
+	  aColor = instNumber % NB_HTML_COLORS;
+    							// Unset the default td max-width of 5px. For some reason setting the max-with on a specific t style does not work
+	  myfile << "<td class=\"t" << aColor << "\"></td><td style=\"max-width: unset;\">" << (*j)->toString() << "</td><td class=\"space\"></td>\n";
   }
+
   myfile << "</tr>";
 #ifdef ADD_COMMENTS
   bool aMoreComments=true, aInit=true;
@@ -429,15 +460,15 @@ int SingleCoreCPU::allTrans2XML(std::ostringstream& glob, int maxNbOfTrans) cons
 }
 
 void SingleCoreCPU::latencies2XML(std::ostringstream& glob, int id1, int id2) {
-
-  for(TransactionList::const_iterator i=_transactList.begin(); i != _transactList.end(); ++i){
-	if ((*i)->getCommand() !=NULL){
-	if ((*i)->getCommand()->getID() == id1 || (*i)->getCommand()->getID() == id2){
-	    (*i)->toXML(glob, 1, _name);
-	}
+	for(TransactionList::const_iterator i=_transactList.begin(); i != _transactList.end(); ++i){
+		if ((*i)->getCommand() !=NULL){
+			if ((*i)->getCommand()->getID() == id1 || (*i)->getCommand()->getID() == id2){
+				(*i)->toXML(glob, 1, _name);
+			}
+		}
 	}
-  }
-  return;
+
+	return;
 }
 
 
diff --git a/simulators/c++2/src_simulator/definitions.h b/simulators/c++2/src_simulator/definitions.h
index fca965bbce..4c8d5c2dcb 100644
--- a/simulators/c++2/src_simulator/definitions.h
+++ b/simulators/c++2/src_simulator/definitions.h
@@ -225,9 +225,17 @@ using std::max;
 #define TAG_ENERGYo "<energy>"
 #define TAG_ENERGYc "</energy>"
 
-// Issue #4 HTML Trace Constants
 #define EXT_SEP "."
-#define CSS "css"
+#define EXT_VCD ".vcd"
+#define EXT_TXT ".txt"
+#define EXT_HTML ".html"
+#define EXT_CSS ".css"
+
+// Issue #4 HTML Trace Constants
+#define MAX_COL_SPAN 1000
+#define START_TD "<td"
+#define END_TD "</td>"
+
 #define SCHED_CSS_FILE_NAME "schedstyle.css"
 #define SCHED_HTML_DOC "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
 #define SCHED_HTML_BEG_HTML "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
@@ -243,7 +251,7 @@ using std::max;
 #define SCHED_HTML_END_STYLE "</style>\n"
 #define SCHED_HTML_CSS_BEG_LINK "<link rel=\"stylesheet\" type=\"text/css\" href=\""
 #define SCHED_HTML_CSS_END_LINK "\" />\n"
-
+#define NB_HTML_COLORS 15
 #define SCHED_HTML_CSS_CONTENT "table{\n \
 	border-collapse: collapse;\n \
 	empty-cells: show;\n \
@@ -252,6 +260,7 @@ using std::max;
 td{\n \
 	padding: 10px 5px;\n \
 	border: 1px solid black;\n \
+	max-width: 5px;\n \
 }\n \
 th{\n \
 	padding: 5px;\n \
@@ -277,22 +286,213 @@ h2 span {\n \
 }\n \
 .space{border-style: none;}\n \
 .not{background-color: white;}\n \
-.t1{background-color: yellow;}\n \
-.t2{background-color: purple;}\n \
-.t3{background-color: red;}\n \
-.t4{background-color: silver;}\n \
-.t5{background-color: teal;}\n \
-.t6{background-color: aqua;}\n \
-.t7{background-color: olive;}\n \
-.t8{background-color: navy;}\n \
-.t9{background-color: maroon;}\n \
-.t10{background-color: lime;}\n \
-.t11{background-color: green;}\n \
-.t12{background-color: gray;}\n \
-.t13{background-color: fuchsia;}\n \
-.t14{background-color: blue;}\n \
-.t15{background-color: black;}\n \
-.t16{background-color: white;}"
+.notfirst {\n \
+	background-color: white;\n \
+	border-style: solid none solid solid;\n \
+}\n \
+.notmid {\n \
+	background-color: white;\n \
+	border-style: solid none solid none;\n \
+}\n \
+.notlast {\n \
+	background-color: white;\n \
+	border-style: solid solid solid none;\n \
+}\n \
+.t0{background-color: yellow;}\n \
+.t0first {\n \
+	background-color: yellow;\n \
+	border-style: solid none solid solid;\n \
+}\n \
+.t0mid {\n \
+	background-color: yellow;\n \
+	border-style: solid none solid none;\n \
+}\n \
+.t0last {\n \
+	background-color: yellow;\n \
+	border-style: solid solid solid none;\n \
+}\n \
+.t1{background-color: purple;}\n \
+.t1first {\n \
+	background-color: purple;\n \
+	border-style: solid none solid solid;\n \
+}\n \
+.t1mid {\n \
+	background-color: purple;\n \
+	border-style: solid none solid none;\n \
+}\n \
+.t1last {\n \
+	background-color: purple;\n \
+	border-style: solid solid solid none;\n \
+}\n \
+.t2{background-color: red;}\n \
+.t2first {\n \
+	background-color: red;\n \
+	border-style: solid none solid solid;\n \
+}\n \
+.t2mid {\n \
+	background-color: red;\n \
+	border-style: solid none solid none;\n \
+}\n \
+.t2last {\n \
+	background-color: red;\n \
+	border-style: solid solid solid none;\n \
+}\n \
+.t3{background-color: silver;}\n \
+.t3first {\n \
+	background-color: silver;\n \
+	border-style: solid none solid solid;\n \
+}\n \
+.t3mid {\n \
+	background-color: silver;\n \
+	border-style: solid none solid none;\n \
+}\n \
+.t3last {\n \
+	background-color: silver;\n \
+	border-style: solid solid solid none;\n \
+}\n \
+.t4{background-color: teal;}\n \
+.t4first {\n \
+	background-color: teal;\n \
+	border-style: solid none solid solid;\n \
+}\n \
+.t4mid {\n \
+	background-color: teal;\n \
+	border-style: solid none solid none;\n \
+}\n \
+.t4last {\n \
+	background-color: teal;\n \
+	border-style: solid solid solid none;\n \
+}\n \
+.t5{background-color: aqua;}\n \
+.t5first {\n \
+	background-color: aqua;\n \
+	border-style: solid none solid solid;\n \
+}\n \
+.t5mid {\n \
+	background-color: aqua;\n \
+	border-style: solid none solid none;\n \
+}\n \
+.t5last {\n \
+	background-color: aqua;\n \
+	border-style: solid solid solid none;\n \
+}\n \
+.t6{background-color: olive;}\n \
+.t6first {\n \
+	background-color: olive;\n \
+	border-style: solid none solid solid;\n \
+}\n \
+.t6mid {\n \
+	background-color: olive;\n \
+	border-style: solid none solid none;\n \
+}\n \
+.t6last {\n \
+	background-color: olive;\n \
+	border-style: solid solid solid none;\n \
+}\n \
+.t7{background-color: navy;}\n \
+.t7first {\n \
+	background-color: navy;\n \
+	border-style: solid none solid solid;\n \
+}\n \
+.t7mid {\n \
+	background-color: navy;\n \
+	border-style: solid none solid none;\n \
+}\n \
+.t7last {\n \
+	background-color: navy;\n \
+	border-style: solid solid solid none;\n \
+}\n \
+.t8{background-color: maroon;}\n \
+.t8first {\n \
+	background-color: maroon;\n \
+	border-style: solid none solid solid;\n \
+}\n \
+.t8mid {\n \
+	background-color: maroon;\n \
+	border-style: solid none solid none;\n \
+}\n \
+.t8last {\n \
+	background-color: maroon;\n \
+	border-style: solid solid solid none;\n \
+}\n \
+.t9{background-color: lime;}\n \
+.t9first {\n \
+	background-color: lime;\n \
+	border-style: solid none solid solid;\n \
+}\n \
+.t9mid {\n \
+	background-color: lime;\n \
+	border-style: solid none solid none;\n \
+}\n \
+.t9last {\n \
+	background-color: lime;\n \
+	border-style: solid solid solid none;\n \
+}\n \
+.t10{background-color: green;}\n \
+.t10first {\n \
+	background-color: green;\n \
+	border-style: solid none solid solid;\n \
+}\n \
+.t10mid {\n \
+	background-color: green;\n \
+	border-style: solid none solid none;\n \
+}\n \
+.t10last {\n \
+	background-color: green;\n \
+	border-style: solid solid solid none;\n \
+}\n \
+.t11{background-color: gray;}\n \
+.t11first {\n \
+	background-color: gray;\n \
+	border-style: solid none solid solid;\n \
+}\n \
+.t11mid {\n \
+	background-color: gray;\n \
+	border-style: solid none solid none;\n \
+}\n \
+.t11last {\n \
+	background-color: gray;\n \
+	border-style: solid solid solid none;\n \
+}\n \
+.t12{background-color: fuchsia;}\n \
+.t12first {\n \
+	background-color: fuchsia;\n \
+	border-style: solid none solid solid;\n \
+}\n \
+.t12mid {\n \
+	background-color: fuchsia;\n \
+	border-style: solid none solid none;\n \
+}\n \
+.t12last {\n \
+	background-color: fuchsia;\n \
+	border-style: solid solid solid none;\n \
+}\n \
+.t13{background-color: blue;}\n \
+.t13first {\n \
+	background-color: blue;\n \
+	border-style: solid none solid solid;\n \
+}\n \
+.t13mid {\n \
+	background-color: blue;\n \
+	border-style: solid none solid none;\n \
+}\n \
+.t13last {\n \
+	background-color: blue;\n \
+	border-style: solid solid solid none;\n \
+}\n \
+.t14{background-color: black;}\n \
+.t14first {\n \
+	background-color: black;\n \
+	border-style: solid none solid solid;\n \
+}\n \
+.t14mid {\n \
+	background-color: black;\n \
+	border-style: solid none solid none;\n \
+}\n \
+.t14last {\n \
+	background-color: black;\n \
+	border-style: solid solid solid none;\n \
+}"
 
 class TMLTask;
 class TMLTransaction;
diff --git a/simulators/c++2/src_simulator/sim/Simulator.cpp b/simulators/c++2/src_simulator/sim/Simulator.cpp
index 6068222357..1844718a73 100644
--- a/simulators/c++2/src_simulator/sim/Simulator.cpp
+++ b/simulators/c++2/src_simulator/sim/Simulator.cpp
@@ -236,10 +236,19 @@ void Simulator::schedule2Graph(std::string& iTraceFileName) const{
   std::cout << "The Graph output took " << getTimeDiff(aBegin,aEnd) << "usec. File: " << iTraceFileName << std::endl;
 }
 
+bool ends_with(std::string const& str, std::string const& suffix) {
+    return suffix.size() <= str.size() && str.find( suffix, str.size() - suffix.size()) != str.npos;
+}
+
 void Simulator::schedule2TXT(std::string& iTraceFileName) const{
   struct timeval aBegin,aEnd;
   gettimeofday(&aBegin,NULL);
-  std::ofstream myfile (iTraceFileName.c_str());
+
+  if ( !ends_with( iTraceFileName, EXT_TXT ) ) {
+	  iTraceFileName.append( EXT_TXT );
+  }
+
+  std::ofstream myfile(iTraceFileName.c_str());
   if (myfile.is_open()){
     //for(CPUList::const_iterator i=_simComp->getCPUIterator(false); i != _simComp->getCPUIterator(true); ++i){
     for(CPUList::const_iterator i=_simComp->getCPUList().begin(); i != _simComp->getCPUList().end(); ++i){
@@ -251,8 +260,10 @@ void Simulator::schedule2TXT(std::string& iTraceFileName) const{
     }
     myfile.close();
   }
-  else
+  else {
     std::cout << "Unable to open text output file." << std::endl;
+  }
+
   gettimeofday(&aEnd,NULL);
   std::cout << "The text output took " << getTimeDiff(aBegin,aEnd) << "usec. File: " << iTraceFileName << std::endl;
 }
@@ -284,7 +295,12 @@ void Simulator::latencies2XML(std::ostringstream& glob, int id1, int id2) {
 void Simulator::schedule2HTML(std::string& iTraceFileName) const {
   struct timeval aBegin,aEnd;
   gettimeofday(&aBegin,NULL);
-  std::ofstream myfile (iTraceFileName.c_str());
+
+  if ( !ends_with( iTraceFileName, EXT_HTML ) ) {
+	  iTraceFileName.append( EXT_HTML );
+  }
+
+  std::ofstream myfile(iTraceFileName.c_str());
 
   if (myfile.is_open()) {
   	// DB: Issue #4
@@ -292,17 +308,19 @@ void Simulator::schedule2HTML(std::string& iTraceFileName) const {
     myfile << SCHED_HTML_BEG_HTML; // <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n
     myfile << SCHED_HTML_BEG_HEAD; // <head>\n
 
-    const int indexSlash = iTraceFileName.find_last_of( "/" );
-    const int indexExt = iTraceFileName.find_last_of( EXT_SEP );
-    std::string cssFileName;
+    const std::string::size_type findSlash = iTraceFileName.find_last_of( "/" );
+    unsigned int indexSlash;
 
-    if ( indexExt >= 0 ) {
-    	cssFileName = iTraceFileName.substr( indexSlash + 1, indexExt - indexSlash ) + CSS;
+    if ( findSlash == std::string::npos ) {
+    	indexSlash = 0;
     }
     else {
-    	cssFileName = iTraceFileName.substr( indexSlash + 1 ).append( EXT_SEP ).append( CSS );
+    	indexSlash = findSlash;
     }
 
+    const std::string ext( EXT_HTML );
+    const std::string cssFileName = iTraceFileName.substr( indexSlash + 1, iTraceFileName.length() - indexSlash - ext.length() - 1 ) + EXT_CSS;
+
     const std::string cssFullFileName = iTraceFileName.substr( 0, indexSlash + 1 ) + cssFileName;
     std::ofstream cssfile( cssFullFileName.c_str() );
 
@@ -357,7 +375,13 @@ void Simulator::schedule2VCD(std::string& iTraceFileName) const{
   gettimeofday(&aBegin,NULL);
   time(&aRawtime);
   aTimeinfo=localtime(&aRawtime);
-  std::ofstream myfile (iTraceFileName.c_str());
+
+  if ( !ends_with( iTraceFileName, EXT_VCD ) ) {
+	  iTraceFileName.append( EXT_VCD );
+  }
+
+  std::ofstream myfile(iTraceFileName.c_str());
+
   if (myfile.is_open()){
     //std::cout << "File is open" << std::endl;
     SignalChangeQueue aQueue;
-- 
GitLab