@@ -341,8 +341,8 @@ void print_usage(const string & progname)
341341 cout << " -silent => silence information output and print only measurements\n " ;
342342 cout << " --version => print application version\n " ;
343343 cout << " -i[=number] | /i[=number] => allow to determine number of iterations\n " ;
344- // cout << " -csv[=file.csv] | /csv[=file.csv] => output compact CSV format to screen or\n"
345- // << " to a file, in case filename is provided\n";
344+ cout << " -csv[=file.csv] | /csv[=file.csv] => output compact CSV format to screen or\n "
345+ << " to a file, in case filename is provided\n " ;
346346 cout << " [-m imc_profile] [-p pcu_profile] [-a freq_band0] [-b freq_band1] [-c freq_band2]\n\n " ;
347347 cout << " Where: imc_profile, pcu_profile, freq_band0, freq_band1 and freq_band2 are the following:\n " ;
348348 cout << " <imc_profile> - profile (counter group) for IMC PMU. Possible values are: 0,1,2,3,4,-1 \n " ;
@@ -382,8 +382,64 @@ struct Metric
382382 Metric () = default ;
383383};
384384
385- void printMetrics (const std::string & header, const std::vector<Metric> & metrics, const bool skipZeroValues = false )
385+ bool csv = false ;
386+ bool csv_header = false ;
387+
388+ void printMetrics (const std::string & header, const std::vector<Metric> & metrics, const CsvOutputType outputType, const bool skipZeroValues = false )
386389{
390+ if (csv)
391+ {
392+ const auto numMetrics = metrics.size ();
393+ choose (outputType,
394+ [&]() {
395+ for (size_t i = 0 ; i < numMetrics; ++i)
396+ {
397+ cout << header << ' ,' ;
398+ }
399+ },
400+ [&]() {
401+ for (size_t i = 0 ; i < numMetrics; ++i)
402+ {
403+ cout << metrics[i].name ;
404+ if (!metrics[i].unit .empty ())
405+ {
406+ cout << ' (' << metrics[i].unit << ' )' ;
407+ }
408+ cout << ' ,' ;
409+ }
410+ },
411+ [&]() {
412+ for (size_t i = 0 ; i < numMetrics; ++i)
413+ {
414+ if (std::holds_alternative<uint64>(metrics[i].value ))
415+ {
416+ cout << std::get<uint64>(metrics[i].value );
417+ }
418+ else if (std::holds_alternative<double >(metrics[i].value ))
419+ {
420+ cout << std::get<double >(metrics[i].value );
421+ }
422+ else if (std::holds_alternative<int64>(metrics[i].value ))
423+ {
424+ cout << std::get<int64>(metrics[i].value );
425+ }
426+ else if (std::holds_alternative<int32>(metrics[i].value ))
427+ {
428+ cout << std::get<int32>(metrics[i].value );
429+ }
430+ else if (std::holds_alternative<bool >(metrics[i].value ))
431+ {
432+ cout << (std::get<bool >(metrics[i].value ) ? ' 1' : ' 0' );
433+ }
434+ else
435+ {
436+ assert (false && " Unknown metric type" );
437+ }
438+ cout << ' ,' ;
439+ }
440+ });
441+ return ;
442+ }
387443 cout << header << " ; " ;
388444 for (const auto & metric : metrics)
389445 {
@@ -444,14 +500,14 @@ void printMetrics(const std::string & header, const std::vector<Metric> & metric
444500 cout << " \n " ;
445501}
446502
447- void printMetrics (const std::string & header, const std::initializer_list<Metric> & metrics, const bool skipZeroValues = false )
503+ void printMetrics (const std::string & header, const std::initializer_list<Metric> & metrics, const CsvOutputType outputType, const bool skipZeroValues = false )
448504{
449505 std::vector<Metric> metricsVec;
450506 for (const auto & metric : metrics)
451507 {
452508 metricsVec.push_back (metric);
453509 }
454- printMetrics (header, metricsVec, skipZeroValues);
510+ printMetrics (header, metricsVec, outputType, skipZeroValues);
455511}
456512
457513PCM_MAIN_NOTHROW;
@@ -479,7 +535,6 @@ int mainThrows(int argc, char * argv[])
479535 freq_band[1 ] = default_freq_band[1 ];
480536 freq_band[2 ] = default_freq_band[2 ];
481537
482- bool csv = false ;
483538 MainLoop mainLoop;
484539 string program = string (argv[0 ]);
485540
@@ -504,10 +559,12 @@ int mainThrows(int argc, char * argv[])
504559 else if (check_argument_equals (*argv, {" -csv" , " /csv" }))
505560 {
506561 csv = true ;
562+ csv_header = true ;
507563 }
508564 else if (extract_argument_value (*argv, {" -csv" , " /csv" }, arg_value))
509565 {
510566 csv = true ;
567+ csv_header = true ;
511568 if (!arg_value.empty ()) {
512569 m->setOutput (arg_value);
513570 }
@@ -684,10 +741,17 @@ int mainThrows(int argc, char * argv[])
684741
685742 if (PERF_LIMIT_REASON_TPMI_Supported) PERF_LIMIT_REASON_TPMI::reset (max_pm_modules);
686743
687- auto printAll = [&](const int delay_ms)
744+ auto printAll = [&](const int delay_ms, const CsvOutputType outputType )
688745 {
689- cout << " Time elapsed: " << AfterTime - BeforeTime << " ms\n " ;
690- cout << " Called sleep function for " << delay_ms << " ms\n " ;
746+ if (csv)
747+ {
748+ printDateForCSV (outputType);
749+ }
750+ else
751+ {
752+ cout << " Time elapsed: " << AfterTime - BeforeTime << " ms\n " ;
753+ cout << " Called sleep function for " << delay_ms << " ms\n " ;
754+ }
691755 for (uint32 socket = 0 ; socket < numSockets; ++socket)
692756 {
693757 if (nCorePowerLicenses)
@@ -699,7 +763,7 @@ int mainThrows(int argc, char * argv[])
699763 {
700764 metrics.push_back (Metric (" Core Power License " + std::to_string (l), getPowerLicenseResidency (l, beforeSocketState[socket], afterSocketState[socket]), " %" ));
701765 }
702- printMetrics (" S" + std::to_string (socket), metrics);
766+ printMetrics (" S" + std::to_string (socket), metrics, outputType );
703767 }
704768 for (uint32 port = 0 ; port < m->getQPILinksPerSocket (); ++port)
705769 {
@@ -708,7 +772,7 @@ int mainThrows(int argc, char * argv[])
708772 Metric (std::string (m->xPI ()) + " Clocks" , getQPIClocks (port, BeforeState[socket], AfterState[socket]), " " ),
709773 Metric (" L0p Tx Cycles" , 100 . * getNormalizedQPIL0pTxCycles (port, BeforeState[socket], AfterState[socket]), " %" ),
710774 Metric (" L1 Cycles" , 100 . * getNormalizedQPIL1Cycles (port, BeforeState[socket], AfterState[socket]), " %" )
711- });
775+ }, outputType );
712776 }
713777 for (uint32 channel = 0 ; channel < m->getMCChannelsPerSocket (); ++channel)
714778 {
@@ -723,7 +787,7 @@ int mainThrows(int argc, char * argv[])
723787 getCKEOffAverageCycles (channel, getFirstRank (imc_profile), BeforeState[socket], AfterState[socket]), " " ),
724788 Metric (" Rank" + std::to_string (getFirstRank (imc_profile)) + " Cycles per transition" ,
725789 getCyclesPerTransition (channel, getFirstRank (imc_profile), BeforeState[socket], AfterState[socket]), " " )
726- });
790+ }, outputType );
727791
728792 printMetrics (" S" + std::to_string (socket) + " CH" + std::to_string (channel),
729793 {
@@ -734,7 +798,7 @@ int mainThrows(int argc, char * argv[])
734798 getCKEOffAverageCycles (channel, getSecondRank (imc_profile), BeforeState[socket], AfterState[socket]), " " ),
735799 Metric (" Rank" + std::to_string (getSecondRank (imc_profile)) + " Cycles per transition" ,
736800 getCyclesPerTransition (channel, getSecondRank (imc_profile), BeforeState[socket], AfterState[socket]), " " )
737- });
801+ }, outputType );
738802 } else if (imc_profile == 4 )
739803 {
740804 printMetrics (" S" + std::to_string (socket) + " CH" + std::to_string (channel),
@@ -743,55 +807,51 @@ int mainThrows(int argc, char * argv[])
743807 Metric (" Self-refresh cycles" , getSelfRefreshCycles (channel, BeforeState[socket], AfterState[socket]), " " ),
744808 Metric (" Self-refresh transitions" , getSelfRefreshTransitions (channel, BeforeState[socket], AfterState[socket]), " " ),
745809 Metric (" PPD cycles" , getPPDCycles (channel, BeforeState[socket], AfterState[socket]), " " )
746- });
810+ }, outputType );
747811 }
748812 }
749813
750814 for (uint32 u = 0 ; u < m->getMaxNumOfUncorePMUs (PCM::PCU_PMU_ID); ++u)
751815 {
752- auto getHeader = [&socket,&m,&u, &BeforeState, &AfterState] ()
816+ std::string header = " S" + std::to_string (socket);
817+ if (m->getMaxNumOfUncorePMUs (PCM::PCU_PMU_ID) > 1 )
753818 {
754- std::string header = " S" + std::to_string (socket);
755- if (m->getMaxNumOfUncorePMUs (PCM::PCU_PMU_ID) > 1 )
756- {
757- header += " U" + std::to_string (u);
758- }
759- return header;
760- };
819+ header += " U" + std::to_string (u);
820+ }
761821 std::vector<Metric> metrics;
762822 switch (pcu_profile)
763823 {
764824 case 0 :
765825 if (cpu_family_model == PCM::HASWELLX || cpu_family_model == PCM::BDX_DE || cpu_family_model == PCM::SKX)
766826 break ;
767827
768- printMetrics (getHeader () ,
828+ printMetrics (header ,
769829 {
770830 Metric (" PCUClocks" , getPCUClocks (u, BeforeState[socket], AfterState[socket]), " " ),
771831 Metric (" Freq band 0 cycles" , 100 . * getNormalizedPCUCounter (u, 1 , BeforeState[socket], AfterState[socket]), " %" ),
772832 Metric (" Freq band 1 cycles" , 100 . * getNormalizedPCUCounter (u, 2 , BeforeState[socket], AfterState[socket]), " %" ),
773833 Metric (" Freq band 2 cycles" , 100 . * getNormalizedPCUCounter (u, 3 , BeforeState[socket], AfterState[socket]), " %" )
774- });
834+ }, outputType );
775835 break ;
776836
777837 case 1 :
778- printMetrics (getHeader () ,
838+ printMetrics (header ,
779839 {
780840 Metric (" PCUClocks" , getPCUClocks (u, BeforeState[socket], AfterState[socket]), " " ),
781841 Metric (cpu_family_model == PCM::SKX ? " C0_1-state residency" : " C0-state residency" , getNormalizedPCUCounter (u, 1 , BeforeState[socket], AfterState[socket]), " " ),
782842 Metric (" C3-state residency" , getNormalizedPCUCounter (u, 2 , BeforeState[socket], AfterState[socket]), " " ),
783843 Metric (cpu_family_model == PCM::SKX ? " C6_7-state residency" : " C6-state residency" , getNormalizedPCUCounter (u, 3 , BeforeState[socket], AfterState[socket]), " " )
784- });
844+ }, outputType );
785845 break ;
786846
787847 case 2 :
788- printMetrics (getHeader () ,
848+ printMetrics (header ,
789849 {
790850 Metric (" PCUClocks" , getPCUClocks (u, BeforeState[socket], AfterState[socket]), " " ),
791851 Metric (" Internal prochot cycles" , 100 . * getNormalizedPCUCounter (u, 1 , BeforeState[socket], AfterState[socket]), " %" ),
792852 Metric (" External prochot cycles" , 100 . * getNormalizedPCUCounter (u, 2 , BeforeState[socket], AfterState[socket]), " %" ),
793853 Metric (" Thermal freq limit cycles" , 100 . * getNormalizedPCUCounter (u, 3 , BeforeState[socket], AfterState[socket]), " %" )
794- });
854+ }, outputType );
795855 break ;
796856
797857 case 3 :
@@ -809,7 +869,7 @@ int mainThrows(int argc, char * argv[])
809869 {
810870 metrics.push_back (Metric (" Clipped freq limit cycles" , 100 . * getNormalizedPCUCounter (u, 3 , BeforeState[socket], AfterState[socket]), " %" ));
811871 }
812- printMetrics (getHeader () , metrics);
872+ printMetrics (header , metrics, outputType );
813873 break ;
814874
815875 case 4 :
@@ -826,13 +886,13 @@ int mainThrows(int argc, char * argv[])
826886 cout << " This PCU profile is not supported on your processor\n " ;
827887 break ;
828888 }
829- printMetrics (getHeader () ,
889+ printMetrics (header ,
830890 {
831891 Metric (" PCUClocks" , getPCUClocks (u, BeforeState[socket], AfterState[socket]), " " ),
832892 Metric (" OS freq limit cycles" , 100 . * getNormalizedPCUCounter (u, 1 , BeforeState[socket], AfterState[socket]), " %" ),
833893 Metric (" Power freq limit cycles" , 100 . * getNormalizedPCUCounter (u, 2 , BeforeState[socket], AfterState[socket]), " %" ),
834894 Metric (" Clipped freq limit cycles" , 100 . * getNormalizedPCUCounter (u, 3 , BeforeState[socket], AfterState[socket]), " %" )
835- });
895+ }, outputType );
836896 break ;
837897 case 5 :
838898 metrics.push_back (Metric (" PCUClocks" , getPCUClocks (u, BeforeState[socket], AfterState[socket]), " " ));
@@ -843,7 +903,7 @@ int mainThrows(int argc, char * argv[])
843903 metrics.push_back (Metric (" UFS transition count" , getUncoreCounter (PCM::PCU_PMU_ID, u, 3 , BeforeState[socket], AfterState[socket]), " " ));
844904 metrics.push_back (Metric (" UFS transition cycles" , 100 . * getNormalizedPCUCounter (u, 0 , BeforeState[socket], AfterState[socket], m), " %" ));
845905 }
846- printMetrics (getHeader () , metrics);
906+ printMetrics (header , metrics, outputType );
847907 break ;
848908 case 6 :
849909 if (cpu_family_model == PCM::HASWELLX || PCM::BDX_DE == cpu_family_model)
@@ -871,25 +931,25 @@ int mainThrows(int argc, char * argv[])
871931 metrics.push_back (Metric (" PC6 transitions" , getUncoreCounter (PCM::PCU_PMU_ID, u, 3 , BeforeState[socket], AfterState[socket]), " " ));
872932 break ;
873933 }
874- printMetrics (getHeader () , metrics);
934+ printMetrics (header , metrics, outputType );
875935 break ;
876936 case 7 :
877937 if (PCM::HASWELLX == cpu_family_model || PCM::BDX_DE == cpu_family_model || PCM::BDX == cpu_family_model) {
878- printMetrics (getHeader () ,
938+ printMetrics (header ,
879939 {
880940 Metric (" UFS_TRANSITIONS_PERF_P_LIMIT" , getNormalizedPCUCounter (u, 0 , BeforeState[socket], AfterState[socket], m) * 100 ., " %" ),
881941 Metric (" UFS_TRANSITIONS_IO_P_LIMIT" , getNormalizedPCUCounter (u, 1 , BeforeState[socket], AfterState[socket], m) * 100 ., " %" ),
882942 Metric (" UFS_TRANSITIONS_UP_RING_TRAFFIC" , getNormalizedPCUCounter (u, 2 , BeforeState[socket], AfterState[socket], m) * 100 ., " %" ),
883943 Metric (" UFS_TRANSITIONS_UP_STALL_CYCLES" , getNormalizedPCUCounter (u, 3 , BeforeState[socket], AfterState[socket], m) * 100 ., " %" )
884- });
944+ }, outputType );
885945 }
886946 break ;
887947 case 8 :
888948 if (PCM::HASWELLX == cpu_family_model || PCM::BDX_DE == cpu_family_model || PCM::BDX == cpu_family_model) {
889- printMetrics (getHeader () ,
949+ printMetrics (header ,
890950 {
891951 Metric (" UFS_TRANSITIONS_DOWN" , getNormalizedPCUCounter (u, 0 , BeforeState[socket], AfterState[socket], m) * 100 ., " %" )
892- });
952+ }, outputType );
893953 }
894954 break ;
895955 }
@@ -901,13 +961,13 @@ int mainThrows(int argc, char * argv[])
901961 Metric (" Consumed Joules" , getConsumedJoules (BeforeState[socket], AfterState[socket]), " " ),
902962 Metric (" Watts" , 1000 . * getConsumedJoules (BeforeState[socket], AfterState[socket]) / double (AfterTime - BeforeTime), " " ),
903963 Metric (" Thermal headroom below TjMax" , AfterState[socket].getPackageThermalHeadroom (), " °C" )
904- });
964+ }, outputType );
905965 printMetrics (" S" + std::to_string (socket),
906966 {
907967 Metric (" Consumed DRAM energy units" , getDRAMConsumedEnergy (BeforeState[socket], AfterState[socket]), " " ),
908968 Metric (" Consumed DRAM Joules" , getDRAMConsumedJoules (BeforeState[socket], AfterState[socket]), " " ),
909969 Metric (" DRAM Watts" , 1000 . * getDRAMConsumedJoules (BeforeState[socket], AfterState[socket]) / double (AfterTime - BeforeTime), " " )
910- });
970+ }, outputType );
911971 }
912972 for (auto instance = 0ULL ; instance < PERF_LIMIT_REASON_TPMI_dies_data.size (); ++instance)
913973 {
@@ -919,7 +979,7 @@ int mainThrows(int argc, char * argv[])
919979 {
920980 metrics.push_back (Metric (PERF_LIMIT_REASON_TPMI::Coarse_Grained_PLR_Bit_Definition_Strings[l], extract_bits (data, l, l) ? true : false , " " ));
921981 }
922- printMetrics (" S" + std::to_string (instance) + " D" + std::to_string (die) + " PERF LIMIT REASONS (DIE LEVEL)" , metrics);
982+ printMetrics (" S" + std::to_string (instance) + " D" + std::to_string (die) + " PERF LIMIT REASONS (DIE LEVEL)" , metrics, outputType );
923983 }
924984 }
925985 for (auto instance = 0ULL ; instance < PERF_LIMIT_REASON_TPMI_modules_data.size (); ++instance)
@@ -960,16 +1020,27 @@ int mainThrows(int argc, char * argv[])
9601020 metrics.push_back (Metric (std::string (PERF_LIMIT_REASON_TPMI::Coarse_Grained_PLR_Bit_Definition_Strings[PERF_LIMIT_REASON_TPMI::Fine_Grained_PLR_Bit_Definition_Data[l].coarse_grained_mapping ]) + " ." +
9611021 PERF_LIMIT_REASON_TPMI::Fine_Grained_PLR_Bit_Definition_Data[l].name , fineGrainedData[die][l], " " ));
9621022 }
963- printMetrics (" S" + std::to_string (instance) + " D" + std::to_string (die) + " PERF LIMIT REASONS (#CORE MODULES)" , metrics, true );
1023+ printMetrics (" S" + std::to_string (instance) + " D" + std::to_string (die) + " PERF LIMIT REASONS (#CORE MODULES)" , metrics, outputType, true );
9641024 }
9651025 }
1026+ if (csv)
1027+ {
1028+ cout << " \n " ;
1029+ }
9661030 };
9671031
968- mainLoop ([& ]()
1032+ auto printLine = [ ]()
9691033 {
9701034 cout << " ----------------------------------------------------------------------------------------------\n " ;
1035+ };
9711036
972- if (!csv) cout << flush;
1037+ mainLoop ([&]()
1038+ {
1039+ if (!csv)
1040+ {
1041+ printLine ();
1042+ cout << flush;
1043+ }
9731044
9741045 const auto delay_ms = calibratedSleep (delay, sysCmd, mainLoop, m);
9751046
@@ -986,14 +1057,23 @@ int mainThrows(int argc, char * argv[])
9861057 PERF_LIMIT_REASON_TPMI::reset (max_pm_modules);
9871058 }
9881059
989- printAll (delay_ms);
1060+ if (csv_header)
1061+ {
1062+ printAll (delay_ms, Header1);
1063+ printAll (delay_ms, Header2);
1064+ csv_header = false ;
1065+ }
1066+ printAll (delay_ms, Data);
9901067
9911068 swap (BeforeState, AfterState);
9921069 swap (BeforeTime, AfterTime);
9931070 swap (beforeSocketState, afterSocketState);
9941071
9951072 if (m->isBlocked ()) {
996- cout << " ----------------------------------------------------------------------------------------------\n " ;
1073+ if (!csv)
1074+ {
1075+ printLine ();
1076+ }
9971077 // in case PCM was blocked after spawning child application: break monitoring loop here
9981078 return false ;
9991079 }
0 commit comments