From 1cce8e8dec77ffe35acaadab1ae0fd565fd6e28e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 16:41:04 +0200 Subject: [PATCH 01/21] Add new translation unit --- CMakeLists.txt | 6 +++++- tool/pftool_tasks.cc | 1 + tool/pftool_tasks.h | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tool/pftool_tasks.cc create mode 100644 tool/pftool_tasks.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d3dedf4..512bd905 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,7 +51,11 @@ target_include_directories(pflib PUBLIC "$") target_link_libraries(pflib PUBLIC yaml-cpp) -add_executable(pftool tool/pftool.cc tool/Menu.cc tool/Rcfile.cc) +add_executable(pftool + tool/pftool.cc + tool/Menu.cc + tool/Rcfile.cc + tool/pftool_tasks.cc) target_link_libraries(pftool PRIVATE pflib readline) # don't install test-menu executable! just for Menu developments diff --git a/tool/pftool_tasks.cc b/tool/pftool_tasks.cc new file mode 100644 index 00000000..4502239c --- /dev/null +++ b/tool/pftool_tasks.cc @@ -0,0 +1 @@ +#include "pftool_tasks.h" diff --git a/tool/pftool_tasks.h b/tool/pftool_tasks.h new file mode 100644 index 00000000..8a6f6d80 --- /dev/null +++ b/tool/pftool_tasks.h @@ -0,0 +1,4 @@ +#ifndef PFTOOL_TASKS_H +#define PFTOOL_TASKS_H + +#endif /* PFTOOL_TASKS_H */ From c77b5ecbc627e9f444af6259f1feb38ef1655b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 16:42:49 +0200 Subject: [PATCH 02/21] Include new header --- tool/pftool.cc | 78 ++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 40 deletions(-) diff --git a/tool/pftool.cc b/tool/pftool.cc index 75b04a3a..d982815a 100644 --- a/tool/pftool.cc +++ b/tool/pftool.cc @@ -3,7 +3,7 @@ * * The commands are written into functions corresponding to the menu's name. */ - +#include "pftool_tasks.h" #include #include #include @@ -1208,7 +1208,7 @@ static void daq_debug( const std::string& cmd, PolarfireTarget* pft ) { reg1=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,1); reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,2); printf(" Read Page: %d Write Page : %d Full: %d Empty: %d Evt Length on current page: %d\n",(reg1>>13)&0x1,(reg1>>12)&0x1,(reg1>>15)&0x1,(reg1>>14)&0x1,(reg1>>0)&0xFFF); printf(" Spy page : %d Spy-as-source : %d Length-of-spy-injected-event : %d\n",reg2&0x1,(reg2>>1)&0x1,(reg2>>16)&0xFFF); - } + } if (cmd=="FULL_DEBUG") { uint32_t reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,2); reg2=reg2^0x2;// invert @@ -1240,9 +1240,9 @@ static void daq_debug( const std::string& cmd, PolarfireTarget* pft ) { else reg2=reg2&0xFFFFFFFEu; pft->wb->wb_write(pflib::tgt_DAQ_Outbuffer,2,reg2); - for (size_t i=0; iwb->wb_write(pflib::tgt_DAQ_Outbuffer,0x1000+i,data[i]); - + /// set the length reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,2); reg2=reg2&0xFFFF;// remove the upper bits @@ -1260,7 +1260,7 @@ static void daq_debug( const std::string& cmd, PolarfireTarget* pft ) { for (int i=0; i<40; i++) { uint32_t val=pft->wb->wb_read(pflib::tgt_DAQ_Inbuffer,(input<<7)|0x40|i); printf("%2d %08x\n",i,val); - } + } } if (cmd=="EFSPY") { static int input=0; @@ -1274,7 +1274,7 @@ static void daq_debug( const std::string& cmd, PolarfireTarget* pft ) { uint32_t val=pft->wb->wb_read(pflib::tgt_DAQ_LinkFmt,(input<<7)|4); printf("%2d %08x\n",i,val); } - pft->wb->wb_write(pflib::tgt_DAQ_LinkFmt,(input<<7)|3,0); + pft->wb->wb_write(pflib::tgt_DAQ_LinkFmt,(input<<7)|3,0); } if (cmd=="SPY") { // set the spy page to match the read page @@ -1290,7 +1290,7 @@ static void daq_debug( const std::string& cmd, PolarfireTarget* pft ) { printf("%04d %08x\n",int(i),val); } } - + if (cmd=="ROC_LOAD") { std::vector data=read_words_from_file(); if (int(data.size())!=PolarfireTarget::NLINKS*40) { @@ -1306,7 +1306,7 @@ static void daq_debug( const std::string& cmd, PolarfireTarget* pft ) { pft->wb->wb_write(pflib::tgt_DAQ_Inbuffer,(ilink<<7)+3,reg); // load the bytes for (int i=0; i<40; i++) - pft->wb->wb_write(pflib::tgt_DAQ_Inbuffer,(ilink<<7)|0x40|i,data[40*ilink+i]); + pft->wb->wb_write(pflib::tgt_DAQ_Inbuffer,(ilink<<7)|0x40|i,data[40*ilink+i]); } } } @@ -1332,14 +1332,14 @@ static void bias( const std::string& cmd, PolarfireTarget* pft ) { iboard=BaseMenu::readline_int("Which board? ",iboard); pflib::Bias bias=pft->hcal.bias(iboard); } - + if (cmd=="INIT") { iboard=BaseMenu::readline_int("Which board? ",iboard); pflib::Bias bias=pft->hcal.bias(iboard); bias.initialize(); } if (cmd=="SET") { - iboard=BaseMenu::readline_int("Which board? ",iboard); + iboard=BaseMenu::readline_int("Which board? ",iboard); static int led_sipm=0; led_sipm=BaseMenu::readline_int(" SiPM(0) or LED(1)? ",led_sipm); int ichan=BaseMenu::readline_int(" Which HDMI connector? ",-1); @@ -1388,7 +1388,7 @@ static void RunMenu( PolarfireTarget* pft_ ) { pfMenu::Line("STATUS", "Wishbone errors counters", &wb ), pfMenu::Line("QUIT","Back to top menu") }); - + pfMenu menu_i2c({ pfMenu::Line("BUS","Pick the I2C bus to use", &i2c ), pfMenu::Line("READ", "Read from an address", &i2c ), @@ -1397,7 +1397,7 @@ static void RunMenu( PolarfireTarget* pft_ ) { pfMenu::Line("MULTIWRITE", "Write to an address", &i2c ), pfMenu::Line("QUIT","Back to top menu") }); - + pfMenu menu_link({ /* pfMenu::Line("STATUS","Dump link status", &link ), @@ -1406,10 +1406,10 @@ static void RunMenu( PolarfireTarget* pft_ ) { */ pfMenu::Line("QUIT","Back to top menu") }); - + pfMenu menu_elinks({ pfMenu::Line("RELINK","Follow standard procedure to establish links", &elinks), - pfMenu::Line("HARD_RESET","Hard reset of the PLL", &elinks), + pfMenu::Line("HARD_RESET","Hard reset of the PLL", &elinks), pfMenu::Line("STATUS", "Elink status summary", &elinks ), pfMenu::Line("SPY", "Spy on an elink", &elinks ), pfMenu::Line("HEADER_CHECK", "Do a pedestal run and tally good/bad headers, only non-DMA", &elinks), @@ -1419,7 +1419,7 @@ static void RunMenu( PolarfireTarget* pft_ ) { pfMenu::Line("BIGSPY", "Take a spy of a specific channel at 32-bits", &elinks), pfMenu::Line("QUIT","Back to top menu") }); - + pfMenu menu_roc({ pfMenu::Line("HARDRESET","Hard reset to all rocs", &roc), pfMenu::Line("SOFTRESET","Soft reset to all rocs", &roc), @@ -1438,7 +1438,7 @@ static void RunMenu( PolarfireTarget* pft_ ) { pfMenu::Line("DEFAULT_PARAMS", "Load default YAML files", &roc), pfMenu::Line("QUIT","Back to top menu") }, roc_render); - + pfMenu menu_bias({ // pfMenu::Line("STATUS","Read the bias line settings", &bias ), pfMenu::Line("INIT","Initialize a board", &bias ), @@ -1446,7 +1446,7 @@ static void RunMenu( PolarfireTarget* pft_ ) { pfMenu::Line("LOAD","Load bias values from file", &bias ), pfMenu::Line("QUIT","Back to top menu"), }); - + pfMenu menu_fc({ pfMenu::Line("STATUS","Check status and counters", &fc ), pfMenu::Line("SW_L1A","Send a software L1A", &fc ), @@ -1461,7 +1461,7 @@ static void RunMenu( PolarfireTarget* pft_ ) { pfMenu::Line("ENABLES","Enable various sources of signal", &fc ), pfMenu::Line("QUIT","Back to top menu") }); - + pfMenu menu_daq_debug({ pfMenu::Line("STATUS","Provide the status", &daq_debug ), pfMenu::Line("FULL_DEBUG", "Toggle debug mode for full-event buffer", &daq_debug ), @@ -1476,7 +1476,7 @@ static void RunMenu( PolarfireTarget* pft_ ) { pfMenu::Line("EFSPY","Spy on an event formatter buffer", &daq_debug ), pfMenu::Line("QUIT","Back to top menu") }); - + pfMenu menu_daq_setup({ pfMenu::Line("STATUS", "Status of the DAQ", &daq_setup), pfMenu::Line("ENABLE", "Toggle enable status", &daq_setup), @@ -1490,7 +1490,7 @@ static void RunMenu( PolarfireTarget* pft_ ) { #endif pfMenu::Line("QUIT","Back to DAQ menu") }); - + pfMenu menu_daq({ pfMenu::Line("DEBUG", "Debugging menu", &menu_daq_debug ), pfMenu::Line("STATUS", "Status of the DAQ", &daq), @@ -1503,8 +1503,8 @@ static void RunMenu( PolarfireTarget* pft_ ) { // pfMenu::Line("SCAN","Take many charge or pedestal runs while changing a single parameter", &daq), pfMenu::Line("QUIT","Back to top menu") }); - - pfMenu menu_expert({ + + pfMenu menu_expert({ pfMenu::Line("OLINK","Optical link functions", &menu_link), pfMenu::Line("WB","Raw wishbone interactions", &menu_wishbone ), pfMenu::Line("I2C","Access the I2C Core", &menu_i2c ), @@ -1517,8 +1517,8 @@ static void RunMenu( PolarfireTarget* pft_ ) { pfMenu::Line("DELAYSCAN","Charge injection delay scan", &tasks ), pfMenu::Line("QUIT","Back to top menu") }); - - pfMenu menu_utop({ + + pfMenu menu_utop({ pfMenu::Line("STATUS","Status summary", &status), pfMenu::Line("TASKS","Various high-level tasks like scans", &menu_tasks ), pfMenu::Line("FAST_CONTROL","Fast Control", &menu_fc ), @@ -1553,7 +1553,7 @@ bool file_exists(const std::string& fname) { void prepareOpts(Rcfile& rcfile) { rcfile.declareVBool("roclinks", "Vector Bool[8] indicating which roc links are active"); - rcfile.declareString("ipbus_map_path", + rcfile.declareString("ipbus_map_path", "Full path to directory containgin IP-bus mapping. Only required for uHal comm."); rcfile.declareString("default_hostname", "Hostname of polarfire to connect to if none are given on the command line"); @@ -1572,7 +1572,7 @@ void prepareOpts(Rcfile& rcfile) { * the usage information is printed and we exit; otherwise, * we continue. * - * The RC files are read from ${PFTOOLRC}, pftoolrc, and ~/.pftoolrc + * The RC files are read from ${PFTOOLRC}, pftoolrc, and ~/.pftoolrc * with priority in that order. * Then the command line parameters are parsed; if not hostname(s) is(are) * provided on the command line, then the 'default_hostname' RC file option @@ -1586,7 +1586,7 @@ void prepareOpts(Rcfile& rcfile) { int main(int argc, char* argv[]) { Rcfile options; prepareOpts(options); - + // print help if (argc == 2 and (!strcmp(argv[1],"-h") or !strcmp(argv[1],"--help"))) { #ifdef PFTOOL_ROGUE @@ -1610,7 +1610,7 @@ int main(int argc, char* argv[]) { #endif printf("Reading RC files from ${PFTOOLRC}, ${CWD}/pftoolrc, ${HOME}/.pftoolrc with priority in this order\n"); options.help(); - + printf("\n"); return 1; } @@ -1623,7 +1623,7 @@ int main(int argc, char* argv[]) { if (file_exists(getenv("PFTOOLRC"))) { options.load(getenv("PFTOOLRC")); } else { - std::cerr << "WARNING: PFTOOLRC=" << getenv("PFTOOLRC") + std::cerr << "WARNING: PFTOOLRC=" << getenv("PFTOOLRC") << " is not loaded because it doesn't exist." << std::endl; } } @@ -1658,7 +1658,7 @@ int main(int argc, char* argv[]) { std::cerr << "Unable to open script file " << argv[i] << std::endl; return 2; } - + std::string line; while (getline(sFile, line)) { // erase whitespace at beginning of line @@ -1675,11 +1675,11 @@ int main(int argc, char* argv[]) { else if (arg=="-u") { isuhal = true; isrogue = false; - } + } else if (arg=="-r") { isrogue = true; isuhal = false; - } + } #endif #endif else { @@ -1724,7 +1724,7 @@ int main(int argc, char* argv[]) { } else { i_host = 0; } - + // initialize connect with Polarfire std::unique_ptr p_pft; try { @@ -1748,13 +1748,13 @@ int main(int argc, char* argv[]) { if (options.contents().has_key("runnumber_file")) last_run_file=options.contents().getString("runnumber_file"); - + if (p_pft) { // prepare the links - if (options.contents().is_vector("roclinks")) { + if (options.contents().is_vector("roclinks")) { std::vector actives=options.contents().getVBool("roclinks"); - for (int ilink=0; - ilinkhcal.elinks().nlinks() and ilinkhcal.elinks().nlinks() and ilinkhcal.elinks().markActive(ilink,actives[ilink]); } @@ -1769,7 +1769,7 @@ int main(int argc, char* argv[]) { return 126; } - if (hostnames.size() > 1) { + if (hostnames.size() > 1) { // menu for that target has been exited, check if user wants to choose another host continue_running = BaseMenu::readline_bool(" Choose a new card/host to connect to ? ", true); } else { @@ -1783,5 +1783,3 @@ int main(int argc, char* argv[]) { } return 0; } - - From 7836dec632bfd81d271c87397ca44eddfc740af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 16:47:07 +0200 Subject: [PATCH 03/21] Move tasks menu to new header --- tool/pftool.cc | 202 ------------------------------------------- tool/pftool_tasks.h | 206 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+), 202 deletions(-) diff --git a/tool/pftool.cc b/tool/pftool.cc index d982815a..87a7dd13 100644 --- a/tool/pftool.cc +++ b/tool/pftool.cc @@ -942,208 +942,6 @@ static void daq( const std::string& cmd, PolarfireTarget* pft ) { } } -/** - * TASK menu commands - * - * ## Commands - * - RESET_POWERUP: execute a series of commands after chip has been power cycled or firmware re-loaded - * - SCANCHARGE : loop over channels and scan a range of a CALIBDAC values, recording only relevant channel points in CSV file - * - * @param[in] cmd command selected from menu - * @param[in] pft active target - */ -static void tasks( const std::string& cmd, PolarfireTarget* pft ) { - pflib::DAQ& daq=pft->hcal.daq(); - - static int low_value=10; - static int high_value=500; - static int steps=10; - static int events_per_step=100; - std::string pagetemplate; - std::string valuename; - std::string modeinfo; - - int nsamples=1; - { - bool multi; - int nextra; - pft->hcal.fc().getMultisampleSetup(multi,nextra); - if (multi) nsamples=nextra+1; - } - - if (cmd=="RESET_POWERUP") { - pft->hcal.fc().resetTransmitter(); - pft->hcal.resyncLoadROC(); - pft->daqHardReset(); - pflib::Elinks& elinks=pft->hcal.elinks(); - elinks.resetHard(); - } - - if (cmd=="SCANCHARGE") { - valuename="CALIB_DAC"; - pagetemplate="REFERENCE_VOLTAGE_%d"; - printf("CALIB_DAC valid range is 0...4095\n"); - low_value=BaseMenu::readline_int("Smallest value of CALIB_DAC?",low_value); - high_value=BaseMenu::readline_int("Largest value of CALIB_DAC?",high_value); - bool is_high_range=BaseMenu::readline_bool("Use HighRange? ",false); - if (is_high_range) modeinfo="HIGHRANGE"; - else modeinfo="LOWRANGE"; - } - /// common stuff for all scans - if (cmd=="SCANCHARGE") { - static const int NUM_ELINK_CHAN=36; - - steps=BaseMenu::readline_int("Number of steps?",steps); - events_per_step=BaseMenu::readline_int("Events per step?",events_per_step); - - time_t t=time(NULL); - struct tm *tm = localtime(&t); - char fname_def_format[1024]; - sprintf(fname_def_format,"scan_%s_%%Y%%m%%d_%%H%%M%%S.csv",valuename.c_str()); - char fname_def[1024]; - strftime(fname_def, sizeof(fname_def), fname_def_format, tm); - - std::string fname=BaseMenu::readline("Filename : ", fname_def); - std::ofstream csv_out=std::ofstream(fname); - - // csv header - csv_out <hcal.elinks().nlinks(); ilink++) { - if (!pft->hcal.elinks().isActive(ilink)) continue; - - int iroc=ilink/2; - for (int ichan=0; ichanhcal.roc(iroc).applyParameter(pagename, "LOWRANGE", 0); - pft->hcal.roc(iroc).applyParameter(pagename, "HIGHRANGE", 0); - } - } - - printf(" Enabling IntCTest...\n"); - - for (int ilink=0; ilinkhcal.elinks().nlinks(); ilink++) { - if (!pft->hcal.elinks().isActive(ilink)) continue; - - int iroc=ilink/2; - char pagename[32]; - snprintf(pagename,32,"REFERENCE_VOLTAGE_%d",(ilink%2)); - // set the value - pft->hcal.roc(iroc).applyParameter(pagename, "INTCTEST", 1); - if (cmd=="SCANCHARGE") { - snprintf(pagename,32,"DIGITAL_HALF_%d",(ilink%2)); - // set the value - pft->hcal.roc(iroc).applyParameter(pagename, "L1OFFSET", 8); - } - } - - //////////////////////////////////////////////////////////// - - for (int step=0; stephcal.elinks().nlinks(); ilink++) { - if (!pft->hcal.elinks().isActive(ilink)) continue; - - int iroc=ilink/2; - char pagename[32]; - snprintf(pagename,32,pagetemplate.c_str(),ilink%2); - // set the value - pft->hcal.roc(iroc).applyParameter(pagename, valuename, value); - } - //////////////////////////////////////////////////////////// - - pft->prepareNewRun(); - - for (int ichan=0; ichanhcal.elinks().nlinks(); ilink++) { - if (!pft->hcal.elinks().isActive(ilink)) continue; - - int iroc=ilink/2; - char pagename[32]; - snprintf(pagename,32,"CHANNEL_%d",(ilink%2)*(NUM_ELINK_CHAN)+ichan); - // set the value - pft->hcal.roc(iroc).applyParameter(pagename, modeinfo, 1); - } - - ////////////////////////////////////////////////////////// - /// Take the expected number of events and save the events - for (int ievt=0; ievtbackend->fc_calibpulse(); - std::vector event = pft->daqReadEvent(); - pft->backend->fc_advance_l1_fifo(); - - - // here we decode the event and store the relevant information only... - pflib::decoding::SuperPacket data(&(event[0]),event.size()); - - for (int ilink=0; ilinkhcal.elinks().nlinks(); ilink++) { - if (!pft->hcal.elinks().isActive(ilink)) continue; - - csv_out << value << ',' << ilink << ',' << ichan << ',' << ievt; - for (int i=0; ihcal.elinks().nlinks(); ilink++) { - if (!pft->hcal.elinks().isActive(ilink)) continue; - - int iroc=ilink/2; - char pagename[32]; - snprintf(pagename,32,"CHANNEL_%d",(ilink%2)*(NUM_ELINK_CHAN)+ichan); - // set the value - pft->hcal.roc(iroc).applyParameter(pagename, modeinfo, 0); - } - - ////////////////////////////////////////////////////////// - } - } - - printf(" Diabling IntCTest...\n"); - - for (int ilink=0; ilinkhcal.elinks().nlinks(); ilink++) { - if (!pft->hcal.elinks().isActive(ilink)) continue; - - int iroc=ilink/2; - char pagename[32]; - snprintf(pagename,32,"REFERENCE_VOLTAGE_%d",(ilink%2)); - // set the value - pft->hcal.roc(iroc).applyParameter(pagename, "INTCTEST", 0); - } - //////////////////////////////////////////////////////////// - } -} /** * Print data words from raw binary file and return them diff --git a/tool/pftool_tasks.h b/tool/pftool_tasks.h index 8a6f6d80..7cd56e76 100644 --- a/tool/pftool_tasks.h +++ b/tool/pftool_tasks.h @@ -1,4 +1,210 @@ #ifndef PFTOOL_TASKS_H #define PFTOOL_TASKS_H +#include "pflib/PolarfireTarget.h" +#include +#include "Menu.h" +#include "pflib/decoding/SuperPacket.h" +/** + * TASK menu commands + * + * ## Commands + * - RESET_POWERUP: execute a series of commands after chip has been power cycled or firmware re-loaded + * - SCANCHARGE : loop over channels and scan a range of a CALIBDAC values, recording only relevant channel points in CSV file + * + * @param[in] cmd command selected from menu + * @param[in] pft active target + */ +static void tasks( const std::string& cmd, pflib::PolarfireTarget* pft ) { + pflib::DAQ& daq=pft->hcal.daq(); + + static int low_value=10; + static int high_value=500; + static int steps=10; + static int events_per_step=100; + std::string pagetemplate; + std::string valuename; + std::string modeinfo; + + int nsamples=1; + { + bool multi; + int nextra; + pft->hcal.fc().getMultisampleSetup(multi,nextra); + if (multi) nsamples=nextra+1; + } + + if (cmd=="RESET_POWERUP") { + pft->hcal.fc().resetTransmitter(); + pft->hcal.resyncLoadROC(); + pft->daqHardReset(); + pflib::Elinks& elinks=pft->hcal.elinks(); + elinks.resetHard(); + } + + if (cmd=="SCANCHARGE") { + valuename="CALIB_DAC"; + pagetemplate="REFERENCE_VOLTAGE_%d"; + printf("CALIB_DAC valid range is 0...4095\n"); + low_value=BaseMenu::readline_int("Smallest value of CALIB_DAC?",low_value); + high_value=BaseMenu::readline_int("Largest value of CALIB_DAC?",high_value); + bool is_high_range=BaseMenu::readline_bool("Use HighRange? ",false); + if (is_high_range) modeinfo="HIGHRANGE"; + else modeinfo="LOWRANGE"; + } + /// common stuff for all scans + if (cmd=="SCANCHARGE") { + static const int NUM_ELINK_CHAN=36; + + steps=BaseMenu::readline_int("Number of steps?",steps); + events_per_step=BaseMenu::readline_int("Events per step?",events_per_step); + + time_t t=time(NULL); + struct tm *tm = localtime(&t); + char fname_def_format[1024]; + sprintf(fname_def_format,"scan_%s_%%Y%%m%%d_%%H%%M%%S.csv",valuename.c_str()); + char fname_def[1024]; + strftime(fname_def, sizeof(fname_def), fname_def_format, tm); + + std::string fname=BaseMenu::readline("Filename : ", fname_def); + std::ofstream csv_out=std::ofstream(fname); + + // csv header + csv_out <hcal.elinks().nlinks(); ilink++) { + if (!pft->hcal.elinks().isActive(ilink)) continue; + + int iroc=ilink/2; + for (int ichan=0; ichanhcal.roc(iroc).applyParameter(pagename, "LOWRANGE", 0); + pft->hcal.roc(iroc).applyParameter(pagename, "HIGHRANGE", 0); + } + } + + printf(" Enabling IntCTest...\n"); + + for (int ilink=0; ilinkhcal.elinks().nlinks(); ilink++) { + if (!pft->hcal.elinks().isActive(ilink)) continue; + + int iroc=ilink/2; + char pagename[32]; + snprintf(pagename,32,"REFERENCE_VOLTAGE_%d",(ilink%2)); + // set the value + pft->hcal.roc(iroc).applyParameter(pagename, "INTCTEST", 1); + if (cmd=="SCANCHARGE") { + snprintf(pagename,32,"DIGITAL_HALF_%d",(ilink%2)); + // set the value + pft->hcal.roc(iroc).applyParameter(pagename, "L1OFFSET", 8); + } + } + + //////////////////////////////////////////////////////////// + + for (int step=0; stephcal.elinks().nlinks(); ilink++) { + if (!pft->hcal.elinks().isActive(ilink)) continue; + + int iroc=ilink/2; + char pagename[32]; + snprintf(pagename,32,pagetemplate.c_str(),ilink%2); + // set the value + pft->hcal.roc(iroc).applyParameter(pagename, valuename, value); + } + //////////////////////////////////////////////////////////// + + pft->prepareNewRun(); + + for (int ichan=0; ichanhcal.elinks().nlinks(); ilink++) { + if (!pft->hcal.elinks().isActive(ilink)) continue; + + int iroc=ilink/2; + char pagename[32]; + snprintf(pagename,32,"CHANNEL_%d",(ilink%2)*(NUM_ELINK_CHAN)+ichan); + // set the value + pft->hcal.roc(iroc).applyParameter(pagename, modeinfo, 1); + } + + ////////////////////////////////////////////////////////// + /// Take the expected number of events and save the events + for (int ievt=0; ievtbackend->fc_calibpulse(); + std::vector event = pft->daqReadEvent(); + pft->backend->fc_advance_l1_fifo(); + + + // here we decode the event and store the relevant information only... + pflib::decoding::SuperPacket data(&(event[0]),event.size()); + + for (int ilink=0; ilinkhcal.elinks().nlinks(); ilink++) { + if (!pft->hcal.elinks().isActive(ilink)) continue; + + csv_out << value << ',' << ilink << ',' << ichan << ',' << ievt; + for (int i=0; ihcal.elinks().nlinks(); ilink++) { + if (!pft->hcal.elinks().isActive(ilink)) continue; + + int iroc=ilink/2; + char pagename[32]; + snprintf(pagename,32,"CHANNEL_%d",(ilink%2)*(NUM_ELINK_CHAN)+ichan); + // set the value + pft->hcal.roc(iroc).applyParameter(pagename, modeinfo, 0); + } + + ////////////////////////////////////////////////////////// + } + } + + printf(" Diabling IntCTest...\n"); + + for (int ilink=0; ilinkhcal.elinks().nlinks(); ilink++) { + if (!pft->hcal.elinks().isActive(ilink)) continue; + + int iroc=ilink/2; + char pagename[32]; + snprintf(pagename,32,"REFERENCE_VOLTAGE_%d",(ilink%2)); + // set the value + pft->hcal.roc(iroc).applyParameter(pagename, "INTCTEST", 0); + } + //////////////////////////////////////////////////////////// + } +} #endif /* PFTOOL_TASKS_H */ From 5407a1918b299985bdcea899cd9fe1c0ca90041a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 16:48:41 +0200 Subject: [PATCH 04/21] Move it to implementation --- tool/pftool_tasks.cc | 194 +++++++++++++++++++++++++++++++++++++++++++ tool/pftool_tasks.h | 192 +----------------------------------------- 2 files changed, 195 insertions(+), 191 deletions(-) diff --git a/tool/pftool_tasks.cc b/tool/pftool_tasks.cc index 4502239c..5e188249 100644 --- a/tool/pftool_tasks.cc +++ b/tool/pftool_tasks.cc @@ -1 +1,195 @@ #include "pftool_tasks.h" + +void tasks( const std::string& cmd, pflib::PolarfireTarget* pft ) +{ + pflib::DAQ& daq=pft->hcal.daq(); + + static int low_value=10; + static int high_value=500; + static int steps=10; + static int events_per_step=100; + std::string pagetemplate; + std::string valuename; + std::string modeinfo; + + int nsamples=1; + { + bool multi; + int nextra; + pft->hcal.fc().getMultisampleSetup(multi,nextra); + if (multi) nsamples=nextra+1; + } + + if (cmd=="RESET_POWERUP") { + pft->hcal.fc().resetTransmitter(); + pft->hcal.resyncLoadROC(); + pft->daqHardReset(); + pflib::Elinks& elinks=pft->hcal.elinks(); + elinks.resetHard(); + } + + if (cmd=="SCANCHARGE") { + valuename="CALIB_DAC"; + pagetemplate="REFERENCE_VOLTAGE_%d"; + printf("CALIB_DAC valid range is 0...4095\n"); + low_value=BaseMenu::readline_int("Smallest value of CALIB_DAC?",low_value); + high_value=BaseMenu::readline_int("Largest value of CALIB_DAC?",high_value); + bool is_high_range=BaseMenu::readline_bool("Use HighRange? ",false); + if (is_high_range) modeinfo="HIGHRANGE"; + else modeinfo="LOWRANGE"; + } + /// common stuff for all scans + if (cmd=="SCANCHARGE") { + static const int NUM_ELINK_CHAN=36; + + steps=BaseMenu::readline_int("Number of steps?",steps); + events_per_step=BaseMenu::readline_int("Events per step?",events_per_step); + + time_t t=time(NULL); + struct tm *tm = localtime(&t); + char fname_def_format[1024]; + sprintf(fname_def_format,"scan_%s_%%Y%%m%%d_%%H%%M%%S.csv",valuename.c_str()); + char fname_def[1024]; + strftime(fname_def, sizeof(fname_def), fname_def_format, tm); + + std::string fname=BaseMenu::readline("Filename : ", fname_def); + std::ofstream csv_out=std::ofstream(fname); + + // csv header + csv_out <hcal.elinks().nlinks(); ilink++) { + if (!pft->hcal.elinks().isActive(ilink)) continue; + + int iroc=ilink/2; + for (int ichan=0; ichanhcal.roc(iroc).applyParameter(pagename, "LOWRANGE", 0); + pft->hcal.roc(iroc).applyParameter(pagename, "HIGHRANGE", 0); + } + } + + printf(" Enabling IntCTest...\n"); + + for (int ilink=0; ilinkhcal.elinks().nlinks(); ilink++) { + if (!pft->hcal.elinks().isActive(ilink)) continue; + + int iroc=ilink/2; + char pagename[32]; + snprintf(pagename,32,"REFERENCE_VOLTAGE_%d",(ilink%2)); + // set the value + pft->hcal.roc(iroc).applyParameter(pagename, "INTCTEST", 1); + if (cmd=="SCANCHARGE") { + snprintf(pagename,32,"DIGITAL_HALF_%d",(ilink%2)); + // set the value + pft->hcal.roc(iroc).applyParameter(pagename, "L1OFFSET", 8); + } + } + + //////////////////////////////////////////////////////////// + + for (int step=0; stephcal.elinks().nlinks(); ilink++) { + if (!pft->hcal.elinks().isActive(ilink)) continue; + + int iroc=ilink/2; + char pagename[32]; + snprintf(pagename,32,pagetemplate.c_str(),ilink%2); + // set the value + pft->hcal.roc(iroc).applyParameter(pagename, valuename, value); + } + //////////////////////////////////////////////////////////// + + pft->prepareNewRun(); + + for (int ichan=0; ichanhcal.elinks().nlinks(); ilink++) { + if (!pft->hcal.elinks().isActive(ilink)) continue; + + int iroc=ilink/2; + char pagename[32]; + snprintf(pagename,32,"CHANNEL_%d",(ilink%2)*(NUM_ELINK_CHAN)+ichan); + // set the value + pft->hcal.roc(iroc).applyParameter(pagename, modeinfo, 1); + } + + ////////////////////////////////////////////////////////// + /// Take the expected number of events and save the events + for (int ievt=0; ievtbackend->fc_calibpulse(); + std::vector event = pft->daqReadEvent(); + pft->backend->fc_advance_l1_fifo(); + + + // here we decode the event and store the relevant information only... + pflib::decoding::SuperPacket data(&(event[0]),event.size()); + + for (int ilink=0; ilinkhcal.elinks().nlinks(); ilink++) { + if (!pft->hcal.elinks().isActive(ilink)) continue; + + csv_out << value << ',' << ilink << ',' << ichan << ',' << ievt; + for (int i=0; ihcal.elinks().nlinks(); ilink++) { + if (!pft->hcal.elinks().isActive(ilink)) continue; + + int iroc=ilink/2; + char pagename[32]; + snprintf(pagename,32,"CHANNEL_%d",(ilink%2)*(NUM_ELINK_CHAN)+ichan); + // set the value + pft->hcal.roc(iroc).applyParameter(pagename, modeinfo, 0); + } + + ////////////////////////////////////////////////////////// + } + } + + printf(" Diabling IntCTest...\n"); + + for (int ilink=0; ilinkhcal.elinks().nlinks(); ilink++) { + if (!pft->hcal.elinks().isActive(ilink)) continue; + + int iroc=ilink/2; + char pagename[32]; + snprintf(pagename,32,"REFERENCE_VOLTAGE_%d",(ilink%2)); + // set the value + pft->hcal.roc(iroc).applyParameter(pagename, "INTCTEST", 0); + } + //////////////////////////////////////////////////////////// + } +} diff --git a/tool/pftool_tasks.h b/tool/pftool_tasks.h index 7cd56e76..58a68bd3 100644 --- a/tool/pftool_tasks.h +++ b/tool/pftool_tasks.h @@ -15,196 +15,6 @@ * @param[in] cmd command selected from menu * @param[in] pft active target */ -static void tasks( const std::string& cmd, pflib::PolarfireTarget* pft ) { - pflib::DAQ& daq=pft->hcal.daq(); - static int low_value=10; - static int high_value=500; - static int steps=10; - static int events_per_step=100; - std::string pagetemplate; - std::string valuename; - std::string modeinfo; - - int nsamples=1; - { - bool multi; - int nextra; - pft->hcal.fc().getMultisampleSetup(multi,nextra); - if (multi) nsamples=nextra+1; - } - - if (cmd=="RESET_POWERUP") { - pft->hcal.fc().resetTransmitter(); - pft->hcal.resyncLoadROC(); - pft->daqHardReset(); - pflib::Elinks& elinks=pft->hcal.elinks(); - elinks.resetHard(); - } - - if (cmd=="SCANCHARGE") { - valuename="CALIB_DAC"; - pagetemplate="REFERENCE_VOLTAGE_%d"; - printf("CALIB_DAC valid range is 0...4095\n"); - low_value=BaseMenu::readline_int("Smallest value of CALIB_DAC?",low_value); - high_value=BaseMenu::readline_int("Largest value of CALIB_DAC?",high_value); - bool is_high_range=BaseMenu::readline_bool("Use HighRange? ",false); - if (is_high_range) modeinfo="HIGHRANGE"; - else modeinfo="LOWRANGE"; - } - /// common stuff for all scans - if (cmd=="SCANCHARGE") { - static const int NUM_ELINK_CHAN=36; - - steps=BaseMenu::readline_int("Number of steps?",steps); - events_per_step=BaseMenu::readline_int("Events per step?",events_per_step); - - time_t t=time(NULL); - struct tm *tm = localtime(&t); - char fname_def_format[1024]; - sprintf(fname_def_format,"scan_%s_%%Y%%m%%d_%%H%%M%%S.csv",valuename.c_str()); - char fname_def[1024]; - strftime(fname_def, sizeof(fname_def), fname_def_format, tm); - - std::string fname=BaseMenu::readline("Filename : ", fname_def); - std::ofstream csv_out=std::ofstream(fname); - - // csv header - csv_out <hcal.elinks().nlinks(); ilink++) { - if (!pft->hcal.elinks().isActive(ilink)) continue; - - int iroc=ilink/2; - for (int ichan=0; ichanhcal.roc(iroc).applyParameter(pagename, "LOWRANGE", 0); - pft->hcal.roc(iroc).applyParameter(pagename, "HIGHRANGE", 0); - } - } - - printf(" Enabling IntCTest...\n"); - - for (int ilink=0; ilinkhcal.elinks().nlinks(); ilink++) { - if (!pft->hcal.elinks().isActive(ilink)) continue; - - int iroc=ilink/2; - char pagename[32]; - snprintf(pagename,32,"REFERENCE_VOLTAGE_%d",(ilink%2)); - // set the value - pft->hcal.roc(iroc).applyParameter(pagename, "INTCTEST", 1); - if (cmd=="SCANCHARGE") { - snprintf(pagename,32,"DIGITAL_HALF_%d",(ilink%2)); - // set the value - pft->hcal.roc(iroc).applyParameter(pagename, "L1OFFSET", 8); - } - } - - //////////////////////////////////////////////////////////// - - for (int step=0; stephcal.elinks().nlinks(); ilink++) { - if (!pft->hcal.elinks().isActive(ilink)) continue; - - int iroc=ilink/2; - char pagename[32]; - snprintf(pagename,32,pagetemplate.c_str(),ilink%2); - // set the value - pft->hcal.roc(iroc).applyParameter(pagename, valuename, value); - } - //////////////////////////////////////////////////////////// - - pft->prepareNewRun(); - - for (int ichan=0; ichanhcal.elinks().nlinks(); ilink++) { - if (!pft->hcal.elinks().isActive(ilink)) continue; - - int iroc=ilink/2; - char pagename[32]; - snprintf(pagename,32,"CHANNEL_%d",(ilink%2)*(NUM_ELINK_CHAN)+ichan); - // set the value - pft->hcal.roc(iroc).applyParameter(pagename, modeinfo, 1); - } - - ////////////////////////////////////////////////////////// - /// Take the expected number of events and save the events - for (int ievt=0; ievtbackend->fc_calibpulse(); - std::vector event = pft->daqReadEvent(); - pft->backend->fc_advance_l1_fifo(); - - - // here we decode the event and store the relevant information only... - pflib::decoding::SuperPacket data(&(event[0]),event.size()); - - for (int ilink=0; ilinkhcal.elinks().nlinks(); ilink++) { - if (!pft->hcal.elinks().isActive(ilink)) continue; - - csv_out << value << ',' << ilink << ',' << ichan << ',' << ievt; - for (int i=0; ihcal.elinks().nlinks(); ilink++) { - if (!pft->hcal.elinks().isActive(ilink)) continue; - - int iroc=ilink/2; - char pagename[32]; - snprintf(pagename,32,"CHANNEL_%d",(ilink%2)*(NUM_ELINK_CHAN)+ichan); - // set the value - pft->hcal.roc(iroc).applyParameter(pagename, modeinfo, 0); - } - - ////////////////////////////////////////////////////////// - } - } - - printf(" Diabling IntCTest...\n"); - - for (int ilink=0; ilinkhcal.elinks().nlinks(); ilink++) { - if (!pft->hcal.elinks().isActive(ilink)) continue; - - int iroc=ilink/2; - char pagename[32]; - snprintf(pagename,32,"REFERENCE_VOLTAGE_%d",(ilink%2)); - // set the value - pft->hcal.roc(iroc).applyParameter(pagename, "INTCTEST", 0); - } - //////////////////////////////////////////////////////////// - } -} +void tasks( const std::string& cmd, pflib::PolarfireTarget* pft ); #endif /* PFTOOL_TASKS_H */ From 6dd529261caf1f51cab0c92360c8ed0702bf5631 Mon Sep 17 00:00:00 2001 From: desk-fish Date: Sat, 9 Apr 2022 18:05:14 +0200 Subject: [PATCH 05/21] Add a header for pftool --- tool/pftool.cc | 31 +------------------------------ tool/pftool.h | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 30 deletions(-) create mode 100644 tool/pftool.h diff --git a/tool/pftool.cc b/tool/pftool.cc index 87a7dd13..87b1f8dd 100644 --- a/tool/pftool.cc +++ b/tool/pftool.cc @@ -1,38 +1,9 @@ +#include "pftool.h" /** * @file pftool.cc File defining the pftool menus and their commands. * * The commands are written into functions corresponding to the menu's name. */ -#include "pftool_tasks.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "pflib/PolarfireTarget.h" -#include "pflib/Compile.h" // for parameter listing -#ifdef PFTOOL_ROGUE -#include "pflib/rogue/RogueWishboneInterface.h" -#endif -#ifdef PFTOOL_UHAL -#include "pflib/uhal/uhalWishboneInterface.h" -#endif -#include "Menu.h" -#include "Rcfile.h" -#include "pflib/decoding/SuperPacket.h" - -/** - * pull the target of our menu into this source file to reduce code - */ -using pflib::PolarfireTarget; /** * Main status of menu diff --git a/tool/pftool.h b/tool/pftool.h new file mode 100644 index 00000000..382b6170 --- /dev/null +++ b/tool/pftool.h @@ -0,0 +1,36 @@ +#ifndef PFTOOL_H +#define PFTOOL_H + + +#include "pftool_tasks.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pflib/PolarfireTarget.h" +#include "pflib/Compile.h" // for parameter listing +#ifdef PFTOOL_ROGUE +#include "pflib/rogue/RogueWishboneInterface.h" +#endif +#ifdef PFTOOL_UHAL +#include "pflib/uhal/uhalWishboneInterface.h" +#endif +#include "Menu.h" +#include "Rcfile.h" +#include "pflib/decoding/SuperPacket.h" + +/** + * pull the target of our menu into this source file to reduce code + */ +using pflib::PolarfireTarget; + +#endif /* PFTOOL_H */ From 8eb5be3d4c58904d4bfc815112887c8d822b0d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 18:29:40 +0200 Subject: [PATCH 06/21] Add a translation unit for the ROC menu --- CMakeLists.txt | 3 ++- tool/pftool.h | 1 + tool/pftool_roc.cc | 1 + tool/pftool_roc.h | 6 ++++++ 4 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tool/pftool_roc.cc create mode 100644 tool/pftool_roc.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 512bd905..be961b71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,7 +55,8 @@ add_executable(pftool tool/pftool.cc tool/Menu.cc tool/Rcfile.cc - tool/pftool_tasks.cc) + tool/pftool_tasks.cc + tool/pftool_roc.cc) target_link_libraries(pftool PRIVATE pflib readline) # don't install test-menu executable! just for Menu developments diff --git a/tool/pftool.h b/tool/pftool.h index 382b6170..75e2bb57 100644 --- a/tool/pftool.h +++ b/tool/pftool.h @@ -3,6 +3,7 @@ #include "pftool_tasks.h" +#include "pftool_roc.h" #include #include #include diff --git a/tool/pftool_roc.cc b/tool/pftool_roc.cc new file mode 100644 index 00000000..d158c5ca --- /dev/null +++ b/tool/pftool_roc.cc @@ -0,0 +1 @@ +#include "pftool_roc.h" diff --git a/tool/pftool_roc.h b/tool/pftool_roc.h new file mode 100644 index 00000000..4fb3e7ed --- /dev/null +++ b/tool/pftool_roc.h @@ -0,0 +1,6 @@ +#ifndef PFTOOL_ROC_H +#define PFTOOL_ROC_H + + + +#endif /* PFTOOL_ROC_H */ From cbd40084440357fbab4756659aadcc7a239a75ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 18:42:37 +0200 Subject: [PATCH 07/21] Move the ROC functionality to a separate TU --- tool/pftool.cc | 132 --------------------------------------------- tool/pftool_roc.cc | 101 ++++++++++++++++++++++++++++++++++ tool/pftool_roc.h | 41 ++++++++++++++ 3 files changed, 142 insertions(+), 132 deletions(-) diff --git a/tool/pftool.cc b/tool/pftool.cc index 87b1f8dd..5f1f4018 100644 --- a/tool/pftool.cc +++ b/tool/pftool.cc @@ -313,138 +313,6 @@ static void elinks( const std::string& cmd, PolarfireTarget* pft ) { } } -/** - * ROC currently being interacted with by user - */ -static int iroc = 0; - -/** - * Simply print the currently selective ROC so that user is aware - * which ROC they are interacting with by default. - * - * @param[in] pft active target (not used) - */ -static void roc_render( PolarfireTarget* pft ) { - printf(" Active ROC: %d\n",iroc); -} - -/** - * ROC menu commands - * - * When necessary, the ROC interaction object pflib::ROC is created - * via pflib::Hcal::roc with the currently active roc. - * - * ## Commands - * - HARDRESET : pflib::Hcal::hardResetROCs - * - SOFTRESET : pflib::Hcal::softResetROC - * - RESYNCLOAD : pflib::Hcal::resyncLoadROC - * - IROC : Change which ROC to focus on - * - CHAN : pflib::ROC::getChannelParameters - * - PAGE : pflib::ROC::readPage - * - PARAM_NAMES : Use pflib::parameters to get list ROC parameter names - * - POKE_REG : pflib::ROC::setValue - * - POKE_PARAM : pflib::ROC::applyParameter - * - LOAD_REG : pflib::PolarfireTarget::loadROCRegisters - * - LOAD_PARAM : pflib::PolarfireTarget::loadROCParameters - * - DUMP : pflib::PolarfireTarget::dumpSettings - * - * @param[in] cmd ROC command - * @param[in] pft active target - */ -static void roc( const std::string& cmd, PolarfireTarget* pft ) { - if (cmd=="HARDRESET") { - pft->hcal.hardResetROCs(); - } - if (cmd=="SOFTRESET") { - iroc=BaseMenu::readline_int("Which ROC to reset [-1 for all]: ",iroc); - pft->hcal.softResetROC(iroc); - } - if (cmd=="RESYNCLOAD") { - iroc=BaseMenu::readline_int("Which ROC to reset [-1 for all]: ",iroc); - pft->hcal.resyncLoadROC(iroc); - } - if (cmd=="IROC") { - iroc=BaseMenu::readline_int("Which ROC to manage: ",iroc); - } - pflib::ROC roc=pft->hcal.roc(iroc); - if (cmd=="CHAN") { - int chan=BaseMenu::readline_int("Which channel? ",0); - std::vector v=roc.getChannelParameters(chan); - for (int i=0; i v=roc.readPage(page,len); - for (int i=0; i param_names = pflib::parameters(p); - for (const std::string& pn : param_names) { - std::cout << pn << "\n"; - } - std::cout << std::endl; - } - if (cmd=="POKE_REG") { - int page=BaseMenu::readline_int("Which page? ",0); - int entry=BaseMenu::readline_int("Offset: ",0); - int value=BaseMenu::readline_int("New value: "); - - roc.setValue(page,entry,value); - } - if (cmd=="POKE"||cmd=="POKE_PARAM") { - std::string page = BaseMenu::readline("Page: ", "Global_Analog_0"); - std::string param = BaseMenu::readline("Parameter: "); - int val = BaseMenu::readline_int("New value: "); - - roc.applyParameter(page, param, val); - } - if (cmd=="LOAD_REG") { - std::cout << - "\n" - " --- This command expects a CSV file with columns [page,offset,value].\n" - << std::flush; - std::string fname = BaseMenu::readline("Filename: "); - pft->loadROCRegisters(iroc,fname); - } - if (cmd=="LOAD"||cmd=="LOAD_PARAM") { - std::cout << - "\n" - " --- This command expects a YAML file with page names, parameter names and their values.\n" - << std::flush; - std::string fname = BaseMenu::readline("Filename: "); - bool prepend_defaults = BaseMenu::readline_bool("Update all parameter values on the chip using the defaults in the manual for any values not provided? ", false); - pft->loadROCParameters(iroc,fname,prepend_defaults); - } - if (cmd=="DEFAULT_PARAMS") { - pft->loadDefaultROCParameters(); - } - if (cmd=="DUMP") { - std::string fname_def_format = "hgcroc_"+std::to_string(iroc)+"_settings_%Y%m%d_%H%M%S.yaml"; - - time_t t = time(NULL) -; struct tm *tm = localtime(&t); - - char fname_def[64]; - strftime(fname_def, sizeof(fname_def), fname_def_format.c_str(), tm); - - std::string fname = BaseMenu::readline("Filename: ", fname_def); - bool decompile = BaseMenu::readline_bool("Decompile register values? ",true); - pft->dumpSettings(iroc,fname,decompile); - } -} /** * Fast Control (FC) menu commands diff --git a/tool/pftool_roc.cc b/tool/pftool_roc.cc index d158c5ca..cbbe16be 100644 --- a/tool/pftool_roc.cc +++ b/tool/pftool_roc.cc @@ -1 +1,102 @@ #include "pftool_roc.h" +int iroc = 0; +void roc_render( PolarfireTarget* pft ) { + printf(" Active ROC: %d\n",iroc); +} + + +void roc( const std::string& cmd, PolarfireTarget* pft ) +{ + if (cmd=="HARDRESET") { + pft->hcal.hardResetROCs(); + } + if (cmd=="SOFTRESET") { + iroc=BaseMenu::readline_int("Which ROC to reset [-1 for all]: ",iroc); + pft->hcal.softResetROC(iroc); + } + if (cmd=="RESYNCLOAD") { + iroc=BaseMenu::readline_int("Which ROC to reset [-1 for all]: ",iroc); + pft->hcal.resyncLoadROC(iroc); + } + if (cmd=="IROC") { + iroc=BaseMenu::readline_int("Which ROC to manage: ",iroc); + } + pflib::ROC roc=pft->hcal.roc(iroc); + if (cmd=="CHAN") { + int chan=BaseMenu::readline_int("Which channel? ",0); + std::vector v=roc.getChannelParameters(chan); + for (int i=0; i v=roc.readPage(page,len); + for (int i=0; i param_names = pflib::parameters(p); + for (const std::string& pn : param_names) { + std::cout << pn << "\n"; + } + std::cout << std::endl; + } + if (cmd=="POKE_REG") { + int page=BaseMenu::readline_int("Which page? ",0); + int entry=BaseMenu::readline_int("Offset: ",0); + int value=BaseMenu::readline_int("New value: "); + + roc.setValue(page,entry,value); + } + if (cmd=="POKE"||cmd=="POKE_PARAM") { + std::string page = BaseMenu::readline("Page: ", "Global_Analog_0"); + std::string param = BaseMenu::readline("Parameter: "); + int val = BaseMenu::readline_int("New value: "); + + roc.applyParameter(page, param, val); + } + if (cmd=="LOAD_REG") { + std::cout << + "\n" + " --- This command expects a CSV file with columns [page,offset,value].\n" + << std::flush; + std::string fname = BaseMenu::readline("Filename: "); + pft->loadROCRegisters(iroc,fname); + } + if (cmd=="LOAD"||cmd=="LOAD_PARAM") { + std::cout << + "\n" + " --- This command expects a YAML file with page names, parameter names and their values.\n" + << std::flush; + std::string fname = BaseMenu::readline("Filename: "); + bool prepend_defaults = BaseMenu::readline_bool("Update all parameter values on the chip using the defaults in the manual for any values not provided? ", false); + pft->loadROCParameters(iroc,fname,prepend_defaults); + } + if (cmd=="DEFAULT_PARAMS") { + pft->loadDefaultROCParameters(); + } + if (cmd=="DUMP") { + std::string fname_def_format = "hgcroc_"+std::to_string(iroc)+"_settings_%Y%m%d_%H%M%S.yaml"; + + time_t t = time(NULL) +; struct tm *tm = localtime(&t); + + char fname_def[64]; + strftime(fname_def, sizeof(fname_def), fname_def_format.c_str(), tm); + + std::string fname = BaseMenu::readline("Filename: ", fname_def); + bool decompile = BaseMenu::readline_bool("Decompile register values? ",true); + pft->dumpSettings(iroc,fname,decompile); + } +} diff --git a/tool/pftool_roc.h b/tool/pftool_roc.h index 4fb3e7ed..4f2dfa8c 100644 --- a/tool/pftool_roc.h +++ b/tool/pftool_roc.h @@ -1,6 +1,47 @@ #ifndef PFTOOL_ROC_H #define PFTOOL_ROC_H +#include "Menu.h" +#include "pflib/PolarfireTarget.h" +#include "pflib/Compile.h" +using pflib::PolarfireTarget; +/** + * ROC currently being interacted with by user + */ +extern int iroc; +/** + * Simply print the currently selective ROC so that user is aware + * which ROC they are interacting with by default. + * + * @param[in] pft active target (not used) + */ +void roc_render( PolarfireTarget* pft ); + +/** + * ROC menu commands + * + * When necessary, the ROC interaction object pflib::ROC is created + * via pflib::Hcal::roc with the currently active roc. + * + * ## Commands + * - HARDRESET : pflib::Hcal::hardResetROCs + * - SOFTRESET : pflib::Hcal::softResetROC + * - RESYNCLOAD : pflib::Hcal::resyncLoadROC + * - IROC : Change which ROC to focus on + * - CHAN : pflib::ROC::getChannelParameters + * - PAGE : pflib::ROC::readPage + * - PARAM_NAMES : Use pflib::parameters to get list ROC parameter names + * - POKE_REG : pflib::ROC::setValue + * - POKE_PARAM : pflib::ROC::applyParameter + * - LOAD_REG : pflib::PolarfireTarget::loadROCRegisters + * - LOAD_PARAM : pflib::PolarfireTarget::loadROCParameters + * - DUMP : pflib::PolarfireTarget::dumpSettings + * + * @param[in] cmd ROC command + * @param[in] pft active target + */ +void roc( const std::string& cmd, PolarfireTarget* pft ); + #endif /* PFTOOL_ROC_H */ From d62d6592506e9bee5998dde85af931798648a554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 18:48:22 +0200 Subject: [PATCH 08/21] Add a DAQ menu TU --- CMakeLists.txt | 3 ++- tool/pftool.h | 1 + tool/pftool_daq.cc | 1 + tool/pftool_daq.h | 7 +++++++ 4 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 tool/pftool_daq.cc create mode 100644 tool/pftool_daq.h diff --git a/CMakeLists.txt b/CMakeLists.txt index be961b71..076f480c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,7 +56,8 @@ add_executable(pftool tool/Menu.cc tool/Rcfile.cc tool/pftool_tasks.cc - tool/pftool_roc.cc) + tool/pftool_roc.cc + tool/pftool_daq.cc) target_link_libraries(pftool PRIVATE pflib readline) # don't install test-menu executable! just for Menu developments diff --git a/tool/pftool.h b/tool/pftool.h index 75e2bb57..26f7886d 100644 --- a/tool/pftool.h +++ b/tool/pftool.h @@ -4,6 +4,7 @@ #include "pftool_tasks.h" #include "pftool_roc.h" +#include "pftool_daq.h" #include #include #include diff --git a/tool/pftool_daq.cc b/tool/pftool_daq.cc new file mode 100644 index 00000000..3e0adb1c --- /dev/null +++ b/tool/pftool_daq.cc @@ -0,0 +1 @@ +#include "pftool_daq.h" diff --git a/tool/pftool_daq.h b/tool/pftool_daq.h new file mode 100644 index 00000000..d5ccd6d9 --- /dev/null +++ b/tool/pftool_daq.h @@ -0,0 +1,7 @@ +#ifndef PFTOOL_DAQ_H +#define PFTOOL_DAQ_H +#include "Menu.h" +#include "pflib/PolarfireTarget.h" + + +#endif /* PFTOOL_DAQ_H */ From 058040af1553e463659a8c0cb4b20158443bf605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 18:55:36 +0200 Subject: [PATCH 09/21] move DAQ menu to separate TU --- tool/pftool.cc | 246 --------------------------------------------- tool/pftool_daq.cc | 230 ++++++++++++++++++++++++++++++++++++++++++ tool/pftool_daq.h | 35 +++++++ 3 files changed, 265 insertions(+), 246 deletions(-) diff --git a/tool/pftool.cc b/tool/pftool.cc index 5f1f4018..496aee0d 100644 --- a/tool/pftool.cc +++ b/tool/pftool.cc @@ -533,254 +533,8 @@ static void daq_setup( const std::string& cmd, PolarfireTarget* pft ) { } -static std::string last_run_file=".last_run_file"; -static std::string start_dma_cmd=""; -static std::string stop_dma_cmd=""; -/** - * DAQ menu commands, DOES NOT include sub-menu commands - * - * ## Commands - * - STATUS : pflib::PolarfireTarget::daqStatus - * and pflib::rogue::RogueWishboneInterface::daq_dma_status if connected in that manner - * - RESET : pflib::PolarfireTarget::daqSoftReset - * - HARD_RESET : pflib::PolarfireTarget::daqHardReset - * - READ : pflib::PolarfireTarget::daqReadDirect with option to save output to file - * - PEDESTAL : pflib::PolarfireTarget::prepareNewRun and then send an L1A trigger with - * pflib::Backend::fc_sendL1A and collect events with pflib::PolarfireTarget::daqReadEvent - * for the input number of events - * - CHARGE : same as PEDESTAL but using pflib::Backend::fc_calibpulse instead of direct L1A - * - SCAN : do a PEDESTAL (or CHARGE)-equivalent for each value of - * an input parameter with an input min, max, and step - * - * @param[in] cmd command selected from menu - * @param[in] pft active target - */ -static void daq( const std::string& cmd, PolarfireTarget* pft ) { - pflib::DAQ& daq=pft->hcal.daq(); - - // default is non-DMA readout - bool dma_enabled=false; - auto daq_run = [&](const std::string& cmd // PEDESTAL, CHARGE, or no trigger - , int run // not used in this implementation of daq - , int nevents // number of events to collect - , int rate // not used in this implementation of daq - , const std::string& fname // file to write to (appended) - ) { - std::unique_ptr fp{fopen(fname.c_str(),"a"),&fclose}; - timeval tv0, tvi; - - gettimeofday(&tv0,0); - - for (int ievt=0; ievtbackend->fc_sendL1A(); - if (cmd=="CHARGE") - pft->backend->fc_calibpulse(); - - gettimeofday(&tvi,0); - double runsec=(tvi.tv_sec-tv0.tv_sec)+(tvi.tv_usec-tvi.tv_usec)/1e6; - // double ratenow=(ievt+1)/runsec; - double targettime=(ievt+1.0)/rate; // what I'd like the rate to be - int usec_ahead=int((targettime-runsec)*1e6); - //printf("Sleeping %f %f %d\n",runsec,targettime,usec_ahead); - if (usec_ahead>100) { // if we are running fast... - usleep(usec_ahead); - // printf("Sleeping %d\n",usec_ahead); - } - - std::vector event = pft->daqReadEvent(); - pft->backend->fc_advance_l1_fifo(); - fwrite(&(event[0]),sizeof(uint32_t),event.size(),fp.get()); - } - }; - -#ifdef PFTOOL_ROGUE - auto rwbi=dynamic_cast(pft->wb); - uint8_t fpgaid_i; - if (rwbi) { - uint8_t samples_per_event; - rwbi->daq_get_dma_setup(fpgaid_i,samples_per_event, dma_enabled); - } -#endif - - if (cmd=="STATUS") { - pft->daqStatus(std::cout); -#ifdef PFTOOL_ROGUE - auto rwbi=dynamic_cast(pft->wb); - if (rwbi) { - printf("DMA : %s Status=%08x\n",(dma_enabled)?("ENABLED"):("DISABLED"),rwbi->daq_dma_status()); - } -#endif - } - if (cmd=="RESET") { - pft->daqSoftReset(); - } - if (cmd=="HARD_RESET") { - pft->daqHardReset(); - } - if (cmd=="READ") { - std::vector buffer = pft->daqReadDirect(); - for (size_t i=0; ibackend->daq_setup_event_tag(run,gmtm->tm_mday,gmtm->tm_mon+1,gmtm->tm_hour,gmtm->tm_min); - - // reset various counters - pft->prepareNewRun(); - - // start DMA, if that's what we're doing... - if (dma_enabled) rwbi->daq_dma_dest(fname); - - // enable external triggers - pft->backend->fc_enables(true,true,false); - - int ievent=0, wasievent=0; - while (ieventbackend->fc_read_counters(spill,occ,occ_max,ievent,vetoed); - if (ievent>wasievent) { - printf("...Now read %d events\n",ievent); - wasievent=ievent; - } else { - sleep(1); - } - } else { - bool full, empty; - int samples, esize; - do { - pft->backend->daq_status(full, empty, samples, esize); - } while (empty); - printf("%d: %d samples waiting for readout...\n",ievent,samples); - - if (f) { - std::vector event = pft->daqReadEvent(); - fwrite(&(event[0]),sizeof(uint32_t),event.size(),f); - } - pft->backend->fc_advance_l1_fifo(); - - ievent++; - } - } - - // disable external triggers - pft->backend->fc_enables(false,true,false); - - if (f) fclose(f); - - if (dma_enabled) rwbi->daq_dma_close(); - - } - if (cmd=="PEDESTAL" || cmd=="CHARGE") { - std::string fname_def_format = "pedestal_%Y%m%d_%H%M%S.raw"; - if (cmd=="CHARGE") fname_def_format = "charge_%Y%m%d_%H%M%S.raw"; - - time_t t = time(NULL); - struct tm *tm = localtime(&t); - - char fname_def[64]; - strftime(fname_def, sizeof(fname_def), fname_def_format.c_str(), tm); - - int run=BaseMenu::readline_int("Run number? ",run); - int nevents=BaseMenu::readline_int("How many events? ", 100); - static int rate=100; - rate=BaseMenu::readline_int("Readout rate? (Hz) ",rate); - std::string fname=BaseMenu::readline("Filename : ", fname_def); - - pft->prepareNewRun(); - -#ifdef PFTOOL_ROGUE - if (dma_enabled) { - rwbi->daq_dma_dest(fname); - rwbi->daq_dma_run(cmd,run,nevents,rate); - rwbi->daq_dma_close(); - } else -#endif - { - daq_run(cmd,run,nevents,rate,fname); - } - } - /** Deprecated by new TASK menu */ - if (cmd=="SCAN"){ - std::string pagename=BaseMenu::readline("Sub-block (aka Page) name : "); - std::string valuename=BaseMenu::readline("Value (aka Parameter) name : "); - int iroc=BaseMenu::readline_int("Which ROC : "); - int minvalue=BaseMenu::readline_int("Minimum value : "); - int maxvalue=BaseMenu::readline_int("Maximum value : "); - int step=BaseMenu::readline_int("Step : "); - int nevents=BaseMenu::readline_int("Events per step : ", 10); - int run=BaseMenu::readline_int("Run number? ",run); - static int rate=100; - rate=BaseMenu::readline_int("Readout rate? (Hz) ",rate); - std::string fname=BaseMenu::readline("Filename : "); - bool charge = BaseMenu::readline_bool("Do a charge injection for each event rather than simple L1A?",false); - std::string trigtype = "PEDESTAL"; - if (charge) trigtype = "CHARGE"; - - pft->prepareNewRun(); - - for(int value = minvalue; value <= maxvalue; value += step){ - pft->hcal.roc(iroc).applyParameter(pagename, valuename, value); -#ifdef PFTOOL_ROGUE - if (dma_enabled) { - rwbi->daq_dma_dest(fname); - rwbi->daq_dma_run(trigtype,run,nevents,rate); - rwbi->daq_dma_close(); - } else -#endif - { - daq_run(trigtype,run,nevents,rate,fname); - } - } - } -} - /** * Print data words from raw binary file and return them diff --git a/tool/pftool_daq.cc b/tool/pftool_daq.cc index 3e0adb1c..1b6a9fed 100644 --- a/tool/pftool_daq.cc +++ b/tool/pftool_daq.cc @@ -1 +1,231 @@ #include "pftool_daq.h" + + + +std::string last_run_file=".last_run_file"; +std::string start_dma_cmd=""; +std::string stop_dma_cmd=""; +void daq( const std::string& cmd, PolarfireTarget* pft ) +{ + pflib::DAQ& daq=pft->hcal.daq(); + + // default is non-DMA readout + bool dma_enabled=false; + auto daq_run = [&](const std::string& cmd // PEDESTAL, CHARGE, or no trigger + , int run // not used in this implementation of daq + , int nevents // number of events to collect + , int rate // not used in this implementation of daq + , const std::string& fname // file to write to (appended) + ) { + std::unique_ptr fp{fopen(fname.c_str(),"a"),&fclose}; + timeval tv0, tvi; + + gettimeofday(&tv0,0); + + for (int ievt=0; ievtbackend->fc_sendL1A(); + if (cmd=="CHARGE") + pft->backend->fc_calibpulse(); + + gettimeofday(&tvi,0); + double runsec=(tvi.tv_sec-tv0.tv_sec)+(tvi.tv_usec-tvi.tv_usec)/1e6; + // double ratenow=(ievt+1)/runsec; + double targettime=(ievt+1.0)/rate; // what I'd like the rate to be + int usec_ahead=int((targettime-runsec)*1e6); + //printf("Sleeping %f %f %d\n",runsec,targettime,usec_ahead); + if (usec_ahead>100) { // if we are running fast... + usleep(usec_ahead); + // printf("Sleeping %d\n",usec_ahead); + } + + std::vector event = pft->daqReadEvent(); + pft->backend->fc_advance_l1_fifo(); + fwrite(&(event[0]),sizeof(uint32_t),event.size(),fp.get()); + } + }; + +#ifdef PFTOOL_ROGUE + auto rwbi=dynamic_cast(pft->wb); + uint8_t fpgaid_i; + if (rwbi) { + uint8_t samples_per_event; + rwbi->daq_get_dma_setup(fpgaid_i,samples_per_event, dma_enabled); + } +#endif + + if (cmd=="STATUS") { + pft->daqStatus(std::cout); +#ifdef PFTOOL_ROGUE + auto rwbi=dynamic_cast(pft->wb); + if (rwbi) { + printf("DMA : %s Status=%08x\n",(dma_enabled)?("ENABLED"):("DISABLED"),rwbi->daq_dma_status()); + } +#endif + } + if (cmd=="RESET") { + pft->daqSoftReset(); + } + if (cmd=="HARD_RESET") { + pft->daqHardReset(); + } + if (cmd=="READ") { + std::vector buffer = pft->daqReadDirect(); + for (size_t i=0; ibackend->daq_setup_event_tag(run,gmtm->tm_mday,gmtm->tm_mon+1,gmtm->tm_hour,gmtm->tm_min); + + // reset various counters + pft->prepareNewRun(); + + // start DMA, if that's what we're doing... + if (dma_enabled) rwbi->daq_dma_dest(fname); + + // enable external triggers + pft->backend->fc_enables(true,true,false); + + int ievent=0, wasievent=0; + while (ieventbackend->fc_read_counters(spill,occ,occ_max,ievent,vetoed); + if (ievent>wasievent) { + printf("...Now read %d events\n",ievent); + wasievent=ievent; + } else { + sleep(1); + } + } else { + bool full, empty; + int samples, esize; + do { + pft->backend->daq_status(full, empty, samples, esize); + } while (empty); + printf("%d: %d samples waiting for readout...\n",ievent,samples); + + if (f) { + std::vector event = pft->daqReadEvent(); + fwrite(&(event[0]),sizeof(uint32_t),event.size(),f); + } + pft->backend->fc_advance_l1_fifo(); + + ievent++; + } + } + + // disable external triggers + pft->backend->fc_enables(false,true,false); + + if (f) fclose(f); + + if (dma_enabled) rwbi->daq_dma_close(); + + } + if (cmd=="PEDESTAL" || cmd=="CHARGE") { + std::string fname_def_format = "pedestal_%Y%m%d_%H%M%S.raw"; + if (cmd=="CHARGE") fname_def_format = "charge_%Y%m%d_%H%M%S.raw"; + + time_t t = time(NULL); + struct tm *tm = localtime(&t); + + char fname_def[64]; + strftime(fname_def, sizeof(fname_def), fname_def_format.c_str(), tm); + + int run=BaseMenu::readline_int("Run number? ",run); + int nevents=BaseMenu::readline_int("How many events? ", 100); + static int rate=100; + rate=BaseMenu::readline_int("Readout rate? (Hz) ",rate); + std::string fname=BaseMenu::readline("Filename : ", fname_def); + + pft->prepareNewRun(); + +#ifdef PFTOOL_ROGUE + if (dma_enabled) { + rwbi->daq_dma_dest(fname); + rwbi->daq_dma_run(cmd,run,nevents,rate); + rwbi->daq_dma_close(); + } else +#endif + { + daq_run(cmd,run,nevents,rate,fname); + } + } + /** Deprecated by new TASK menu */ + if (cmd=="SCAN"){ + std::string pagename=BaseMenu::readline("Sub-block (aka Page) name : "); + std::string valuename=BaseMenu::readline("Value (aka Parameter) name : "); + int iroc=BaseMenu::readline_int("Which ROC : "); + int minvalue=BaseMenu::readline_int("Minimum value : "); + int maxvalue=BaseMenu::readline_int("Maximum value : "); + int step=BaseMenu::readline_int("Step : "); + int nevents=BaseMenu::readline_int("Events per step : ", 10); + int run=BaseMenu::readline_int("Run number? ",run); + static int rate=100; + rate=BaseMenu::readline_int("Readout rate? (Hz) ",rate); + std::string fname=BaseMenu::readline("Filename : "); + bool charge = BaseMenu::readline_bool("Do a charge injection for each event rather than simple L1A?",false); + std::string trigtype = "PEDESTAL"; + if (charge) trigtype = "CHARGE"; + + pft->prepareNewRun(); + + for(int value = minvalue; value <= maxvalue; value += step){ + pft->hcal.roc(iroc).applyParameter(pagename, valuename, value); +#ifdef PFTOOL_ROGUE + if (dma_enabled) { + rwbi->daq_dma_dest(fname); + rwbi->daq_dma_run(trigtype,run,nevents,rate); + rwbi->daq_dma_close(); + } else +#endif + { + daq_run(trigtype,run,nevents,rate,fname); + } + } + } +} diff --git a/tool/pftool_daq.h b/tool/pftool_daq.h index d5ccd6d9..3e28e29e 100644 --- a/tool/pftool_daq.h +++ b/tool/pftool_daq.h @@ -2,6 +2,41 @@ #define PFTOOL_DAQ_H #include "Menu.h" #include "pflib/PolarfireTarget.h" +#include +#include +#include +#ifdef PFTOOL_ROGUE +#include "pflib/rogue/RogueWishboneInterface.h" +#endif +#ifdef PFTOOL_UHAL +#include "pflib/uhal/uhalWishboneInterface.h" +#endif +using pflib::PolarfireTarget; + +extern std::string last_run_file; +extern std::string start_dma_cmd; +extern std::string stop_dma_cmd; + +/** + * DAQ menu commands, DOES NOT include sub-menu commands + * + * ## Commands + * - STATUS : pflib::PolarfireTarget::daqStatus + * and pflib::rogue::RogueWishboneInterface::daq_dma_status if connected in that manner + * - RESET : pflib::PolarfireTarget::daqSoftReset + * - HARD_RESET : pflib::PolarfireTarget::daqHardReset + * - READ : pflib::PolarfireTarget::daqReadDirect with option to save output to file + * - PEDESTAL : pflib::PolarfireTarget::prepareNewRun and then send an L1A trigger with + * pflib::Backend::fc_sendL1A and collect events with pflib::PolarfireTarget::daqReadEvent + * for the input number of events + * - CHARGE : same as PEDESTAL but using pflib::Backend::fc_calibpulse instead of direct L1A + * - SCAN : do a PEDESTAL (or CHARGE)-equivalent for each value of + * an input parameter with an input min, max, and step + * + * @param[in] cmd command selected from menu + * @param[in] pft active target + */ +void daq( const std::string& cmd, PolarfireTarget* pft ); #endif /* PFTOOL_DAQ_H */ From 5ccc588f817a1d64b82153ad00e10ca451b013c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 19:36:12 +0200 Subject: [PATCH 10/21] Add a TU for I2C --- CMakeLists.txt | 3 ++- tool/pftool.h | 2 +- tool/pftool_i2c.cc | 1 + tool/pftool_i2c.h | 8 ++++++++ 4 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 tool/pftool_i2c.cc create mode 100644 tool/pftool_i2c.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 076f480c..cc928a94 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,8 @@ add_executable(pftool tool/Rcfile.cc tool/pftool_tasks.cc tool/pftool_roc.cc - tool/pftool_daq.cc) + tool/pftool_daq.cc + tool/pftool_i2c.cc) target_link_libraries(pftool PRIVATE pflib readline) # don't install test-menu executable! just for Menu developments diff --git a/tool/pftool.h b/tool/pftool.h index 26f7886d..fceb71e7 100644 --- a/tool/pftool.h +++ b/tool/pftool.h @@ -1,7 +1,7 @@ #ifndef PFTOOL_H #define PFTOOL_H - +#include "pftool_i2c.h" #include "pftool_tasks.h" #include "pftool_roc.h" #include "pftool_daq.h" diff --git a/tool/pftool_i2c.cc b/tool/pftool_i2c.cc new file mode 100644 index 00000000..43606467 --- /dev/null +++ b/tool/pftool_i2c.cc @@ -0,0 +1 @@ +#include "pftool_i2c.h" diff --git a/tool/pftool_i2c.h b/tool/pftool_i2c.h new file mode 100644 index 00000000..a6f7bcb0 --- /dev/null +++ b/tool/pftool_i2c.h @@ -0,0 +1,8 @@ +#ifndef PFTOOL_I2C_H +#define PFTOOL_I2C_H +#include "Menu.h" +#include "pflib/PolarfireTarget.h" +using pflib::PolarfireTarget; + + +#endif /* PFTOOL_I2C_H */ From a6ebbe4801a9c26db30c6ec8c3a0cdc26efeb4ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 19:40:15 +0200 Subject: [PATCH 11/21] Rename new TU to expert --- CMakeLists.txt | 2 +- tool/pftool.cc | 76 ------------------------------------------- tool/pftool_expert.cc | 63 +++++++++++++++++++++++++++++++++++ tool/pftool_expert.h | 25 ++++++++++++++ tool/pftool_i2c.cc | 1 - tool/pftool_i2c.h | 8 ----- 6 files changed, 89 insertions(+), 86 deletions(-) create mode 100644 tool/pftool_expert.cc create mode 100644 tool/pftool_expert.h delete mode 100644 tool/pftool_i2c.cc delete mode 100644 tool/pftool_i2c.h diff --git a/CMakeLists.txt b/CMakeLists.txt index cc928a94..f3373c0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,7 @@ add_executable(pftool tool/pftool_tasks.cc tool/pftool_roc.cc tool/pftool_daq.cc - tool/pftool_i2c.cc) + tool/pftool_expert.cc) target_link_libraries(pftool PRIVATE pflib readline) # don't install test-menu executable! just for Menu developments diff --git a/tool/pftool.cc b/tool/pftool.cc index 496aee0d..a4dc92d4 100644 --- a/tool/pftool.cc +++ b/tool/pftool.cc @@ -73,82 +73,6 @@ static void wb( const std::string& cmd, PolarfireTarget* pft ) { } } -/** - * Direct I2C commands - * - * We construct a raw I2C interface by passing the wishbone from the target - * into the pflib::I2C class. - * - * ## Commands - * - BUS : pflib::I2C::set_active_bus, default retrieved by pflib::I2C::get_active_bus - * - WRITE : pflib::I2C::write_byte after passing 1000 to pflib::I2C::set_bus_speed - * - READ : pflib::I2C::read_byte after passing 100 to pflib::I2C::set_bus_speed - * - MULTIREAD : pflib::I2C::general_write_read - * - MULTIWRITE : pflib::I2C::general_write_read - * - * @param[in] cmd I2C command - * @param[in] pft active target - */ -static void i2c( const std::string& cmd, PolarfireTarget* pft ) { - static uint32_t addr=0; - static int waddrlen=1; - static int i2caddr=0; - pflib::I2C i2c(pft->wb); - - if (cmd=="BUS") { - int ibus=i2c.get_active_bus(); - ibus=BaseMenu::readline_int("Bus to make active",ibus); - i2c.set_active_bus(ibus); - } - if (cmd=="WRITE") { - i2caddr=BaseMenu::readline_int("I2C Target ",i2caddr); - uint32_t val=BaseMenu::readline_int("Value ",0); - i2c.set_bus_speed(1000); - i2c.write_byte(i2caddr,val); - } - if (cmd=="READ") { - i2caddr=BaseMenu::readline_int("I2C Target",i2caddr); - i2c.set_bus_speed(100); - uint8_t val=i2c.read_byte(i2caddr); - printf("%02x : %02x\n",i2caddr,val); - } - if (cmd=="MULTIREAD") { - i2caddr=BaseMenu::readline_int("I2C Target",i2caddr); - waddrlen=BaseMenu::readline_int("Read address length",waddrlen); - std::vector waddr; - if (waddrlen>0) { - addr=BaseMenu::readline_int("Read address",addr); - for (int i=0; i>8); - } - } - int len=BaseMenu::readline_int("Read length",1); - std::vector data=i2c.general_write_read(i2caddr,waddr); - for (size_t i=0; i wdata; - if (waddrlen>0) { - addr=BaseMenu::readline_int("Write address",addr); - for (int i=0; i>8); - } - } - int len=BaseMenu::readline_int("Write data length",1); - for (int j=0; jwb); + + if (cmd=="BUS") { + int ibus=i2c.get_active_bus(); + ibus=BaseMenu::readline_int("Bus to make active",ibus); + i2c.set_active_bus(ibus); + } + if (cmd=="WRITE") { + i2caddr=BaseMenu::readline_int("I2C Target ",i2caddr); + uint32_t val=BaseMenu::readline_int("Value ",0); + i2c.set_bus_speed(1000); + i2c.write_byte(i2caddr,val); + } + if (cmd=="READ") { + i2caddr=BaseMenu::readline_int("I2C Target",i2caddr); + i2c.set_bus_speed(100); + uint8_t val=i2c.read_byte(i2caddr); + printf("%02x : %02x\n",i2caddr,val); + } + if (cmd=="MULTIREAD") { + i2caddr=BaseMenu::readline_int("I2C Target",i2caddr); + waddrlen=BaseMenu::readline_int("Read address length",waddrlen); + std::vector waddr; + if (waddrlen>0) { + addr=BaseMenu::readline_int("Read address",addr); + for (int i=0; i>8); + } + } + int len=BaseMenu::readline_int("Read length",1); + std::vector data=i2c.general_write_read(i2caddr,waddr); + for (size_t i=0; i wdata; + if (waddrlen>0) { + addr=BaseMenu::readline_int("Write address",addr); + for (int i=0; i>8); + } + } + int len=BaseMenu::readline_int("Write data length",1); + for (int j=0; j Date: Sat, 9 Apr 2022 19:41:00 +0200 Subject: [PATCH 12/21] Missed one #include --- tool/pftool.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/pftool.h b/tool/pftool.h index fceb71e7..17e77358 100644 --- a/tool/pftool.h +++ b/tool/pftool.h @@ -1,7 +1,7 @@ #ifndef PFTOOL_H #define PFTOOL_H -#include "pftool_i2c.h" +#include "pftool_expert.h" #include "pftool_tasks.h" #include "pftool_roc.h" #include "pftool_daq.h" From a6627704cd7b4ff3578aefe5a94cef42b787b3e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 19:42:11 +0200 Subject: [PATCH 13/21] Move wishbone functionality to expert region --- tool/pftool.cc | 51 ------------------------------------------- tool/pftool_expert.cc | 38 +++++++++++++++++++++++++++++++- tool/pftool_expert.h | 26 +++++++++++++++++++--- 3 files changed, 60 insertions(+), 55 deletions(-) diff --git a/tool/pftool.cc b/tool/pftool.cc index a4dc92d4..e55cd9c9 100644 --- a/tool/pftool.cc +++ b/tool/pftool.cc @@ -21,57 +21,6 @@ static void status( PolarfireTarget* pft ) { printf("\n"); } -/** - * Low-level Wishbone Interactions - * - * We acces the active wishbone connection via PolarfireTarget. - * @see BaseMenu::readline_int for how integers can be passed in - * (in short, decimal, hex, octal, and binary are supported) - * - * ## Commands - * - RESET : WishboneInterface::wb_reset - * - WRITE : WishboneInterface::wb_write - * - READ : WishboneInterface::wb_read - * - BLOCKREAD : Loop over READ for input number of words - * - STATUS : Print results form WishboneInterface::wb_errors - * - * @param[in] cmd Wishbone Command - * @param[in] pft active target - */ -static void wb( const std::string& cmd, PolarfireTarget* pft ) { - static uint32_t target=0; - static uint32_t addr=0; - if (cmd=="RESET") { - pft->wb->wb_reset(); - } - if (cmd=="WRITE") { - target=BaseMenu::readline_int("Target",target); - addr=BaseMenu::readline_int("Address",addr); - uint32_t val=BaseMenu::readline_int("Value",0); - pft->wb->wb_write(target,addr,val); - } - if (cmd=="READ") { - target=BaseMenu::readline_int("Target",target); - addr=BaseMenu::readline_int("Address",addr); - uint32_t val=pft->wb->wb_read(target,addr); - printf(" Read: 0x%08x\n",val); - } - if (cmd=="BLOCKREAD") { - target=BaseMenu::readline_int("Target",target); - addr=BaseMenu::readline_int("Starting address",addr); - int len=BaseMenu::readline_int("Number of words",8); - for (int i=0; iwb->wb_read(target,addr+i); - printf(" %2d/0x%04x : 0x%08x\n",target,addr+i,val); - } - } - if (cmd=="STATUS") { - uint32_t crcd, crcu, wbe; - pft->wb->wb_errors(crcu,crcd,wbe); - printf("CRC errors: Up -- %d Down --%d \n",crcu,crcd); - printf("Wishbone errors: %d\n",wbe); - } -} /** diff --git a/tool/pftool_expert.cc b/tool/pftool_expert.cc index a7f672ae..918c8a03 100644 --- a/tool/pftool_expert.cc +++ b/tool/pftool_expert.cc @@ -1,4 +1,4 @@ -#include "pftool_i2c.h" +#include "pftool_expert.h" void i2c( const std::string& cmd, PolarfireTarget* pft ) { @@ -61,3 +61,39 @@ void i2c( const std::string& cmd, PolarfireTarget* pft ) i2c.general_write_read(i2caddr,wdata); } } + +void wb( const std::string& cmd, PolarfireTarget* pft ) +{ + static uint32_t target=0; + static uint32_t addr=0; + if (cmd=="RESET") { + pft->wb->wb_reset(); + } + if (cmd=="WRITE") { + target=BaseMenu::readline_int("Target",target); + addr=BaseMenu::readline_int("Address",addr); + uint32_t val=BaseMenu::readline_int("Value",0); + pft->wb->wb_write(target,addr,val); + } + if (cmd=="READ") { + target=BaseMenu::readline_int("Target",target); + addr=BaseMenu::readline_int("Address",addr); + uint32_t val=pft->wb->wb_read(target,addr); + printf(" Read: 0x%08x\n",val); + } + if (cmd=="BLOCKREAD") { + target=BaseMenu::readline_int("Target",target); + addr=BaseMenu::readline_int("Starting address",addr); + int len=BaseMenu::readline_int("Number of words",8); + for (int i=0; iwb->wb_read(target,addr+i); + printf(" %2d/0x%04x : 0x%08x\n",target,addr+i,val); + } + } + if (cmd=="STATUS") { + uint32_t crcd, crcu, wbe; + pft->wb->wb_errors(crcu,crcd,wbe); + printf("CRC errors: Up -- %d Down --%d \n",crcu,crcd); + printf("Wishbone errors: %d\n",wbe); + } +} diff --git a/tool/pftool_expert.h b/tool/pftool_expert.h index 5df14995..7a9cef45 100644 --- a/tool/pftool_expert.h +++ b/tool/pftool_expert.h @@ -11,8 +11,10 @@ using pflib::PolarfireTarget; * into the pflib::I2C class. * * ## Commands - * - BUS : pflib::I2C::set_active_bus, default retrieved by pflib::I2C::get_active_bus - * - WRITE : pflib::I2C::write_byte after passing 1000 to pflib::I2C::set_bus_speed + * - BUS : pflib::I2C::set_active_bus, default retrieved by + * pflib::I2C::get_active_bus + * - WRITE : pflib::I2C::write_byte after passing 1000 to + * pflib::I2C::set_bus_speed * - READ : pflib::I2C::read_byte after passing 100 to pflib::I2C::set_bus_speed * - MULTIREAD : pflib::I2C::general_write_read * - MULTIWRITE : pflib::I2C::general_write_read @@ -20,6 +22,24 @@ using pflib::PolarfireTarget; * @param[in] cmd I2C command * @param[in] pft active target */ -void i2c( const std::string& cmd, PolarfireTarget* pft ); +void i2c(const std::string &cmd, PolarfireTarget *pft); +/** + * Low-level Wishbone Interactions + * + * We acces the active wishbone connection via PolarfireTarget. + * @see BaseMenu::readline_int for how integers can be passed in + * (in short, decimal, hex, octal, and binary are supported) + * + * ## Commands + * - RESET : WishboneInterface::wb_reset + * - WRITE : WishboneInterface::wb_write + * - READ : WishboneInterface::wb_read + * - BLOCKREAD : Loop over READ for input number of words + * - STATUS : Print results form WishboneInterface::wb_errors + * + * @param[in] cmd Wishbone Command + * @param[in] pft active target + */ +void wb(const std::string &cmd, PolarfireTarget *pft); #endif /* PFTOOL_I2C_H */ From b5072f3a38406949e53f6a8a324676f960455267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 19:46:47 +0200 Subject: [PATCH 14/21] Add FC TU --- CMakeLists.txt | 3 ++- tool/pftool.cc | 5 +++++ tool/pftool.h | 6 +----- tool/pftool_fastcontrol.cc | 2 ++ tool/pftool_fastcontrol.h | 7 +++++++ 5 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 tool/pftool_fastcontrol.cc create mode 100644 tool/pftool_fastcontrol.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f3373c0b..c7feb2f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,8 @@ add_executable(pftool tool/pftool_tasks.cc tool/pftool_roc.cc tool/pftool_daq.cc - tool/pftool_expert.cc) + tool/pftool_expert.cc + tool/pftool_fastcontrol.cc) target_link_libraries(pftool PRIVATE pflib readline) # don't install test-menu executable! just for Menu developments diff --git a/tool/pftool.cc b/tool/pftool.cc index e55cd9c9..4c63342d 100644 --- a/tool/pftool.cc +++ b/tool/pftool.cc @@ -1,10 +1,15 @@ #include "pftool.h" + /** * @file pftool.cc File defining the pftool menus and their commands. * * The commands are written into functions corresponding to the menu's name. */ +/** + * pull the target of our menu into this source file to reduce code + */ +using pflib::PolarfireTarget; /** * Main status of menu * diff --git a/tool/pftool.h b/tool/pftool.h index 17e77358..60e14c1e 100644 --- a/tool/pftool.h +++ b/tool/pftool.h @@ -1,6 +1,6 @@ #ifndef PFTOOL_H #define PFTOOL_H - +#include "pftool_fastcontrol.h" #include "pftool_expert.h" #include "pftool_tasks.h" #include "pftool_roc.h" @@ -30,9 +30,5 @@ #include "Rcfile.h" #include "pflib/decoding/SuperPacket.h" -/** - * pull the target of our menu into this source file to reduce code - */ -using pflib::PolarfireTarget; #endif /* PFTOOL_H */ diff --git a/tool/pftool_fastcontrol.cc b/tool/pftool_fastcontrol.cc new file mode 100644 index 00000000..6013f719 --- /dev/null +++ b/tool/pftool_fastcontrol.cc @@ -0,0 +1,2 @@ + +#include "pftool_fastcontrol.h" diff --git a/tool/pftool_fastcontrol.h b/tool/pftool_fastcontrol.h new file mode 100644 index 00000000..e63bffbe --- /dev/null +++ b/tool/pftool_fastcontrol.h @@ -0,0 +1,7 @@ +#ifndef PFTOOL_FASTCONTROL_H +#define PFTOOL_FASTCONTROL_H +#include "pflib/PolarfireTarget.h" +#include "Menu.h" + + +#endif /* PFTOOL_FASTCONTROL_H */ From e40f6979aaf88428c46d8f009ff74cb5e74fe8b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 19:49:12 +0200 Subject: [PATCH 15/21] Move the fast control menu to corresponding TU --- tool/pftool.cc | 125 ------------------------------------- tool/pftool_fastcontrol.cc | 107 +++++++++++++++++++++++++++++++ tool/pftool_fastcontrol.h | 26 ++++++++ 3 files changed, 133 insertions(+), 125 deletions(-) diff --git a/tool/pftool.cc b/tool/pftool.cc index 4c63342d..55f8452a 100644 --- a/tool/pftool.cc +++ b/tool/pftool.cc @@ -192,131 +192,6 @@ static void elinks( const std::string& cmd, PolarfireTarget* pft ) { } -/** - * Fast Control (FC) menu commands - * - * ## Commands - * - SW_L1A : pflib::Backend::fc_sendL1A - * - LINK_RESET : pflib::Backend::fc_linkreset - * - BUFFER_CLEAR : pflib::Backend::fc_bufferclear - * - COUNTER_RESET : pflib::FastControl::resetCounters - * - FC_RESET : pflib::FastControl::resetTransmitter - * - CALIB : pflib::Backend::fc_setup_calib - * - MULTISAMPLE : pflib::FastControl::setupMultisample - * and pflib::rouge::RogueWishboneInterface::daq_dma_setup if that is how the user is connected - * - STATUS : print mutlisample status and Error and Command counters - * pflib::FastControl::getErrorCounters, pflib::FastControl::getCmdCounters, - * pflib::FastControl::getMultisampleSetup - * - * @param[in] cmd FC menu command - * @param[in] pft active target - */ -static void fc( const std::string& cmd, PolarfireTarget* pft ) { - bool do_status=false; - - if (cmd=="SW_L1A") { - pft->backend->fc_sendL1A(); - printf("Sent SW L1A\n"); - } - if (cmd=="LINK_RESET") { - pft->backend->fc_linkreset(); - printf("Sent LINK RESET\n"); - } - if (cmd=="RUN_CLEAR") { - pft->backend->fc_clear_run(); - std::cout << "Cleared run counters" << std::endl; - } - if (cmd=="BUFFER_CLEAR") { - pft->backend->fc_bufferclear(); - printf("Sent BUFFER CLEAR\n"); - } - if (cmd=="VETO_SETUP") { - bool veto_daq_busy, veto_l1_occ; - int level_busy, level_ok; - pft->backend->fc_veto_setup_read(veto_daq_busy, veto_l1_occ,level_busy, level_ok); - veto_daq_busy=BaseMenu::readline_bool("Veto L1A on DAQ busy? ",veto_daq_busy); - veto_l1_occ=BaseMenu::readline_bool("Veto L1A on L1 occupancy? ",veto_l1_occ); - pft->backend->fc_veto_setup(veto_daq_busy, veto_l1_occ,level_busy, level_ok); - if (veto_l1_occ) printf("\n Occupancy Veto Thresholds -- OK->BUSY at %d, BUSY->OK at %d\n",level_busy,level_ok); - } - if (cmd=="COUNTER_RESET") { - pft->hcal.fc().resetCounters(); - do_status=true; - } - if (cmd=="FC_RESET") { - pft->hcal.fc().resetTransmitter(); - } - if (cmd=="CALIB") { - int len, offset; - pft->backend->fc_get_setup_calib(len,offset); -#ifdef PFTOOL_UHAL - std::cout << - "NOTE: A known bug in uMNio firmware which has been patched in later versions\n" - " leads to the inability of the firmware to read some parameters.\n" - " If you are seeing 0 as the default even after setting these parameters,\n" - " you have this (slightly) buggy firmware." - << std::endl << std::endl; -#endif - len=BaseMenu::readline_int("Calibration pulse length?",len); - offset=BaseMenu::readline_int("Calibration L1A offset?",offset); - pft->backend->fc_setup_calib(len,offset); - } - if (cmd=="MULTISAMPLE") { - bool multi; - int nextra; - pft->hcal.fc().getMultisampleSetup(multi,nextra); - multi=BaseMenu::readline_bool("Enable multisample readout? ",multi); - if (multi) - nextra=BaseMenu::readline_int("Extra samples (total is +1 from this number) : ",nextra); - pft->hcal.fc().setupMultisample(multi,nextra); - // also, DMA needs to know -#ifdef PFTOOL_ROGUE - auto rwbi=dynamic_cast(pft->wb); - if (rwbi) { - bool enabled; - uint8_t samples_per_event, fpgaid_i; - rwbi->daq_get_dma_setup(fpgaid_i,samples_per_event, enabled); - samples_per_event=nextra+1; - rwbi->daq_dma_setup(fpgaid_i,samples_per_event); - } -#endif - } - if (cmd=="STATUS" || do_status) { - static const std::vector bit_comments = { - "orbit requests", - "l1a/read requests", - "", - "", - "", - "calib pulse requests", - "", - "" - }; - bool multi; - int nextra; - pft->hcal.fc().getMultisampleSetup(multi,nextra); - if (multi) printf(" Multisample readout enabled : %d extra L1a (%d total samples)\n",nextra,nextra+1); - else printf(" Multisaple readout disabled\n"); - printf(" Snapshot: %03x\n",pft->wb->wb_read(1,3)); - uint32_t sbe,dbe; - pft->hcal.fc().getErrorCounters(sbe,dbe); - printf(" Single bit errors: %d Double bit errors: %d\n",sbe,dbe); - std::vector cnt=pft->hcal.fc().getCmdCounters(); - for (int i=0; i<8; i++) - printf(" Bit %d count: %20u (%s)\n",i,cnt[i],bit_comments.at(i).c_str()); - int spill_count, header_occ, header_occ_max, event_count,vetoed_counter; - pft->backend->fc_read_counters(spill_count, header_occ, header_occ_max, event_count, vetoed_counter); - printf(" Spills: %d Events: %d Header occupancy: %d (max %d) Vetoed L1A: %d\n",spill_count,event_count,header_occ,header_occ_max,vetoed_counter); - } - if (cmd=="ENABLES") { - bool ext_l1a, ext_spill, timer_l1a; - pft->backend->fc_enables_read(ext_l1a, ext_spill, timer_l1a); - ext_l1a=BaseMenu::readline_bool("Enable external L1A? ",ext_l1a); - ext_spill=BaseMenu::readline_bool("Enable external spill? ",ext_spill); - timer_l1a=BaseMenu::readline_bool("Enable timer L1A? ",timer_l1a); - pft->backend->fc_enables(ext_l1a, ext_spill, timer_l1a); - } -} /** * DAQ->SETUP menu commands diff --git a/tool/pftool_fastcontrol.cc b/tool/pftool_fastcontrol.cc index 6013f719..bfccc9d7 100644 --- a/tool/pftool_fastcontrol.cc +++ b/tool/pftool_fastcontrol.cc @@ -1,2 +1,109 @@ #include "pftool_fastcontrol.h" +using pflib::PolarfireTarget; +void fc( const std::string& cmd, PolarfireTarget* pft ) { + bool do_status=false; + + if (cmd=="SW_L1A") { + pft->backend->fc_sendL1A(); + printf("Sent SW L1A\n"); + } + if (cmd=="LINK_RESET") { + pft->backend->fc_linkreset(); + printf("Sent LINK RESET\n"); + } + if (cmd=="RUN_CLEAR") { + pft->backend->fc_clear_run(); + std::cout << "Cleared run counters" << std::endl; + } + if (cmd=="BUFFER_CLEAR") { + pft->backend->fc_bufferclear(); + printf("Sent BUFFER CLEAR\n"); + } + if (cmd=="VETO_SETUP") { + bool veto_daq_busy, veto_l1_occ; + int level_busy, level_ok; + pft->backend->fc_veto_setup_read(veto_daq_busy, veto_l1_occ,level_busy, level_ok); + veto_daq_busy=BaseMenu::readline_bool("Veto L1A on DAQ busy? ",veto_daq_busy); + veto_l1_occ=BaseMenu::readline_bool("Veto L1A on L1 occupancy? ",veto_l1_occ); + pft->backend->fc_veto_setup(veto_daq_busy, veto_l1_occ,level_busy, level_ok); + if (veto_l1_occ) printf("\n Occupancy Veto Thresholds -- OK->BUSY at %d, BUSY->OK at %d\n",level_busy,level_ok); + } + if (cmd=="COUNTER_RESET") { + pft->hcal.fc().resetCounters(); + do_status=true; + } + if (cmd=="FC_RESET") { + pft->hcal.fc().resetTransmitter(); + } + if (cmd=="CALIB") { + int len, offset; + pft->backend->fc_get_setup_calib(len,offset); +#ifdef PFTOOL_UHAL + std::cout << + "NOTE: A known bug in uMNio firmware which has been patched in later versions\n" + " leads to the inability of the firmware to read some parameters.\n" + " If you are seeing 0 as the default even after setting these parameters,\n" + " you have this (slightly) buggy firmware." + << std::endl << std::endl; +#endif + len=BaseMenu::readline_int("Calibration pulse length?",len); + offset=BaseMenu::readline_int("Calibration L1A offset?",offset); + pft->backend->fc_setup_calib(len,offset); + } + if (cmd=="MULTISAMPLE") { + bool multi; + int nextra; + pft->hcal.fc().getMultisampleSetup(multi,nextra); + multi=BaseMenu::readline_bool("Enable multisample readout? ",multi); + if (multi) + nextra=BaseMenu::readline_int("Extra samples (total is +1 from this number) : ",nextra); + pft->hcal.fc().setupMultisample(multi,nextra); + // also, DMA needs to know +#ifdef PFTOOL_ROGUE + auto rwbi=dynamic_cast(pft->wb); + if (rwbi) { + bool enabled; + uint8_t samples_per_event, fpgaid_i; + rwbi->daq_get_dma_setup(fpgaid_i,samples_per_event, enabled); + samples_per_event=nextra+1; + rwbi->daq_dma_setup(fpgaid_i,samples_per_event); + } +#endif + } + if (cmd=="STATUS" || do_status) { + static const std::vector bit_comments = { + "orbit requests", + "l1a/read requests", + "", + "", + "", + "calib pulse requests", + "", + "" + }; + bool multi; + int nextra; + pft->hcal.fc().getMultisampleSetup(multi,nextra); + if (multi) printf(" Multisample readout enabled : %d extra L1a (%d total samples)\n",nextra,nextra+1); + else printf(" Multisaple readout disabled\n"); + printf(" Snapshot: %03x\n",pft->wb->wb_read(1,3)); + uint32_t sbe,dbe; + pft->hcal.fc().getErrorCounters(sbe,dbe); + printf(" Single bit errors: %d Double bit errors: %d\n",sbe,dbe); + std::vector cnt=pft->hcal.fc().getCmdCounters(); + for (int i=0; i<8; i++) + printf(" Bit %d count: %20u (%s)\n",i,cnt[i],bit_comments.at(i).c_str()); + int spill_count, header_occ, header_occ_max, event_count,vetoed_counter; + pft->backend->fc_read_counters(spill_count, header_occ, header_occ_max, event_count, vetoed_counter); + printf(" Spills: %d Events: %d Header occupancy: %d (max %d) Vetoed L1A: %d\n",spill_count,event_count,header_occ,header_occ_max,vetoed_counter); + } + if (cmd=="ENABLES") { + bool ext_l1a, ext_spill, timer_l1a; + pft->backend->fc_enables_read(ext_l1a, ext_spill, timer_l1a); + ext_l1a=BaseMenu::readline_bool("Enable external L1A? ",ext_l1a); + ext_spill=BaseMenu::readline_bool("Enable external spill? ",ext_spill); + timer_l1a=BaseMenu::readline_bool("Enable timer L1A? ",timer_l1a); + pft->backend->fc_enables(ext_l1a, ext_spill, timer_l1a); + } +} diff --git a/tool/pftool_fastcontrol.h b/tool/pftool_fastcontrol.h index e63bffbe..66ea3137 100644 --- a/tool/pftool_fastcontrol.h +++ b/tool/pftool_fastcontrol.h @@ -3,5 +3,31 @@ #include "pflib/PolarfireTarget.h" #include "Menu.h" +#ifdef PFTOOL_ROGUE +#include "pflib/rogue/RogueWishboneInterface.h" +#endif +#ifdef PFTOOL_UHAL +#include "pflib/uhal/uhalWishboneInterface.h" +#endif +/** + * Fast Control (FC) menu commands + * + * ## Commands + * - SW_L1A : pflib::Backend::fc_sendL1A + * - LINK_RESET : pflib::Backend::fc_linkreset + * - BUFFER_CLEAR : pflib::Backend::fc_bufferclear + * - COUNTER_RESET : pflib::FastControl::resetCounters + * - FC_RESET : pflib::FastControl::resetTransmitter + * - CALIB : pflib::Backend::fc_setup_calib + * - MULTISAMPLE : pflib::FastControl::setupMultisample + * and pflib::rouge::RogueWishboneInterface::daq_dma_setup if that is how the user is connected + * - STATUS : print mutlisample status and Error and Command counters + * pflib::FastControl::getErrorCounters, pflib::FastControl::getCmdCounters, + * pflib::FastControl::getMultisampleSetup + * + * @param[in] cmd FC menu command + * @param[in] pft active target + */ +void fc( const std::string& cmd, pflib::PolarfireTarget* pft); #endif /* PFTOOL_FASTCONTROL_H */ From 93b969ba119ce5b7842240eda62374850345a27c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 19:54:01 +0200 Subject: [PATCH 16/21] Add a TU for the BIAS menu --- CMakeLists.txt | 3 ++- tool/pftool.h | 1 + tool/pftool_bias.cc | 1 + tool/pftool_bias.h | 8 ++++++++ 4 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 tool/pftool_bias.cc create mode 100644 tool/pftool_bias.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c7feb2f6..554b2f0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,7 +59,8 @@ add_executable(pftool tool/pftool_roc.cc tool/pftool_daq.cc tool/pftool_expert.cc - tool/pftool_fastcontrol.cc) + tool/pftool_fastcontrol.cc + tool/pftool_bias.cc) target_link_libraries(pftool PRIVATE pflib readline) # don't install test-menu executable! just for Menu developments diff --git a/tool/pftool.h b/tool/pftool.h index 60e14c1e..ea37285e 100644 --- a/tool/pftool.h +++ b/tool/pftool.h @@ -5,6 +5,7 @@ #include "pftool_tasks.h" #include "pftool_roc.h" #include "pftool_daq.h" +#include "pftool_bias.h" #include #include #include diff --git a/tool/pftool_bias.cc b/tool/pftool_bias.cc new file mode 100644 index 00000000..8c4ca7b5 --- /dev/null +++ b/tool/pftool_bias.cc @@ -0,0 +1 @@ +#include "pftool_bias.h" diff --git a/tool/pftool_bias.h b/tool/pftool_bias.h new file mode 100644 index 00000000..a9cdd933 --- /dev/null +++ b/tool/pftool_bias.h @@ -0,0 +1,8 @@ +#ifndef PFTOOL_BIAS_H +#define PFTOOL_BIAS_H + +#include "pflib/PolarfireTarget.h" +#include "Menu.h" + + +#endif /* PFTOOL_BIAS_H */ From d0c3e8d62cadb1bd4fb93ec94094921081d952e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 20:01:58 +0200 Subject: [PATCH 17/21] Add the final TU, ELINKS --- CMakeLists.txt | 1 + tool/pftool.cc | 52 ------------------------------------------- tool/pftool.h | 1 + tool/pftool_bias.cc | 39 ++++++++++++++++++++++++++++++++ tool/pftool_bias.h | 16 +++++++++++++ tool/pftool_elinks.cc | 2 ++ tool/pftool_elinks.h | 9 ++++++++ 7 files changed, 68 insertions(+), 52 deletions(-) create mode 100644 tool/pftool_elinks.cc create mode 100644 tool/pftool_elinks.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 554b2f0a..156e9ec8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,6 +59,7 @@ add_executable(pftool tool/pftool_roc.cc tool/pftool_daq.cc tool/pftool_expert.cc + tool/pftool_elinks.cc tool/pftool_fastcontrol.cc tool/pftool_bias.cc) target_link_libraries(pftool PRIVATE pflib readline) diff --git a/tool/pftool.cc b/tool/pftool.cc index 55f8452a..f077acd3 100644 --- a/tool/pftool.cc +++ b/tool/pftool.cc @@ -455,58 +455,6 @@ static void daq_debug( const std::string& cmd, PolarfireTarget* pft ) { } } -/** - * BIAS menu commands - * - * @note This menu has not been explored thoroughly so some of these commands - * are not fully developed. - * - * ## Commands - * - STATUS : _does nothing_ after selecting a board. - * - INIT : pflib::Bias::initialize the selected board - * - SET : pflib::PolarfireTarget::setBiasSetting - * - LOAD : pflib::PolarfireTarget::loadBiasSettings - * - * @param[in] cmd selected menu command - * @param[in] pft active target - */ -static void bias( const std::string& cmd, PolarfireTarget* pft ) { - static int iboard=0; - if (cmd=="STATUS") { - iboard=BaseMenu::readline_int("Which board? ",iboard); - pflib::Bias bias=pft->hcal.bias(iboard); - } - - if (cmd=="INIT") { - iboard=BaseMenu::readline_int("Which board? ",iboard); - pflib::Bias bias=pft->hcal.bias(iboard); - bias.initialize(); - } - if (cmd=="SET") { - iboard=BaseMenu::readline_int("Which board? ",iboard); - static int led_sipm=0; - led_sipm=BaseMenu::readline_int(" SiPM(0) or LED(1)? ",led_sipm); - int ichan=BaseMenu::readline_int(" Which HDMI connector? ",-1); - int dac=BaseMenu::readline_int(" What DAC value? ",0); - if (ichan>=0) { - pft->setBiasSetting(iboard,led_sipm==1,ichan,dac); - } - if (ichan==-1) { - printf("\n Setting bias on all 16 connectors. \n"); - for(int k = 0; k < 16; k++){ - pft->setBiasSetting(iboard,led_sipm==1,k,dac); - } - } - } - if (cmd=="LOAD") { - printf("\n --- This command expects a CSV file with four columns [0=SiPM/1=LED,board,hdmi#,value].\n"); - printf(" --- Line starting with # are ignored.\n"); - std::string fname=BaseMenu::readline("Filename: "); - if (not pft->loadBiasSettings(fname)) { - std::cerr << "\n\n ERROR: Unable to access " << fname << std::endl; - } - } -} /** * Menu construction for pftool diff --git a/tool/pftool.h b/tool/pftool.h index ea37285e..65d9ce3a 100644 --- a/tool/pftool.h +++ b/tool/pftool.h @@ -5,6 +5,7 @@ #include "pftool_tasks.h" #include "pftool_roc.h" #include "pftool_daq.h" +#include "pftool_elinks.h" #include "pftool_bias.h" #include #include diff --git a/tool/pftool_bias.cc b/tool/pftool_bias.cc index 8c4ca7b5..c6b02180 100644 --- a/tool/pftool_bias.cc +++ b/tool/pftool_bias.cc @@ -1 +1,40 @@ #include "pftool_bias.h" +using pflib::PolarfireTarget; +void bias( const std::string& cmd, PolarfireTarget* pft ) +{ + static int iboard=0; + if (cmd=="STATUS") { + iboard=BaseMenu::readline_int("Which board? ",iboard); + pflib::Bias bias=pft->hcal.bias(iboard); + } + + if (cmd=="INIT") { + iboard=BaseMenu::readline_int("Which board? ",iboard); + pflib::Bias bias=pft->hcal.bias(iboard); + bias.initialize(); + } + if (cmd=="SET") { + iboard=BaseMenu::readline_int("Which board? ",iboard); + static int led_sipm=0; + led_sipm=BaseMenu::readline_int(" SiPM(0) or LED(1)? ",led_sipm); + int ichan=BaseMenu::readline_int(" Which HDMI connector? ",-1); + int dac=BaseMenu::readline_int(" What DAC value? ",0); + if (ichan>=0) { + pft->setBiasSetting(iboard,led_sipm==1,ichan,dac); + } + if (ichan==-1) { + printf("\n Setting bias on all 16 connectors. \n"); + for(int k = 0; k < 16; k++){ + pft->setBiasSetting(iboard,led_sipm==1,k,dac); + } + } + } + if (cmd=="LOAD") { + printf("\n --- This command expects a CSV file with four columns [0=SiPM/1=LED,board,hdmi#,value].\n"); + printf(" --- Line starting with # are ignored.\n"); + std::string fname=BaseMenu::readline("Filename: "); + if (not pft->loadBiasSettings(fname)) { + std::cerr << "\n\n ERROR: Unable to access " << fname << std::endl; + } + } +} diff --git a/tool/pftool_bias.h b/tool/pftool_bias.h index a9cdd933..e77095e4 100644 --- a/tool/pftool_bias.h +++ b/tool/pftool_bias.h @@ -4,5 +4,21 @@ #include "pflib/PolarfireTarget.h" #include "Menu.h" +/** + * BIAS menu commands + * + * @note This menu has not been explored thoroughly so some of these commands + * are not fully developed. + * + * ## Commands + * - STATUS : _does nothing_ after selecting a board. + * - INIT : pflib::Bias::initialize the selected board + * - SET : pflib::PolarfireTarget::setBiasSetting + * - LOAD : pflib::PolarfireTarget::loadBiasSettings + * + * @param[in] cmd selected menu command + * @param[in] pft active target + */ +void bias( const std::string& cmd, pflib::PolarfireTarget* pft ); #endif /* PFTOOL_BIAS_H */ diff --git a/tool/pftool_elinks.cc b/tool/pftool_elinks.cc new file mode 100644 index 00000000..7b64c3db --- /dev/null +++ b/tool/pftool_elinks.cc @@ -0,0 +1,2 @@ +#include "pftool_elinks.h" +using pflib::PolarfireTarget; diff --git a/tool/pftool_elinks.h b/tool/pftool_elinks.h new file mode 100644 index 00000000..ec61f1a3 --- /dev/null +++ b/tool/pftool_elinks.h @@ -0,0 +1,9 @@ +#ifndef PFTOOL_ELINKS_H +#define PFTOOL_ELINKS_H + +#include "pflib/PolarfireTarget.h" +#include "Menu.h" + + + +#endif /* PFTOOL_ELINKS_H */ From aa3ba965976a8b576e128d0c89c4c4a4df35c3f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 20:03:43 +0200 Subject: [PATCH 18/21] Move the ELINKS menu to its TU --- tool/pftool.cc | 124 ------------------------------------------ tool/pftool.h | 1 - tool/pftool_elinks.cc | 106 ++++++++++++++++++++++++++++++++++++ tool/pftool_elinks.h | 22 ++++++++ 4 files changed, 128 insertions(+), 125 deletions(-) diff --git a/tool/pftool.cc b/tool/pftool.cc index f077acd3..91ba1074 100644 --- a/tool/pftool.cc +++ b/tool/pftool.cc @@ -67,130 +67,6 @@ static void link( const std::string& cmd, PolarfireTarget* pft ) { } } -/** - * ELINKS menu commands - * - * We retrieve a reference to the current elinks object via - * pflib::Hcal::elinks and then procede to the commands. - * - * ## Commands - * - RELINK : pflib::PolarfireTarget::elink_relink - * - SPY : pflib::Elinks::spy - * - HEADER_CHECK : do a pedestal run and count good/bad headers in it - * - BITSLIP : pflib::Elinks::setBitslip and pflib::Elinks::setBitslipAuto - * - BIGSPY : PolarfireTarget::elinksBigSpy - * - DELAY : pflib::Elinks::setDelay - * - HARD_RESET : pflib::Elinks::resetHard - * - SCAN : pflib::Elinks::scanAlign - * - STATUS : pflib::PolarfireTarget::elinkStatus with std::cout input - * - * @param[in] cmd ELINKS command - * @param[in] pft active target - */ -static void elinks( const std::string& cmd, PolarfireTarget* pft ) { - pflib::Elinks& elinks=pft->hcal.elinks(); - static int ilink=0,nevents{100}; - static int min_delay{0}, max_delay{128}; - if (cmd=="RELINK"){ - ilink=BaseMenu::readline_int("Which elink? (-1 for all) ",ilink); - min_delay=BaseMenu::readline_int("Min delay? ",min_delay); - max_delay=BaseMenu::readline_int("Max delay? ",max_delay); - pft->elink_relink(ilink,min_delay,max_delay); - } - if (cmd=="SPY") { - ilink=BaseMenu::readline_int("Which elink? ",ilink); - std::vector spy=elinks.spy(ilink); - for (size_t i=0; ihcal.fc().getMultisampleSetup(multi,nextra); - if (multi) nsamples=nextra+1; - } - - pft->prepareNewRun(); - - int n_good_bxheaders[8] = {0,0,0,0,0,0,0,0}; - int n_bad_bxheaders[8] = {0,0,0,0,0,0,0,0}; - int n_good_idles[8] = {0,0,0,0,0,0,0,0}; - int n_bad_idles[8] = {0,0,0,0,0,0,0,0}; - for (int ievt{0}; ievt < nevents; ievt++) { - pft->backend->fc_sendL1A(); - std::vector event_raw = pft->daqReadEvent(); - pflib::decoding::SuperPacket event{&(event_raw[0]), int(event_raw.size())}; - for (int s{0}; s < nsamples; s++) { - for (int l{0}; l < 8; l++) { - auto packet = event.sample(s).roc(l); - if (packet.length() > 2) { - if (event.sample(s).roc(l).good_bxheader()) n_good_bxheaders[l]++; - else n_bad_bxheaders[l]++; - if (event.sample(s).roc(l).good_idle()) n_good_idles[l]++; - else n_bad_idles[l]++; - } - } - } - } - - printf(" %26s | %26s\n","BX Headers","Idles"); - printf("Link %10s %10s %4s | %10s %10s %4s\n","Good","Bad","B/T","Good","Bad","B/T"); - for (int ilink{0}; ilink < 8; ilink++) { - float bg_bxheaders = 0.; - if (n_good_bxheaders[ilink]+n_bad_bxheaders[ilink]>0) - bg_bxheaders = float(n_bad_bxheaders[ilink])/ - (n_good_bxheaders[ilink]+n_bad_bxheaders[ilink]); - float bg_idles = 0.; - if (n_good_idles[ilink]+n_bad_idles[ilink]>0) - bg_idles = float(n_bad_idles[ilink])/ - (n_good_idles[ilink]+n_bad_idles[ilink]); - printf("%4d %10d %10d %.2f | %10d %10d %.2f\n", ilink, - n_good_bxheaders[ilink], n_bad_bxheaders[ilink], bg_bxheaders, - n_good_idles[ilink], n_bad_idles[ilink], bg_idles); - } - } - if (cmd=="BITSLIP") { - ilink=BaseMenu::readline_int("Which elink? ",ilink); - int bitslip=BaseMenu::readline_int("Bitslip value (-1 for auto): ",elinks.getBitslip(ilink)); - for (int jlink=0; jlink<8; jlink++) { - if (ilink>=0 && jlink!=ilink) continue; - if (bitslip<0) elinks.setBitslipAuto(jlink,true); - else { - elinks.setBitslipAuto(jlink,false); - elinks.setBitslip(jlink,bitslip); - } - } - } - if (cmd=="BIGSPY") { - int mode=BaseMenu::readline_int("Mode? (0=immediate, 1=L1A) ",0); - ilink=BaseMenu::readline_int("Which elink? ",ilink); - int presamples=BaseMenu::readline_int("Presamples? ",20); - std::vector words = pft->elinksBigSpy(ilink,presamples,mode==1); - for (int i=0; ielinkStatus(std::cout); - } -} - /** diff --git a/tool/pftool.h b/tool/pftool.h index 65d9ce3a..e1d5726c 100644 --- a/tool/pftool.h +++ b/tool/pftool.h @@ -30,7 +30,6 @@ #endif #include "Menu.h" #include "Rcfile.h" -#include "pflib/decoding/SuperPacket.h" #endif /* PFTOOL_H */ diff --git a/tool/pftool_elinks.cc b/tool/pftool_elinks.cc index 7b64c3db..e06c308c 100644 --- a/tool/pftool_elinks.cc +++ b/tool/pftool_elinks.cc @@ -1,2 +1,108 @@ #include "pftool_elinks.h" using pflib::PolarfireTarget; + + +void elinks( const std::string& cmd, PolarfireTarget* pft ) +{ + pflib::Elinks& elinks=pft->hcal.elinks(); + static int ilink=0,nevents{100}; + static int min_delay{0}, max_delay{128}; + if (cmd=="RELINK"){ + ilink=BaseMenu::readline_int("Which elink? (-1 for all) ",ilink); + min_delay=BaseMenu::readline_int("Min delay? ",min_delay); + max_delay=BaseMenu::readline_int("Max delay? ",max_delay); + pft->elink_relink(ilink,min_delay,max_delay); + } + if (cmd=="SPY") { + ilink=BaseMenu::readline_int("Which elink? ",ilink); + std::vector spy=elinks.spy(ilink); + for (size_t i=0; ihcal.fc().getMultisampleSetup(multi,nextra); + if (multi) nsamples=nextra+1; + } + + pft->prepareNewRun(); + + int n_good_bxheaders[8] = {0,0,0,0,0,0,0,0}; + int n_bad_bxheaders[8] = {0,0,0,0,0,0,0,0}; + int n_good_idles[8] = {0,0,0,0,0,0,0,0}; + int n_bad_idles[8] = {0,0,0,0,0,0,0,0}; + for (int ievt{0}; ievt < nevents; ievt++) { + pft->backend->fc_sendL1A(); + std::vector event_raw = pft->daqReadEvent(); + pflib::decoding::SuperPacket event{&(event_raw[0]), int(event_raw.size())}; + for (int s{0}; s < nsamples; s++) { + for (int l{0}; l < 8; l++) { + auto packet = event.sample(s).roc(l); + if (packet.length() > 2) { + if (event.sample(s).roc(l).good_bxheader()) n_good_bxheaders[l]++; + else n_bad_bxheaders[l]++; + if (event.sample(s).roc(l).good_idle()) n_good_idles[l]++; + else n_bad_idles[l]++; + } + } + } + } + + printf(" %26s | %26s\n","BX Headers","Idles"); + printf("Link %10s %10s %4s | %10s %10s %4s\n","Good","Bad","B/T","Good","Bad","B/T"); + for (int ilink{0}; ilink < 8; ilink++) { + float bg_bxheaders = 0.; + if (n_good_bxheaders[ilink]+n_bad_bxheaders[ilink]>0) + bg_bxheaders = float(n_bad_bxheaders[ilink])/ + (n_good_bxheaders[ilink]+n_bad_bxheaders[ilink]); + float bg_idles = 0.; + if (n_good_idles[ilink]+n_bad_idles[ilink]>0) + bg_idles = float(n_bad_idles[ilink])/ + (n_good_idles[ilink]+n_bad_idles[ilink]); + printf("%4d %10d %10d %.2f | %10d %10d %.2f\n", ilink, + n_good_bxheaders[ilink], n_bad_bxheaders[ilink], bg_bxheaders, + n_good_idles[ilink], n_bad_idles[ilink], bg_idles); + } + } + if (cmd=="BITSLIP") { + ilink=BaseMenu::readline_int("Which elink? ",ilink); + int bitslip=BaseMenu::readline_int("Bitslip value (-1 for auto): ",elinks.getBitslip(ilink)); + for (int jlink=0; jlink<8; jlink++) { + if (ilink>=0 && jlink!=ilink) continue; + if (bitslip<0) elinks.setBitslipAuto(jlink,true); + else { + elinks.setBitslipAuto(jlink,false); + elinks.setBitslip(jlink,bitslip); + } + } + } + if (cmd=="BIGSPY") { + int mode=BaseMenu::readline_int("Mode? (0=immediate, 1=L1A) ",0); + ilink=BaseMenu::readline_int("Which elink? ",ilink); + int presamples=BaseMenu::readline_int("Presamples? ",20); + std::vector words = pft->elinksBigSpy(ilink,presamples,mode==1); + for (int i=0; ielinkStatus(std::cout); + } +} diff --git a/tool/pftool_elinks.h b/tool/pftool_elinks.h index ec61f1a3..d9a0d4af 100644 --- a/tool/pftool_elinks.h +++ b/tool/pftool_elinks.h @@ -3,7 +3,29 @@ #include "pflib/PolarfireTarget.h" #include "Menu.h" +#include "pflib/decoding/SuperPacket.h" +/** + * ELINKS menu commands + * + * We retrieve a reference to the current elinks object via + * pflib::Hcal::elinks and then procede to the commands. + * + * ## Commands + * - RELINK : pflib::PolarfireTarget::elink_relink + * - SPY : pflib::Elinks::spy + * - HEADER_CHECK : do a pedestal run and count good/bad headers in it + * - BITSLIP : pflib::Elinks::setBitslip and pflib::Elinks::setBitslipAuto + * - BIGSPY : PolarfireTarget::elinksBigSpy + * - DELAY : pflib::Elinks::setDelay + * - HARD_RESET : pflib::Elinks::resetHard + * - SCAN : pflib::Elinks::scanAlign + * - STATUS : pflib::PolarfireTarget::elinkStatus with std::cout input + * + * @param[in] cmd ELINKS command + * @param[in] pft active target + */ +void elinks( const std::string& cmd, pflib::PolarfireTarget* pft); #endif /* PFTOOL_ELINKS_H */ From b8855c15841615ae10d6fa69ff6ebbeba5eb467e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Einar=20El=C3=A9n?= Date: Sat, 9 Apr 2022 20:07:21 +0200 Subject: [PATCH 19/21] Move remaining DAQ menus --- tool/pftool.cc | 263 --------------------------------------------- tool/pftool_daq.cc | 226 +++++++++++++++++++++++++++++++++++++- tool/pftool_daq.h | 45 +++++++- 3 files changed, 268 insertions(+), 266 deletions(-) diff --git a/tool/pftool.cc b/tool/pftool.cc index 91ba1074..267c3653 100644 --- a/tool/pftool.cc +++ b/tool/pftool.cc @@ -69,269 +69,6 @@ static void link( const std::string& cmd, PolarfireTarget* pft ) { -/** - * DAQ->SETUP menu commands - * - * Before doing any of the commands, we retrieve a reference to the daq - * object via pflib::Hcal::daq. - * - * ## Commands - * - STATUS : pflib::PolarfireTarget::daqStatus - * and pflib::rogue::RogueWishboneInterface::daq_dma_status if connected in that manner - * - ENABLE : toggle whether daq is enabled pflib::DAQ::enable and pflib::DAQ::enabled - * - ZS : pflib::PolarfireTarget::enableZeroSuppression - * - L1APARAMS : Use target's wishbone interface to set the L1A delay and capture length - * Uses pflib::tgt_DAQ_Inbuffer - * - DMA : enable DMA readout pflib::rogue::RogueWishboneInterface::daq_dma_enable - * - FPGA : Set the polarfire FPGA ID number (pflib::DAQ::setIds) and pass this - * to DMA setup if it is enabled - * - STANDARD : Do FPGA command and setup links that are - * labeled as active (pflib::DAQ::setupLink) - * - * @param[in] cmd selected command from DAQ->SETUP menu - * @param[in] pft active target - */ -static void daq_setup( const std::string& cmd, PolarfireTarget* pft ) { - pflib::DAQ& daq=pft->hcal.daq(); - if (cmd=="STATUS") { - pft->daqStatus(std::cout); -#ifdef PFTOOL_ROGUE - auto rwbi=dynamic_cast(pft->wb); - if (rwbi) { - bool enabled; - uint8_t samples_per_event, fpgaid_i; - rwbi->daq_get_dma_setup(fpgaid_i,samples_per_event, enabled); - printf("DMA : %s Status=%08x\n",(enabled)?("ENABLED"):("DISABLED"),rwbi->daq_dma_status()); - } -#endif - } - if (cmd=="ENABLE") { - daq.enable(!daq.enabled()); - } - if (cmd=="ZS") { - int jlink=BaseMenu::readline_int("Which link (-1 for all)? ",-1); - bool fullSuppress=BaseMenu::readline_bool("Suppress all channels? ",false); - pft->enableZeroSuppression(jlink,fullSuppress); - } - if (cmd=="L1APARAMS") { - int ilink=BaseMenu::readline_int("Which link? ",-1); - if (ilink>=0) { - uint32_t reg1=pft->wb->wb_read(pflib::tgt_DAQ_Inbuffer,(ilink<<7)|1); - int delay=BaseMenu::readline_int("L1A delay? ",(reg1>>8)&0xFF); - int capture=BaseMenu::readline_int("L1A capture length? ",(reg1>>16)&0xFF); - reg1=(reg1&0xFF)|((delay&0xFF)<<8)|((capture&0xFF)<<16); - pft->wb->wb_write(pflib::tgt_DAQ_Inbuffer,(ilink<<7)|1,reg1); - } - } - if (cmd=="DMA") { -#ifdef PFTOOL_ROGUE - auto rwbi=dynamic_cast(pft->wb); - if (rwbi) { - bool enabled; - uint8_t samples_per_event, fpgaid_i; - rwbi->daq_get_dma_setup(fpgaid_i,samples_per_event, enabled); - enabled=BaseMenu::readline_bool("Enable DMA? ",enabled); - rwbi->daq_dma_enable(enabled); - } else { - std::cout << "\nNot connected to chip with RogueWishboneInterface, cannot activate DMA.\n" << std::endl; - } -#endif - } - if (cmd=="STANDARD") { - daq_setup("FPGA",pft); - pflib::Elinks& elinks=pft->hcal.elinks(); - for (int i=0; i(pft->wb); - if (rwbi) { - bool enabled; - uint8_t samples_per_event, fpgaid_i; - rwbi->daq_get_dma_setup(fpgaid_i,samples_per_event, enabled); - fpgaid_i=(uint8_t(fpgaid)); - rwbi->daq_dma_setup(fpgaid_i,samples_per_event); - } -#endif - } -} - - - - - -/** - * Print data words from raw binary file and return them - * @return vector of 32-bit data words in file - */ -std::vector read_words_from_file() { - std::vector data; - /// load from file - std::string fname=BaseMenu::readline("Read from text file (line by line hex 32-bit words)"); - char buffer[512]; - FILE* f=fopen(fname.c_str(),"r"); - if (f==0) { - printf("Unable to open '%s'\n",fname.c_str()); - return data; - } - while (!feof(f)) { - buffer[0]=0; - fgets(buffer,511,f); - if (strlen(buffer)<8 || strchr(buffer,'#')!=0) continue; - uint32_t val; - val=strtoul(buffer,0,16); - data.push_back(val); - printf("%08x\n",val); - } - fclose(f); - return data; -} - -/** - * DAQ->DEBUG menu commands - * - * @note These commands have been archived since further development of pflib - * has progressed. They are still available in this submenu; however, - * they should only be used by an expert who is familiar with the chip - * and has looked at what the commands do in the code. - * - * @param[in] cmd selected command from menu - * @param[in] pft active target - */ -static void daq_debug( const std::string& cmd, PolarfireTarget* pft ) { - if (cmd=="STATUS") { - // get the general status - daq("STATUS", pft); - uint32_t reg1,reg2; - printf("-----Per-ROC Controls-----\n"); - reg1=pft->wb->wb_read(pflib::tgt_DAQ_Control,1); - printf(" Disable ROC links: %s\n",(reg1&0x80000000u)?("TRUE"):("FALSE")); - - printf(" Link F E RP WP \n"); - for (int ilink=0; ilinkwb->wb_read(pflib::tgt_DAQ_Inbuffer,(ilink<<7)|3); - printf(" %2d %d %d %2d %2d %08x\n",ilink,(reg>>26)&1,(reg>>27)&1,(reg>>16)&0xf,(reg>>12)&0xf,reg); - } - printf("-----Event builder -----\n"); - reg1=pft->wb->wb_read(pflib::tgt_DAQ_Control,6); - printf(" EVB Debug word: %08x\n",reg1); - reg1=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,1); - reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,4); - printf(" Event buffer Debug word: %08x %08x\n",reg1,reg2); - - printf("-----Full event buffer-----\n"); - reg1=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,1); - reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,2); printf(" Read Page: %d Write Page : %d Full: %d Empty: %d Evt Length on current page: %d\n",(reg1>>13)&0x1,(reg1>>12)&0x1,(reg1>>15)&0x1,(reg1>>14)&0x1,(reg1>>0)&0xFFF); - printf(" Spy page : %d Spy-as-source : %d Length-of-spy-injected-event : %d\n",reg2&0x1,(reg2>>1)&0x1,(reg2>>16)&0xFFF); - } - if (cmd=="FULL_DEBUG") { - uint32_t reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,2); - reg2=reg2^0x2;// invert - pft->wb->wb_write(pflib::tgt_DAQ_Outbuffer,2,reg2); - } - if (cmd=="DISABLE_ROCLINKS") { - uint32_t reg=pft->wb->wb_read(pflib::tgt_DAQ_Control,1); - reg=reg^0x80000000u;// invert - pft->wb->wb_write(pflib::tgt_DAQ_Control,1,reg); - } - if (cmd=="FULL_SEND") { - uint32_t reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,2); - reg2=reg2|0x1000;// set the send bit - pft->wb->wb_write(pflib::tgt_DAQ_Outbuffer,2,reg2); - } - if (cmd=="ROC_SEND") { - uint32_t reg2=pft->wb->wb_read(pflib::tgt_DAQ_Control,1); - reg2=reg2|0x40000000;// set the send bit - pft->wb->wb_write(pflib::tgt_DAQ_Control,1,reg2); - } - if (cmd=="FULL_LOAD") { - std::vector data=read_words_from_file(); - - // set the spy page to match the read page - uint32_t reg1=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,1); - uint32_t reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,2); - int rpage=(reg1>>12)&0x1; - if (rpage) reg2=reg2|0x1; - else reg2=reg2&0xFFFFFFFEu; - pft->wb->wb_write(pflib::tgt_DAQ_Outbuffer,2,reg2); - - for (size_t i=0; iwb->wb_write(pflib::tgt_DAQ_Outbuffer,0x1000+i,data[i]); - - /// set the length - reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,2); - reg2=reg2&0xFFFF;// remove the upper bits - reg2=reg2|(data.size()<<16); - pft->wb->wb_write(pflib::tgt_DAQ_Outbuffer,2,reg2); - } - if (cmd=="IBSPY") { - static int input=0; - input=BaseMenu::readline_int("Which input?",input); - uint32_t reg=pft->wb->wb_read(pflib::tgt_DAQ_Inbuffer,(input<<7)|3); - int rp=BaseMenu::readline_int("Read page?",(reg>>16)&0xF); - reg=reg&0xFFFFFFF0u; - reg=reg|(rp&0xF); - pft->wb->wb_write(pflib::tgt_DAQ_Inbuffer,((input<<7)|3),reg); - for (int i=0; i<40; i++) { - uint32_t val=pft->wb->wb_read(pflib::tgt_DAQ_Inbuffer,(input<<7)|0x40|i); - printf("%2d %08x\n",i,val); - } - } - if (cmd=="EFSPY") { - static int input=0; - input=BaseMenu::readline_int("Which input?",input); - pft->wb->wb_write(pflib::tgt_DAQ_LinkFmt,(input<<7)|3,0); - uint32_t reg=pft->wb->wb_read(pflib::tgt_DAQ_LinkFmt,(input<<7)|4); - printf("PTRs now: 0x%08x\n",reg); - int rp=BaseMenu::readline_int("Read page?",reg&0xF); - for (int i=0; i<40; i++) { - pft->wb->wb_write(pflib::tgt_DAQ_LinkFmt,(input<<7)|3,0x400|(rp<<6)|i); - uint32_t val=pft->wb->wb_read(pflib::tgt_DAQ_LinkFmt,(input<<7)|4); - printf("%2d %08x\n",i,val); - } - pft->wb->wb_write(pflib::tgt_DAQ_LinkFmt,(input<<7)|3,0); - } - if (cmd=="SPY") { - // set the spy page to match the read page - uint32_t reg1=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,1); - uint32_t reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,2); - int rpage=(reg1>>12)&0x1; - if (rpage) reg2=reg2|0x1; - else reg2=reg2&0xFFFFFFFEu; - pft->wb->wb_write(pflib::tgt_DAQ_Outbuffer,2,reg2); - - for (size_t i=0; i<32; i++) { - uint32_t val=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,0x1000|i); - printf("%04d %08x\n",int(i),val); - } - } - - if (cmd=="ROC_LOAD") { - std::vector data=read_words_from_file(); - if (int(data.size())!=PolarfireTarget::NLINKS*40) { - printf("Expected %d words, got only %d\n",PolarfireTarget::NLINKS*40,int(data.size())); - return; - } - for (int ilink=0; ilinkwb->wb_read(pflib::tgt_DAQ_Inbuffer,(ilink<<7)+3); - int rpage=(reg>>16)&0xF; - reg=(reg&0xFFFFF000u)|rpage|(40<<4); - pft->wb->wb_write(pflib::tgt_DAQ_Inbuffer,(ilink<<7)+3,reg); - // load the bytes - for (int i=0; i<40; i++) - pft->wb->wb_write(pflib::tgt_DAQ_Inbuffer,(ilink<<7)|0x40|i,data[40*ilink+i]); - } - } -} - - /** * Menu construction for pftool * diff --git a/tool/pftool_daq.cc b/tool/pftool_daq.cc index 1b6a9fed..ea47b806 100644 --- a/tool/pftool_daq.cc +++ b/tool/pftool_daq.cc @@ -1,10 +1,35 @@ #include "pftool_daq.h" - +using pflib::PolarfireTarget; std::string last_run_file=".last_run_file"; std::string start_dma_cmd=""; std::string stop_dma_cmd=""; + +std::vector read_words_from_file() +{ + std::vector data; + /// load from file + std::string fname=BaseMenu::readline("Read from text file (line by line hex 32-bit words)"); + char buffer[512]; + FILE* f=fopen(fname.c_str(),"r"); + if (f==0) { + printf("Unable to open '%s'\n",fname.c_str()); + return data; + } + while (!feof(f)) { + buffer[0]=0; + fgets(buffer,511,f); + if (strlen(buffer)<8 || strchr(buffer,'#')!=0) continue; + uint32_t val; + val=strtoul(buffer,0,16); + data.push_back(val); + printf("%08x\n",val); + } + fclose(f); + return data; +} + void daq( const std::string& cmd, PolarfireTarget* pft ) { pflib::DAQ& daq=pft->hcal.daq(); @@ -229,3 +254,202 @@ void daq( const std::string& cmd, PolarfireTarget* pft ) } } } +void daq_debug( const std::string& cmd, pflib::PolarfireTarget* pft ) +{ + if (cmd=="STATUS") { + // get the general status + daq("STATUS", pft); + uint32_t reg1,reg2; + printf("-----Per-ROC Controls-----\n"); + reg1=pft->wb->wb_read(pflib::tgt_DAQ_Control,1); + printf(" Disable ROC links: %s\n",(reg1&0x80000000u)?("TRUE"):("FALSE")); + + printf(" Link F E RP WP \n"); + for (int ilink=0; ilinkwb->wb_read(pflib::tgt_DAQ_Inbuffer,(ilink<<7)|3); + printf(" %2d %d %d %2d %2d %08x\n",ilink,(reg>>26)&1,(reg>>27)&1,(reg>>16)&0xf,(reg>>12)&0xf,reg); + } + printf("-----Event builder -----\n"); + reg1=pft->wb->wb_read(pflib::tgt_DAQ_Control,6); + printf(" EVB Debug word: %08x\n",reg1); + reg1=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,1); + reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,4); + printf(" Event buffer Debug word: %08x %08x\n",reg1,reg2); + + printf("-----Full event buffer-----\n"); + reg1=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,1); + reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,2); printf(" Read Page: %d Write Page : %d Full: %d Empty: %d Evt Length on current page: %d\n",(reg1>>13)&0x1,(reg1>>12)&0x1,(reg1>>15)&0x1,(reg1>>14)&0x1,(reg1>>0)&0xFFF); + printf(" Spy page : %d Spy-as-source : %d Length-of-spy-injected-event : %d\n",reg2&0x1,(reg2>>1)&0x1,(reg2>>16)&0xFFF); + } + if (cmd=="FULL_DEBUG") { + uint32_t reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,2); + reg2=reg2^0x2;// invert + pft->wb->wb_write(pflib::tgt_DAQ_Outbuffer,2,reg2); + } + if (cmd=="DISABLE_ROCLINKS") { + uint32_t reg=pft->wb->wb_read(pflib::tgt_DAQ_Control,1); + reg=reg^0x80000000u;// invert + pft->wb->wb_write(pflib::tgt_DAQ_Control,1,reg); + } + if (cmd=="FULL_SEND") { + uint32_t reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,2); + reg2=reg2|0x1000;// set the send bit + pft->wb->wb_write(pflib::tgt_DAQ_Outbuffer,2,reg2); + } + if (cmd=="ROC_SEND") { + uint32_t reg2=pft->wb->wb_read(pflib::tgt_DAQ_Control,1); + reg2=reg2|0x40000000;// set the send bit + pft->wb->wb_write(pflib::tgt_DAQ_Control,1,reg2); + } + if (cmd=="FULL_LOAD") { + std::vector data=read_words_from_file(); + + // set the spy page to match the read page + uint32_t reg1=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,1); + uint32_t reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,2); + int rpage=(reg1>>12)&0x1; + if (rpage) reg2=reg2|0x1; + else reg2=reg2&0xFFFFFFFEu; + pft->wb->wb_write(pflib::tgt_DAQ_Outbuffer,2,reg2); + + for (size_t i=0; iwb->wb_write(pflib::tgt_DAQ_Outbuffer,0x1000+i,data[i]); + + /// set the length + reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,2); + reg2=reg2&0xFFFF;// remove the upper bits + reg2=reg2|(data.size()<<16); + pft->wb->wb_write(pflib::tgt_DAQ_Outbuffer,2,reg2); + } + if (cmd=="IBSPY") { + static int input=0; + input=BaseMenu::readline_int("Which input?",input); + uint32_t reg=pft->wb->wb_read(pflib::tgt_DAQ_Inbuffer,(input<<7)|3); + int rp=BaseMenu::readline_int("Read page?",(reg>>16)&0xF); + reg=reg&0xFFFFFFF0u; + reg=reg|(rp&0xF); + pft->wb->wb_write(pflib::tgt_DAQ_Inbuffer,((input<<7)|3),reg); + for (int i=0; i<40; i++) { + uint32_t val=pft->wb->wb_read(pflib::tgt_DAQ_Inbuffer,(input<<7)|0x40|i); + printf("%2d %08x\n",i,val); + } + } + if (cmd=="EFSPY") { + static int input=0; + input=BaseMenu::readline_int("Which input?",input); + pft->wb->wb_write(pflib::tgt_DAQ_LinkFmt,(input<<7)|3,0); + uint32_t reg=pft->wb->wb_read(pflib::tgt_DAQ_LinkFmt,(input<<7)|4); + printf("PTRs now: 0x%08x\n",reg); + int rp=BaseMenu::readline_int("Read page?",reg&0xF); + for (int i=0; i<40; i++) { + pft->wb->wb_write(pflib::tgt_DAQ_LinkFmt,(input<<7)|3,0x400|(rp<<6)|i); + uint32_t val=pft->wb->wb_read(pflib::tgt_DAQ_LinkFmt,(input<<7)|4); + printf("%2d %08x\n",i,val); + } + pft->wb->wb_write(pflib::tgt_DAQ_LinkFmt,(input<<7)|3,0); + } + if (cmd=="SPY") { + // set the spy page to match the read page + uint32_t reg1=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,1); + uint32_t reg2=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,2); + int rpage=(reg1>>12)&0x1; + if (rpage) reg2=reg2|0x1; + else reg2=reg2&0xFFFFFFFEu; + pft->wb->wb_write(pflib::tgt_DAQ_Outbuffer,2,reg2); + + for (size_t i=0; i<32; i++) { + uint32_t val=pft->wb->wb_read(pflib::tgt_DAQ_Outbuffer,0x1000|i); + printf("%04d %08x\n",int(i),val); + } + } + + if (cmd=="ROC_LOAD") { + std::vector data=read_words_from_file(); + if (int(data.size())!=PolarfireTarget::NLINKS*40) { + printf("Expected %d words, got only %d\n",PolarfireTarget::NLINKS*40,int(data.size())); + return; + } + for (int ilink=0; ilinkwb->wb_read(pflib::tgt_DAQ_Inbuffer,(ilink<<7)+3); + int rpage=(reg>>16)&0xF; + reg=(reg&0xFFFFF000u)|rpage|(40<<4); + pft->wb->wb_write(pflib::tgt_DAQ_Inbuffer,(ilink<<7)+3,reg); + // load the bytes + for (int i=0; i<40; i++) + pft->wb->wb_write(pflib::tgt_DAQ_Inbuffer,(ilink<<7)|0x40|i,data[40*ilink+i]); + } + } +} + +void daq_setup( const std::string& cmd, pflib::PolarfireTarget* pft ) +{ + pflib::DAQ& daq=pft->hcal.daq(); + if (cmd=="STATUS") { + pft->daqStatus(std::cout); +#ifdef PFTOOL_ROGUE + auto rwbi=dynamic_cast(pft->wb); + if (rwbi) { + bool enabled; + uint8_t samples_per_event, fpgaid_i; + rwbi->daq_get_dma_setup(fpgaid_i,samples_per_event, enabled); + printf("DMA : %s Status=%08x\n",(enabled)?("ENABLED"):("DISABLED"),rwbi->daq_dma_status()); + } +#endif + } + if (cmd=="ENABLE") { + daq.enable(!daq.enabled()); + } + if (cmd=="ZS") { + int jlink=BaseMenu::readline_int("Which link (-1 for all)? ",-1); + bool fullSuppress=BaseMenu::readline_bool("Suppress all channels? ",false); + pft->enableZeroSuppression(jlink,fullSuppress); + } + if (cmd=="L1APARAMS") { + int ilink=BaseMenu::readline_int("Which link? ",-1); + if (ilink>=0) { + uint32_t reg1=pft->wb->wb_read(pflib::tgt_DAQ_Inbuffer,(ilink<<7)|1); + int delay=BaseMenu::readline_int("L1A delay? ",(reg1>>8)&0xFF); + int capture=BaseMenu::readline_int("L1A capture length? ",(reg1>>16)&0xFF); + reg1=(reg1&0xFF)|((delay&0xFF)<<8)|((capture&0xFF)<<16); + pft->wb->wb_write(pflib::tgt_DAQ_Inbuffer,(ilink<<7)|1,reg1); + } + } + if (cmd=="DMA") { +#ifdef PFTOOL_ROGUE + auto rwbi=dynamic_cast(pft->wb); + if (rwbi) { + bool enabled; + uint8_t samples_per_event, fpgaid_i; + rwbi->daq_get_dma_setup(fpgaid_i,samples_per_event, enabled); + enabled=BaseMenu::readline_bool("Enable DMA? ",enabled); + rwbi->daq_dma_enable(enabled); + } else { + std::cout << "\nNot connected to chip with RogueWishboneInterface, cannot activate DMA.\n" << std::endl; + } +#endif + } + if (cmd=="STANDARD") { + daq_setup("FPGA",pft); + pflib::Elinks& elinks=pft->hcal.elinks(); + for (int i=0; i(pft->wb); + if (rwbi) { + bool enabled; + uint8_t samples_per_event, fpgaid_i; + rwbi->daq_get_dma_setup(fpgaid_i,samples_per_event, enabled); + fpgaid_i=(uint8_t(fpgaid)); + rwbi->daq_dma_setup(fpgaid_i,samples_per_event); + } +#endif + } +} diff --git a/tool/pftool_daq.h b/tool/pftool_daq.h index 3e28e29e..fafd696e 100644 --- a/tool/pftool_daq.h +++ b/tool/pftool_daq.h @@ -11,12 +11,16 @@ #ifdef PFTOOL_UHAL #include "pflib/uhal/uhalWishboneInterface.h" #endif -using pflib::PolarfireTarget; extern std::string last_run_file; extern std::string start_dma_cmd; extern std::string stop_dma_cmd; +/** + * Print data words from raw binary file and return them + * @return vector of 32-bit data words in file + */ +std::vector read_words_from_file(); /** * DAQ menu commands, DOES NOT include sub-menu commands * @@ -36,7 +40,44 @@ extern std::string stop_dma_cmd; * @param[in] cmd command selected from menu * @param[in] pft active target */ -void daq( const std::string& cmd, PolarfireTarget* pft ); +void daq( const std::string& cmd, pflib::PolarfireTarget* pft ); + +/** + * DAQ->SETUP menu commands + * + * Before doing any of the commands, we retrieve a reference to the daq + * object via pflib::Hcal::daq. + * + * ## Commands + * - STATUS : pflib::PolarfireTarget::daqStatus + * and pflib::rogue::RogueWishboneInterface::daq_dma_status if connected in that manner + * - ENABLE : toggle whether daq is enabled pflib::DAQ::enable and pflib::DAQ::enabled + * - ZS : pflib::PolarfireTarget::enableZeroSuppression + * - L1APARAMS : Use target's wishbone interface to set the L1A delay and capture length + * Uses pflib::tgt_DAQ_Inbuffer + * - DMA : enable DMA readout pflib::rogue::RogueWishboneInterface::daq_dma_enable + * - FPGA : Set the polarfire FPGA ID number (pflib::DAQ::setIds) and pass this + * to DMA setup if it is enabled + * - STANDARD : Do FPGA command and setup links that are + * labeled as active (pflib::DAQ::setupLink) + * + * @param[in] cmd selected command from DAQ->SETUP menu + * @param[in] pft active target + */ +void daq_setup( const std::string& cmd, pflib::PolarfireTarget* pft ); + +/** + * DAQ->DEBUG menu commands + * + * @note These commands have been archived since further development of pflib + * has progressed. They are still available in this submenu; however, + * they should only be used by an expert who is familiar with the chip + * and has looked at what the commands do in the code. + * + * @param[in] cmd selected command from menu + * @param[in] pft active target + */ +void daq_debug( const std::string& cmd, pflib::PolarfireTarget* pft ); #endif /* PFTOOL_DAQ_H */ From d1f80a400063d20c05740601115207492eaef677 Mon Sep 17 00:00:00 2001 From: desk-fish Date: Mon, 11 Apr 2022 17:53:44 +0200 Subject: [PATCH 20/21] Don't forget about adding the new code :) --- tool/pftool_elinks.cc | 98 +++++++++++++++++++++++++++++++++++++++++++ tool/pftool_elinks.h | 2 + 2 files changed, 100 insertions(+) diff --git a/tool/pftool_elinks.cc b/tool/pftool_elinks.cc index e06c308c..2fe8b64d 100644 --- a/tool/pftool_elinks.cc +++ b/tool/pftool_elinks.cc @@ -1,6 +1,100 @@ #include "pftool_elinks.h" using pflib::PolarfireTarget; +void align_elinks(PolarfireTarget* pft, pflib::Elinks& elinks) { + const int nevents=10; + + int delay_step = BaseMenu::readline_int("Delay step: ",delay_step); + + int nsamples=1; + { + bool multi; + int nextra; + pft->hcal.fc().getMultisampleSetup(multi,nextra); + if (multi) nsamples=nextra+1; + } + + int bitslip_candidate[8] = {0,0,0,0,0,0,0,0}; + int delay_candidate[8] = {0,0,0,0,0,0,0,0}; + int record_bx[8] = {0,0,0,0,0,0,0,0}; + int record_idle[8] = {0,0,0,0,0,0,0,0}; + + pft->prepareNewRun(); + + for(int bitslip = 0; bitslip <= 7; bitslip += 1){ + std::cout << "Scanning bitslip: " << bitslip << std::endl; + for(int delay = 0; delay <= 128; delay += delay_step){ + for(int jlink = 0; jlink < 8; jlink++){ + elinks.setDelay(jlink,delay); + elinks.setBitslipAuto(jlink,false); + elinks.setBitslip(jlink,bitslip); + } + int n_good_bxheaders[8] = {0,0,0,0,0,0,0,0}; + int n_bad_bxheaders[8] = {0,0,0,0,0,0,0,0}; + int n_good_idles[8] = {0,0,0,0,0,0,0,0}; + int n_bad_idles[8] = {0,0,0,0,0,0,0,0}; + for (int ievt{0}; ievt < nevents; ievt++) { + pft->backend->fc_sendL1A(); + std::vector event_raw = pft->daqReadEvent(); + pflib::decoding::SuperPacket event{&(event_raw[0]), int(event_raw.size())}; + for (int s{0}; s < nsamples; s++) { + for(int jlink = 0; jlink < 8; jlink++){ + auto packet = event.sample(s).roc(jlink); + if (packet.length() > 2) { + if (event.sample(s).roc(jlink).good_bxheader()) n_good_bxheaders[jlink]++; + else n_bad_bxheaders[jlink]++; + if (event.sample(s).roc(jlink).good_idle()) n_good_idles[jlink]++; + else n_bad_idles[jlink]++; + } + } + } + } + for(int i = 0; i < 8; i++){ + if(n_good_idles[i] >= record_idle[i] && n_good_bxheaders[i] >= record_bx[i]){ + record_bx[i] = n_good_bxheaders[i]; + record_idle[i] = n_good_idles[i]; + bitslip_candidate[i] = bitslip; + delay_candidate[i] = delay; + } + } + + /* + for(int jlink = 0; jlink < 8; jlink++){ + std::cout << n_good_bxheaders[jlink] << ":" << n_good_idles[jlink] << " "; + } + std::cout << std::endl; + */ + } + } + std::cout << "Candidates" << std::endl; + for(int i = 0; i < 8; i++){ + std::cout << "Link " << i << std::endl; + std::cout << "Bitslip: " << bitslip_candidate[i] << " Delay: " << delay_candidate[i] << std::endl; + + elinks.setDelay(i,delay_candidate[i]); + elinks.setBitslipAuto(i,false); + elinks.setBitslip(i,bitslip_candidate[i]); + + float bg_bxheaders = 1.; + int bad_bxheaders = nsamples*nevents-record_bx[i]; + if (record_bx[i]>0) + bg_bxheaders = float(bad_bxheaders)/ + (record_bx[i]+bad_bxheaders); + std::cout << "Percentage of bad BX headers: " << bg_bxheaders*100. << std::endl; + if(bg_bxheaders > 0.1){ + std::cout << "Consider a PLL hard_reset" << std::endl; + } + float bg_idles = 1.; + int bad_idles = nsamples*nevents-record_idle[i]; + if (record_idle[i]>0) + bg_idles = float(bad_idles)/ + (record_idle[i]+bad_idles); + std::cout << "Percentage of bad idles: " << bg_idles*100. << std::endl; + if(bg_idles > 0.1){ + std::cout << "Consider a PLL hard_reset" << std::endl; + } + } +} void elinks( const std::string& cmd, PolarfireTarget* pft ) { @@ -19,6 +113,10 @@ void elinks( const std::string& cmd, PolarfireTarget* pft ) for (size_t i=0; i Date: Mon, 11 Apr 2022 11:28:40 -0500 Subject: [PATCH 21/21] remove extra copy of ELINKS.ALIGN --- tool/pftool_elinks.cc | 94 ------------------------------------------- 1 file changed, 94 deletions(-) diff --git a/tool/pftool_elinks.cc b/tool/pftool_elinks.cc index 0bf8183a..2fe8b64d 100644 --- a/tool/pftool_elinks.cc +++ b/tool/pftool_elinks.cc @@ -167,100 +167,6 @@ void elinks( const std::string& cmd, PolarfireTarget* pft ) n_good_idles[ilink], n_bad_idles[ilink], bg_idles); } } - if (cmd=="ALIGN") { - nevents=10; - - int delay_step = BaseMenu::readline_int("Delay step: ",delay_step); - - int nsamples=1; - { - bool multi; - int nextra; - pft->hcal.fc().getMultisampleSetup(multi,nextra); - if (multi) nsamples=nextra+1; - } - - int bitslip_candidate[8] = {0,0,0,0,0,0,0,0}; - int delay_candidate[8] = {0,0,0,0,0,0,0,0}; - int record_bx[8] = {0,0,0,0,0,0,0,0}; - int record_idle[8] = {0,0,0,0,0,0,0,0}; - - pft->prepareNewRun(); - - for(int bitslip = 0; bitslip <= 7; bitslip += 1){ - std::cout << "Scanning bitslip: " << bitslip << std::endl; - for(int delay = 0; delay <= 128; delay += delay_step){ - for(int jlink = 0; jlink < 8; jlink++){ - elinks.setDelay(jlink,delay); - elinks.setBitslipAuto(jlink,false); - elinks.setBitslip(jlink,bitslip); - } - int n_good_bxheaders[8] = {0,0,0,0,0,0,0,0}; - int n_bad_bxheaders[8] = {0,0,0,0,0,0,0,0}; - int n_good_idles[8] = {0,0,0,0,0,0,0,0}; - int n_bad_idles[8] = {0,0,0,0,0,0,0,0}; - for (int ievt{0}; ievt < nevents; ievt++) { - pft->backend->fc_sendL1A(); - std::vector event_raw = pft->daqReadEvent(); - pflib::decoding::SuperPacket event{&(event_raw[0]), int(event_raw.size())}; - for (int s{0}; s < nsamples; s++) { - for(int jlink = 0; jlink < 8; jlink++){ - auto packet = event.sample(s).roc(jlink); - if (packet.length() > 2) { - if (event.sample(s).roc(jlink).good_bxheader()) n_good_bxheaders[jlink]++; - else n_bad_bxheaders[jlink]++; - if (event.sample(s).roc(jlink).good_idle()) n_good_idles[jlink]++; - else n_bad_idles[jlink]++; - } - } - } - } - for(int i = 0; i < 8; i++){ - if(n_good_idles[i] >= record_idle[i] && n_good_bxheaders[i] >= record_bx[i]){ - record_bx[i] = n_good_bxheaders[i]; - record_idle[i] = n_good_idles[i]; - bitslip_candidate[i] = bitslip; - delay_candidate[i] = delay; - } - } - - /* - for(int jlink = 0; jlink < 8; jlink++){ - std::cout << n_good_bxheaders[jlink] << ":" << n_good_idles[jlink] << " "; - } - std::cout << std::endl; - */ - } - } - std::cout << "Candidates" << std::endl; - for(int i = 0; i < 8; i++){ - std::cout << "Link " << i << std::endl; - std::cout << "Bitslip: " << bitslip_candidate[i] << " Delay: " << delay_candidate[i] << std::endl; - - elinks.setDelay(i,delay_candidate[i]); - elinks.setBitslipAuto(i,false); - elinks.setBitslip(i,bitslip_candidate[i]); - - float bg_bxheaders = 1.; - int bad_bxheaders = nsamples*nevents-record_bx[i]; - if (record_bx[i]>0) - bg_bxheaders = float(bad_bxheaders)/ - (record_bx[i]+bad_bxheaders); - std::cout << "Percentage of bad BX headers: " << bg_bxheaders*100. << std::endl; - if(bg_bxheaders > 0.1){ - std::cout << "Consider a PLL hard_reset" << std::endl; - } - float bg_idles = 1.; - int bad_idles = nsamples*nevents-record_idle[i]; - if (record_idle[i]>0) - bg_idles = float(bad_idles)/ - (record_idle[i]+bad_idles); - std::cout << "Percentage of bad idles: " << bg_idles*100. << std::endl; - if(bg_idles > 0.1){ - std::cout << "Consider a PLL hard_reset" << std::endl; - } - } - } if (cmd=="BITSLIP") { ilink=BaseMenu::readline_int("Which elink? ",ilink); int bitslip=BaseMenu::readline_int("Bitslip value (-1 for auto): ",elinks.getBitslip(ilink));