diff --git a/Makefile.in b/Makefile.in index fe1d3a1ff672d5ab5084e74d97cd292eb7fbef76..8a460ae0ed51c85f3cb93b62d40f09b23bbe1c4b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -46,6 +46,7 @@ DEVFLAGS=@DEVFLAGS@ @/bin/mkdir -p build/$@epics @/bin/mv -f build/$@epics-medm build/$@epics/medm @/bin/mv -f build/$@epics-config build/$@epics/config +ifndef RCG_BUILD_NO_KOBJ @echo Building front-end Linux kernel module $@... @make -sC src/fe/$@ clean # copy IOP symbol file to build area if found @@ -60,10 +61,13 @@ DEVFLAGS=@DEVFLAGS@ @make -C src/fe/$@ >> $@.log 2>>$@_error.log || (tail $@.log; cat $@_error.log && /bin/false) @$(srcdir)/src/epics/util/checkUndefined.pl $@_error.log >> $@.log 2>>$@_error.log || (tail $@.log; cat $@_error.log && /bin/false) @echo Done -# @echo Building front-end user space object $@... -# @/bin/rm -rf src/fe/$@_usp/*.o ; -# @make -C src/fe/$@_usp >> $@.log 2>>$@_error.log || (tail $@.log; cat $@_error.log && /bin/false) -# @echo Done +endif +ifdef RCG_BUILD_USP + @echo Building front-end user space object $@... + @/bin/rm -rf src/fe/$@_usp/*.o ; + @make -C src/fe/$@_usp >> $@.log 2>>$@_error.log || (tail $@.log; cat $@_error.log && /bin/false) + @echo Done +endif @/bin/mkdir -p target/$@epics/src @echo $(srcdir) > target/$@epics/src/rcg_location.txt @echo Build date `date` > target/$@epics/src/build.txt diff --git a/NEWS b/NEWS index c2ff98d1fa0cdc7968bb8dae0ebfeee90ccc223a..25c3212c1a95e793e0826bf4a434eda2654b0f62 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,13 @@ ================================================================================================== +Changes for 4.0.2 +================================================================================================== +- RCG I/O module mapping modified to allow DAC models to appear in any order on the bus. (issue #150) +- Fix for ANU new 'N' site setting (Issue #117) +- Fix to rtcds stop --all to stop IOP model last +- Various changes to clear all RCG code gcc compile warnings (Issue #147) +- Modified Parameters.pm to perform proper checking for Parameter block entreis. (Issue #155) +- Enabled user space code compile with RCG_BUILD_USP compile argument +================================================================================================== Changes for 4.0.1 ================================================================================================== - Minor fix to the daq_wiper.py script, so that it does not crash when a free size is specified. diff --git a/src/drv/fmReadCoeff.c b/src/drv/fmReadCoeff.c index c5f1bcde896c5e4c1876e8e5d5b4891499245643..bfbfe7ed022e7d3ae5b3bbd9cc7a1dfdec65855f 100644 --- a/src/drv/fmReadCoeff.c +++ b/src/drv/fmReadCoeff.c @@ -31,6 +31,9 @@ #include "fmReadCoeff.h" #include "crc.h" +int getwords(char *, char *[], int ); +extern int checkFileCrc(char *); + /* Cat string and make upper case */ static char *strcat_upper(char *dest, char *src) { char *d = dest; diff --git a/src/drv/mbuf/mbuf.c b/src/drv/mbuf/mbuf.c index 0a45ce097c17c1a750aee2531854f4e687bb12cc..37414251b65244c695777e91ea3ccfd26b7a7792 100644 --- a/src/drv/mbuf/mbuf.c +++ b/src/drv/mbuf/mbuf.c @@ -42,6 +42,11 @@ static struct class* mbuf_class = NULL; static struct device* mbuf_device = NULL; static struct cdev mbuf_cdev; +#define CDS_LOCAL_MBUF_SETTINGS_BUFFER_SIZE 10 + +atomic_t mbuf_verbosity = ATOMIC_INIT(0); + + /* methods of the character device */ static int mbuf_open(struct inode *inode, struct file *filp); static int mbuf_release(struct inode *inode, struct file *filp); @@ -99,7 +104,10 @@ static DEFINE_SPINLOCK(lock); int mbuf_release_area(char *name, struct file *file) { int i; - printk(KERN_INFO " mbuf_release_area %s\n", name); + if ((int)atomic_read(&mbuf_verbosity) > 0) { + printk(KERN_INFO + " mbuf_release_area %s\n", name); + } spin_lock(&lock); // See if allocated for (i = 0; i < MAX_AREAS; i++) { @@ -230,8 +238,8 @@ int mbuf_allocate_area(char *name, int size, struct file *file) { //rkfree(kmalloc_area[i], s); //kmalloc_area[i] = 0; if (kmalloc_area[i] == 0) { - printk("malloc() failed\n"); - spin_unlock(&lock); + spin_unlock(&lock); + printk("malloc() failed\n"); return -1; } @@ -309,14 +317,20 @@ static int mbuf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, { int res; int mod = 0; - struct mbuf_request_struct req; + int verbose = 0; + struct mbuf_request_struct req; void __user *argp = (void __user *)arg; - printk(KERN_INFO "mbuf_ioctl: command=%d\n", cmd); - switch(cmd){ - case IOCTL_MBUF_ALLOCATE: + verbose = (int)atomic_read(&mbuf_verbosity); + + if (verbose > 0) { + printk(KERN_INFO + "mbuf_ioctl: command=%d\n", cmd); + } + switch(cmd){ + case IOCTL_MBUF_ALLOCATE: { - if (copy_from_user (&req, (void *) argp, sizeof (req))) { + if (copy_from_user (&req, (void *) argp, sizeof (req))) { return -EFAULT; } // the size should be a multiple of page size @@ -324,7 +338,10 @@ static int mbuf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (mod != 0) { req.size += PAGE_SIZE - mod; } - printk(KERN_INFO "mbuf_ioctl: name:%.32s, size:%d, cmd:%d, file:%p\n", req.name, (int)req.size, cmd, file); + if (verbose > 0) { + printk(KERN_INFO + "mbuf_ioctl: name:%.32s, size:%d, cmd:%d, file:%p\n", req.name, (int) req.size, cmd, file); + } res = mbuf_allocate_area(req.name, req.size, file); if (res >= 0) { return kmalloc_area_size[res]; @@ -333,12 +350,12 @@ static int mbuf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } } break; - case IOCTL_MBUF_DEALLOCATE: + case IOCTL_MBUF_DEALLOCATE: { if (copy_from_user (&req, (void *) argp, sizeof (req))) { return -EFAULT; } - //printk("mbuf_ioctl: name:%.32s, size:%d, cmd:%d, file:%p\n", req.name, req.size, cmd, file); + //printk("mbuf_ioctl: name:%.32s, size:%d, cmd:%d, file:%p\n", req.name, req.size, cmd, file); res = mbuf_release_area(req.name, file); if (res >= 0) { return 0; @@ -348,7 +365,7 @@ static int mbuf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } break; - case IOCTL_MBUF_INFO: + case IOCTL_MBUF_INFO: #if 0 for (i = 0; i < MAX_AREAS; i++) { if (kmalloc_area[i]) { @@ -361,8 +378,8 @@ static int mbuf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, break; default: return -EINVAL; - } - return -EINVAL; + } + return -EINVAL; } static ssize_t mbuf_sysfs_status(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { @@ -389,15 +406,44 @@ static ssize_t mbuf_sysfs_status(struct kobject *kobj, struct kobj_attribute *at return count; } +static ssize_t mbuf_sysfs_verbosity_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { + int new_verbosity = 0; + char localbuf[CDS_LOCAL_MBUF_SETTINGS_BUFFER_SIZE+1]; + int conv_ret = 0; + + memset(localbuf, 0, CDS_LOCAL_MBUF_SETTINGS_BUFFER_SIZE+1); + if (count >= CDS_LOCAL_MBUF_SETTINGS_BUFFER_SIZE) { + printk("mbuf_sysfs_verbosity_store called with too much input, ignoring the value"); + return -EFAULT; + } + memcpy(localbuf, buf, count); + localbuf[count] ='\0'; + + + if ((conv_ret = kstrtoint(localbuf, 10, &new_verbosity)) != 0) { + printk("mbuf_sysfs_verbosity_store error converting verbosity into an integer - %s %d", (conv_ret == -ERANGE ? "range" : "overflow"), conv_ret); + return -EFAULT; + } + atomic_set(&mbuf_verbosity, new_verbosity); + return (ssize_t) count; +} + +static ssize_t mbuf_sysfs_verbosity_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { + return sprintf(buf, "%d\n", (int)atomic_read(&mbuf_verbosity)); +} + + /* sysfs related structures */ static struct kobject *mbuf_sysfs_dir = NULL; /* individual sysfs debug attributes */ static struct kobj_attribute sysfs_mbuf_status_attr = __ATTR(status, 0444, mbuf_sysfs_status, NULL); +static struct kobj_attribute sysfs_mbuf_verbosity_attr = __ATTR(verbosity, 0644, mbuf_sysfs_verbosity_show, mbuf_sysfs_verbosity_store); /* group attributes together for bulk operations */ static struct attribute *mbuf_fields[] = { &sysfs_mbuf_status_attr.attr, + &sysfs_mbuf_verbosity_attr.attr, NULL, }; diff --git a/src/drv/mbuf/mbuf_probe/CMakeLists.txt b/src/drv/mbuf/mbuf_probe/CMakeLists.txt index b27b0321b46bfe1187071c6743cb21c176bff0f5..715c84526de9b13845521d82de3b363b3743c6b5 100644 --- a/src/drv/mbuf/mbuf_probe/CMakeLists.txt +++ b/src/drv/mbuf/mbuf_probe/CMakeLists.txt @@ -4,12 +4,13 @@ add_executable(mbuf_probe mbuf_probe.cc mbuf_decoders.cc analyze_daq_multi_dc.cc - analyze_rmipc.cc) + analyze_rmipc.cc + check_size.cc) target_include_directories(mbuf_probe PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/../../include ) -target_link_libraries(mbuf_probe PUBLIC driver::shmem) +target_link_libraries(mbuf_probe PUBLIC driver::shmem driver::ini_parsing) target_requires_cpp11(mbuf_probe PRIVATE) install(TARGETS mbuf_probe DESTINATION bin) \ No newline at end of file diff --git a/src/drv/mbuf/mbuf_probe/check_size.cc b/src/drv/mbuf/mbuf_probe/check_size.cc new file mode 100644 index 0000000000000000000000000000000000000000..01301fed08d6eeefba7323d16060571f25b94c6d --- /dev/null +++ b/src/drv/mbuf/mbuf_probe/check_size.cc @@ -0,0 +1,320 @@ +// +// Created by jonathan.hanks on 8/13/20. +// + +#include "check_size.hh" + +#include <algorithm> +#include <array> +#include <fstream> +#include <iostream> + +#include "daq_core.h" +#include "daq_core_defs.h" +#include "daq_data_types.h" + +#include "daqmap.h" +extern "C" { +#include "param.h" +} + +namespace check_mbuf_sizes +{ + typedef struct ini_file_info + { + ini_file_info( ) + : dcu_sizes( ), dcu_config_crc( ), last_dcuid( 0 ), valid( true ) + { + std::fill( dcu_sizes.begin( ), dcu_sizes.end( ), 0 ); + std::fill( dcu_config_crc.begin( ), dcu_config_crc.end( ), 0 ); + } + ini_file_info( const ini_file_info& ) noexcept = default; + ini_file_info& operator=( const ini_file_info& ) noexcept = default; + + std::array< unsigned int, DAQ_TRANSIT_MAX_DCU > dcu_sizes; + std::array< unsigned long, DAQ_TRANSIT_MAX_DCU > dcu_config_crc; + int last_dcuid; + bool valid; + } size_info; + + int + channel_callback( char* channel_name, + struct CHAN_PARAM* params, + void* user ) + { + auto* info = reinterpret_cast< ini_file_info* >( user ); + int chan_size = data_type_size( params->datatype ) * + ( params->datarate / DAQ_NUM_DATA_BLOCKS_PER_SECOND ); + if ( chan_size == 0 ) + { + info->valid = false; + } + else + { + info->dcu_sizes[ params->dcuid ] += chan_size; + } + info->last_dcuid = params->dcuid; + return 1; + } + + ini_file_info + load_master( const std::string& fname ) + { + ini_file_info sysinfo; + // File names are specified in `master_config' file + std::ifstream mcf( fname ); + + for ( std::string line; std::getline( mcf, line ); ) + { + std::string trimmed_line; + trimmed_line.reserve( line.size( ) ); + std::copy_if( line.begin( ), + line.end( ), + std::back_inserter( trimmed_line ), + []( const char ch ) -> bool { return ch != ' '; } ); + if ( line.front( ) == '#' ) + { + continue; + } + if ( trimmed_line.empty( ) || trimmed_line.front( ) == '#' ) + { + continue; + } + + std::string ext = + ( trimmed_line.size( ) > 4 + ? trimmed_line.substr( trimmed_line.size( ) - 4 ) + : "" ); + auto testpoint = ( ext == ".par" ); + + unsigned long file_crc = 0; + sysinfo.valid = true; + sysinfo.last_dcuid = -1; + int parse_status = + ::parseConfigFile( const_cast< char* >( trimmed_line.c_str( ) ), + &file_crc, + channel_callback, + testpoint, + 0, + reinterpret_cast< void* >( &sysinfo ) ); + if ( parse_status == 0 || !sysinfo.valid || sysinfo.last_dcuid < 0 ) + { + std::cerr << "Unable to process " << trimmed_line + << " either the file is invalid, bad data types, or " + "other error (" + << sysinfo.valid << ", " << sysinfo.last_dcuid + << ")\n"; + if ( sysinfo.last_dcuid >= 0 ) + { + sysinfo.dcu_sizes[ sysinfo.last_dcuid ] = 0; + } + } + else + { + sysinfo.dcu_config_crc[ sysinfo.last_dcuid ] = file_crc; + } + } + return sysinfo; + } + + int + check_size_rmipc( volatile void* buffer, + std::size_t buffer_size, + const ::ConfigOpts& options ) + { + if ( options.analysis_type != MBUF_RMIPC || + buffer_size != 64 * 1024 * 1024 ) + { + return 0; + } + + load_master( options.ini_file_fname ); + + unsigned int prev_config_crc{ 0 }; + unsigned int prev_data_size{ 0 }; + + auto header = reinterpret_cast< const volatile rmIpcStr* >( buffer ); + + ini_file_info dcu_reference; + bool noted_crc_change{ false }; + + bool have_inis = false; + if ( !options.ini_file_fname.empty( ) ) + { + dcu_reference = load_master( options.ini_file_fname ); + have_inis = true; + } + + bool first_iteration = true; + while ( true ) + { + wait_until_changed< const unsigned int, 5000 >( &header->cycle, + header->cycle ); + + auto cur_cycle = header->cycle; + auto dcuid = header->dcuId; + + if ( !first_iteration ) + { + if ( have_inis ) + { + if ( header->crc != dcu_reference.dcu_config_crc[ dcuid ] && + !noted_crc_change ) + { + std::cout + << "config change on dcu " << dcuid << " from " + << dcu_reference.dcu_config_crc[ dcuid ] << " to " + << header->crc << "\n"; + noted_crc_change = true; + } + if ( dcu_reference.dcu_sizes[ dcuid ] != + header->dataBlockSize ) + { + std::cout << "wrong data size on " << dcuid + << " expected " + << dcu_reference.dcu_sizes[ dcuid ] << " got " + << header->dataBlockSize << "\n"; + } + } + else + { + if ( prev_config_crc != header->crc && !noted_crc_change ) + { + std::cout << "config change on dcu " << dcuid + << " from " << prev_config_crc << " to " + << header->crc << "\n"; + noted_crc_change; + } + if ( prev_data_size != header->dataBlockSize ) + { + std::cout << "data size change on dcu " << dcuid + << " from " << prev_data_size << " to " + << header->dataBlockSize << "\n"; + } + } + } + prev_config_crc = header->crc; + prev_data_size = header->dataBlockSize; + + if ( first_iteration ) + { + std::cout + << "Completed the first iteration of the check_size test" + << std::endl; + first_iteration = false; + } + } + return 0; + } + + int + check_size_multi( volatile void* buffer, + std::size_t buffer_size, + const ::ConfigOpts& options ) + { + if ( !buffer || buffer_size < DAQD_MIN_SHMEM_BUFFER_SIZE || + buffer_size > DAQD_MAX_SHMEM_BUFFER_SIZE || + options.analysis_type != MBUF_DAQ_MULTI_DC ) + { + return 0; + } + + load_master( options.ini_file_fname ); + + std::array< unsigned int, DAQ_TRANSIT_MAX_DCU > prev_config_crc{}; + std::array< unsigned int, DAQ_TRANSIT_MAX_DCU > prev_data_size{}; + + std::fill( prev_config_crc.begin( ), prev_config_crc.end( ), 0 ); + std::fill( prev_data_size.begin( ), prev_data_size.end( ), 0 ); + + auto multi_header = + reinterpret_cast< const volatile daq_multi_cycle_data_t* >( + buffer ); + + ini_file_info dcu_reference; + std::array< bool, DAQ_TRANSIT_MAX_DCU > noted_crc_change{}; + std::fill( noted_crc_change.begin( ), noted_crc_change.end( ), false ); + bool have_inis = false; + if ( !options.ini_file_fname.empty( ) ) + { + dcu_reference = load_master( options.ini_file_fname ); + have_inis = true; + } + + bool first_iteration = true; + while ( true ) + { + wait_for_time_change< 5000 >( multi_header->header ); + + auto cur_cycle = multi_header->header.curCycle; + auto cycle_data_size = multi_header->header.cycleDataSize; + + auto cur_cylce_block = + reinterpret_cast< const volatile daq_multi_dcu_data_t* >( + &multi_header->dataBlock[ 0 ] + + (cycle_data_size)*cur_cycle ); + auto total_models = cur_cylce_block->header.dcuTotalModels; + + for ( auto i = 0; i < total_models; ++i ) + { + auto& cur_header = cur_cylce_block->header.dcuheader[ i ]; + auto dcuid = cur_header.dcuId; + + if ( !first_iteration ) + { + if ( have_inis ) + { + if ( cur_header.fileCrc != + dcu_reference.dcu_config_crc[ dcuid ] && + !noted_crc_change[ dcuid ] ) + { + std::cout << "config change on dcu " << dcuid + << " from " + << dcu_reference.dcu_config_crc[ dcuid ] + << " to " << cur_header.fileCrc << "\n"; + noted_crc_change[ dcuid ] = true; + } + if ( dcu_reference.dcu_sizes[ dcuid ] != + cur_header.dataBlockSize ) + { + std::cout << "wrong data size on " << dcuid + << " expected " + << dcu_reference.dcu_sizes[ dcuid ] + << " got " << cur_header.dataBlockSize + << "\n"; + } + } + else + { + if ( prev_config_crc[ dcuid ] != cur_header.fileCrc && + !noted_crc_change[ dcuid ] ) + { + std::cout << "config change on dcu " << dcuid + << " from " << prev_config_crc[ dcuid ] + << " to " << cur_header.fileCrc << "\n"; + noted_crc_change[ dcuid ]; + } + if ( prev_data_size[ dcuid ] != + cur_header.dataBlockSize ) + { + std::cout << "data size change on dcu " << dcuid + << " from " << prev_data_size[ dcuid ] + << " to " << cur_header.dataBlockSize + << "\n"; + } + } + } + prev_config_crc[ dcuid ] = cur_header.fileCrc; + prev_data_size[ dcuid ] = cur_header.dataBlockSize; + } + if ( first_iteration ) + { + std::cout + << "Completed the first iteration of the check_size test" + << std::endl; + first_iteration = false; + } + } + return 0; + } +} // namespace check_mbuf_sizes \ No newline at end of file diff --git a/src/drv/mbuf/mbuf_probe/check_size.hh b/src/drv/mbuf/mbuf_probe/check_size.hh new file mode 100644 index 0000000000000000000000000000000000000000..221135bcabd8dae941d38a75faed49a9ea0cbe83 --- /dev/null +++ b/src/drv/mbuf/mbuf_probe/check_size.hh @@ -0,0 +1,22 @@ +// +// Created by jonathan.hanks on 8/13/20. +// + +#ifndef DAQD_TRUNK_CHECK_SIZE_HH +#define DAQD_TRUNK_CHECK_SIZE_HH + +#include <cstddef> + +#include "mbuf_probe.hh" + +namespace check_mbuf_sizes +{ + int check_size_rmipc( volatile void* buffer, + std::size_t buffer_Size, + const ConfigOpts& options ); + int check_size_multi( volatile void* buffer, + std::size_t buffer_Size, + const ConfigOpts& options ); +} // namespace check_mbuf_sizes + +#endif // DAQD_TRUNK_CHECK_SIZE_HH diff --git a/src/drv/mbuf/mbuf_probe/gap_check.cc b/src/drv/mbuf/mbuf_probe/gap_check.cc index 2e1fce44fed1a34039ef7dc328aee595188c1c47..3d347959063ab93047bef265bcdecd3fb61933bf 100644 --- a/src/drv/mbuf/mbuf_probe/gap_check.cc +++ b/src/drv/mbuf/mbuf_probe/gap_check.cc @@ -2,58 +2,12 @@ // Created by jonathan.hanks on 3/13/20. // #include "gap_check.hh" -#include <chrono> -#include <daq_core.h> - -#include <sys/time.h> -#include <unistd.h> #include <iostream> +#include "mbuf_probe.hh" namespace check_gap { - static std::int64_t - time_now_ms( ) - { - timeval tv; - gettimeofday( &tv, 0 ); - return static_cast< std::uint64_t >( tv.tv_sec * 1000 + - tv.tv_usec / 1000 ); - } - - struct cycle_sample_t - { - unsigned int cycle; - unsigned int gps; - unsigned int gps_nano; - unsigned int gps_cycle; - std::uint64_t time_ms; - }; - - cycle_sample_t - wait_for_time_change( volatile daq_multi_cycle_header_t& header ) - { - cycle_sample_t results; - unsigned int cur_cycle = header.curCycle; - while ( header.curCycle == cur_cycle ) - { - usleep( 2000 ); - } - results.time_ms = time_now_ms( ); - results.cycle = header.curCycle; - - unsigned int stride = header.cycleDataSize; - volatile char* buffer_data = - reinterpret_cast< volatile char* >( &header ) + - sizeof( daq_multi_cycle_header_t ); - volatile daq_dc_data_t* daq = - reinterpret_cast< volatile daq_dc_data_t* >( - buffer_data + stride * header.curCycle ); - results.gps = daq->header.dcuheader[ 0 ].timeSec; - results.gps_nano = daq->header.dcuheader[ 0 ].timeNSec; - results.gps_cycle = daq->header.dcuheader[ 0 ].cycle; - return results; - } int check_gaps( volatile void* buffer, std::size_t buffer_size ) diff --git a/src/drv/mbuf/mbuf_probe/mbuf_probe.cc b/src/drv/mbuf/mbuf_probe/mbuf_probe.cc index 4e81684ac3808262b38f1128e3398fbd01cb3c21..e1879d55910c472e9732592555a8e1c38112b584 100644 --- a/src/drv/mbuf/mbuf_probe/mbuf_probe.cc +++ b/src/drv/mbuf/mbuf_probe/mbuf_probe.cc @@ -28,6 +28,10 @@ #include "analyze_daq_multi_dc.hh" #include "analyze_rmipc.hh" #include "gap_check.hh" +#include "check_size.hh" + +const int OK = 0; +const int ERROR = 1; void usage( const char* progname ) @@ -42,6 +46,8 @@ usage( const char* progname ) std::cout << "\tanalyze - continually read the mbuf and do some analysis\n"; std::cout << "\tgap_check - continually scan the buffers looking for " "gaps/jumps in the data stream\n"; + std::cout << "\tcheck_sizes - check the given buffer's data segment sizes " + "against the expected size as calculated in the ini files."; std::cout << "\t-b <buffer name> - The name of the buffer to act on\n"; std::cout << "\t-m <buffer size in MB> - The size of the buffer in megabytes\n"; @@ -49,6 +55,8 @@ usage( const char* progname ) "multiple of 4k)\n"; std::cout << "\t-o <filename> - Output file for the copy operation " "(defaults to probe_out.bin)\n"; + std::cout << "\t-i <filename> - Path to the master ini file (only used " + "for the check_size action)\n"; std::cout << "\t--struct <type> - Type of structure to analyze [rmIpcStr]\n"; std::cout << "\t--dcu <dcuid> - Optional DCU id used to select a dcu for " @@ -79,6 +87,7 @@ parse_options( int argc, char* argv[] ) command_lookup.insert( std::make_pair( "delete", DELETE ) ); command_lookup.insert( std::make_pair( "analyze", ANALYZE ) ); command_lookup.insert( std::make_pair( "gap_check", GAP_CHECK ) ); + command_lookup.insert( std::make_pair( "check_size", CHECK_SIZE ) ); std::map< std::string, MBufStructures > struct_lookup; struct_lookup.insert( std::make_pair( "rmIpcStr", MBUF_RMIPC ) ); @@ -157,6 +166,17 @@ parse_options( int argc, char* argv[] ) is >> offset; opts.decoder = DataDecoder( offset, format_spec ); } + else if ( arg == "-i" ) + { + if ( args.empty( ) ) + { + opts.set_error( + "You must specify a ini file path when using -i" ); + return opts; + } + opts.ini_file_fname = args.front( ); + args.pop_front( ); + } else if ( arg == "--struct" ) { if ( args.empty( ) ) @@ -325,9 +345,6 @@ list_shmem_segments( ) int handle_analyze( const ConfigOpts& opts ) { - const int OK = 0; - const int ERROR = 1; - volatile void* buffer = shmem_open_segment( opts.buffer_name.c_str( ), opts.buffer_size ); switch ( opts.analysis_type ) @@ -348,9 +365,6 @@ handle_analyze( const ConfigOpts& opts ) int handle_gap_check( const ConfigOpts& opts ) { - const int OK = 0; - const int ERROR = 1; - if ( opts.analysis_type != MBUF_DAQ_MULTI_DC ) { std::cout << "daq_multi_cycle is the only mode that the crc_check is " @@ -363,6 +377,26 @@ handle_gap_check( const ConfigOpts& opts ) return OK; } +int +handle_check_size( const ConfigOpts& opts ) +{ + volatile void* buffer = + shmem_open_segment( opts.buffer_name.c_str( ), opts.buffer_size ); + switch ( opts.analysis_type ) + { + case MBUF_RMIPC: + check_mbuf_sizes::check_size_rmipc( buffer, opts.buffer_size, opts ); + break; + case MBUF_DAQ_MULTI_DC: + check_mbuf_sizes::check_size_multi( buffer, opts.buffer_size, opts ); + break; + default: + std::cout << "Unknown analysis type for the check size commandn"; + return ERROR; + } + return OK; +} + int main( int argc, char* argv[] ) { @@ -408,6 +442,8 @@ main( int argc, char* argv[] ) return handle_analyze( opts ); case GAP_CHECK: return handle_gap_check( opts ); + case CHECK_SIZE: + return handle_check_size( opts ); } return 0; } diff --git a/src/drv/mbuf/mbuf_probe/mbuf_probe.hh b/src/drv/mbuf/mbuf_probe/mbuf_probe.hh index 2b1e64c71e7ad92bbbee261ff0481ae37f825615..9609af1d65deb0c970b37f9ee354c95245580baa 100644 --- a/src/drv/mbuf/mbuf_probe/mbuf_probe.hh +++ b/src/drv/mbuf/mbuf_probe/mbuf_probe.hh @@ -5,12 +5,17 @@ #ifndef DAQD_MBUF_PROBE_HH #define DAQD_MBUF_PROBE_HH +#include <chrono> #include <cstddef> #include <string> #include <vector> +#include <type_traits> +#include <sys/time.h> #include <unistd.h> +#include <daq_core.h> + #include "mbuf_decoders.hh" enum MBufCommands @@ -22,6 +27,7 @@ enum MBufCommands DELETE, ANALYZE, GAP_CHECK, + CHECK_SIZE, }; enum MBufStructures @@ -35,8 +41,9 @@ struct ConfigOpts { ConfigOpts( ) : action( INVALID ), buffer_size( 0 ), buffer_name( "" ), - output_fname( "probe_out.bin" ), error_msg( "" ), dcu_id( -1 ), - decoder( ), analysis_type( MBUF_INVALID ) + output_fname( "probe_out.bin" ), error_msg( "" ), + ini_file_fname( "" ), dcu_id( -1 ), decoder( ), + analysis_type( MBUF_INVALID ) { } MBufCommands action; @@ -44,6 +51,7 @@ struct ConfigOpts std::string buffer_name; std::string output_fname; std::string error_msg; + std::string ini_file_fname; int dcu_id; DataDecoder decoder; MBufStructures analysis_type; @@ -115,6 +123,13 @@ struct ConfigOpts "as well as daq_multi_cycle" ); } break; + case CHECK_SIZE: + if ( buffer_name.empty( ) || buffer_size == 0 ) + { + set_error( "To check sizes you must specify a buffer, size, " + "and optionally an ini file" ); + } + break; case INVALID: default: set_error( "Please select a valid action" ); @@ -134,17 +149,59 @@ struct ConfigOpts } }; -template < typename T > +template < typename T, int CheckPeriodUS = 250 > unsigned int wait_until_changed( volatile T* counter, T old_counter ) { - T cur_cycle = *counter; + typename std::remove_const< T >::type cur_cycle = *counter; do { - usleep( 250 ); + usleep( CheckPeriodUS ); cur_cycle = *counter; } while ( cur_cycle == old_counter ); return cur_cycle; } +inline std::int64_t +time_now_ms( ) +{ + timeval tv; + gettimeofday( &tv, 0 ); + return static_cast< std::uint64_t >( tv.tv_sec * 1000 + tv.tv_usec / 1000 ); +} + +struct cycle_sample_t +{ + unsigned int cycle; + unsigned int gps; + unsigned int gps_nano; + unsigned int gps_cycle; + std::uint64_t time_ms; +}; + +template < int CheckPeriodUS = 2000 > +cycle_sample_t +wait_for_time_change( const volatile daq_multi_cycle_header_t& header ) +{ + cycle_sample_t results; + unsigned int cur_cycle = header.curCycle; + while ( header.curCycle == cur_cycle ) + { + usleep( CheckPeriodUS ); + } + results.time_ms = time_now_ms( ); + results.cycle = header.curCycle; + + unsigned int stride = header.cycleDataSize; + const volatile char* buffer_data = + reinterpret_cast< const volatile char* >( &header ) + + sizeof( daq_multi_cycle_header_t ); + const volatile daq_dc_data_t* daq = + reinterpret_cast< const volatile daq_dc_data_t* >( + buffer_data + stride * header.curCycle ); + results.gps = daq->header.dcuheader[ 0 ].timeSec; + results.gps_nano = daq->header.dcuheader[ 0 ].timeNSec; + results.gps_cycle = daq->header.dcuheader[ 0 ].cycle; + return results; +} #endif // DAQD_MBUF_PROBE_HH diff --git a/src/epics/seq/main.c b/src/epics/seq/main.c index 18835a8cdc1834515f09d377adac1ea412b85cd5..9ddc80775f62bb5176c7e157e71e81e42630f713 100644 --- a/src/epics/seq/main.c +++ b/src/epics/seq/main.c @@ -322,6 +322,7 @@ void cleanupCASDF(); #else int getDbValueDouble(ADDRESS*,double *,time_t *); int getDbValueString(ADDRESS*,char *, int, time_t *); +int getDbValueLong(ADDRESS *,unsigned int * ,time_t *); void dbDumpRecords(DBBASE *,const char *); #endif diff --git a/src/epics/util/feCodeGen.pl b/src/epics/util/feCodeGen.pl index 36f13a8f29d95ca230b88d62029e35fcccf7c712..06bf5ba555b6edb1fe2a1a5c1d23e98197cab624 100755 --- a/src/epics/util/feCodeGen.pl +++ b/src/epics/util/feCodeGen.pl @@ -111,12 +111,13 @@ $maxDioMod = pop(@mdmNum); # Initialize default settings. $sitedepwarning = 0; $adcmasterdepwarning = 0; -$ifo = "M1"; # Default value for the ifo name -$location = "mit"; # Default value for the location name -$rate = "60"; # In microseconds (default setting) +$timemasterdepwarning = 0; +$ifo = "dummy"; # Default value for the ifo name +$location = "zzz"; # Default value for the location name +$rate = 0; # In microseconds (default setting) $brate = "52"; -$dcuId = 10; # Default dcu Id -$targetHost = "localhost"; # Default target host name +$dcuId = 0; # Default dcu Id +$targetHost = "dummy"; # Default target host name $edcusync = "none"; $specificCpu = -1; # Defaults is to run the FE on the first available CPU $iopModel = -1; @@ -294,6 +295,7 @@ die unless CDS::Parser::process(); close(IN); +#Print warning messages if model contains Parameter block entries due for deprecation if(($iopModel == 1) and ($modelrate > $adcclock) and ($clock_div == 1)) { die "Error:\nModel rate $modelrate > ADC clock $adcclock\nFix adcclock in Param Block\n*****\n"; @@ -306,6 +308,10 @@ if($adcmasterdepwarning == 1) { print WARNINGS "WARNING: The 'adcMaster=' designator in the model parameter block\n\t is scheduled for deprecation in future releases. \n"; print WARNINGS "*******: Please replace adcMaster=1 designator with iop_model=1 \n"; } +if($timemasterdepwarning == 1) { + print WARNINGS "WARNING: The 'time_master=' designator in the model parameter block\n\t is scheduled for deprecation in future releases. \n"; + print WARNINGS "*******: Please replace time_master=1 designator with dolphin_time_xmit=1 \n"; +} #// #// Model now consists of top level parts and single level subsystem(s). <em>Parser3.pm</em> has taken care of all part diff --git a/src/epics/util/lib/Parameters.pm b/src/epics/util/lib/Parameters.pm index 77011b5d371d02caf470d39046fb5fcffcd1fb4e..80b05e57483f93f17160d06b4a8e968cd87dfdd3 100644 --- a/src/epics/util/lib/Parameters.pm +++ b/src/epics/util/lib/Parameters.pm @@ -9,6 +9,7 @@ use Env qw(RCG_HOST); #// #// \n +use Switch; # Print Epics communication structure into a header file # Current part number is passed as first argument @@ -23,24 +24,32 @@ sub parseParams { #print "Split array is @sp\n"; for (@sp) { @spp = split(/=/); + # Find and convert params due for deprecation in later releases if (@spp == 2) { - if ($spp[0] eq "site" ) { + if ($spp[0] eq "site" ) { $::sitedepwarning = 1; + $spp[0] = "ifo"; } - if ($spp[0] eq "adcMaster" ) { + if($spp[0] eq "adcMaster") { $::adcmasterdepwarning = 1; + $spp[0] = "iop_model"; } - if (($spp[0] eq "site") or ($spp[0] eq "ifo") ) { - $spp[1] =~ s/,/ /g; - - if (lc($spp[1]) ne $::ifo_from_mdl_name) { - $errmsg = "***ERROR: Model <ifo> name part does not match cdsParameters: "; - $errmsg .= $::ifo . ", " . $spp[1] . "\n"; - - die $errmsg; - } + if($spp[0] eq "time_master") { + $::timemasterdepwarning = 1; + $spp[0] = "dolphin_time_xmit"; + } + switch($spp[0]) + { + case "ifo" { + print "PARAM ifo set to $spp[1]\n"; + $spp[1] =~ s/,/ /g; + if (lc($spp[1]) ne $::ifo_from_mdl_name) { + $errmsg = "***ERROR: Model <ifo> name part does not match cdsParameters: "; + $errmsg .= $::ifo . ", " . $spp[1] . "\n"; + die $errmsg; + } - $::ifo = $spp[1]; + $::ifo = $spp[1]; if ($::ifo =~ /^M/) { $::location = "mit"; } elsif ($::ifo =~ /^A/) { @@ -62,146 +71,289 @@ sub parseParams { } elsif ($::ifo =~ /^X/) { $::location = "tst"; } - } elsif ($spp[0] eq "rate") { - print "Rate set to $spp[1]\n"; + } + case "rate" + { + print "PARAM Rate set to $spp[1]\n"; my $param_speed = $spp[1]; - if ($param_speed eq "2K") { + switch($param_speed) + { + case "2K" { $::rate = 480; $::modelrate = 2; $::servoflag = "-DSERVO2K"; - } elsif ($param_speed eq "4K") { + } + case "4K" { $::rate = 240; $::modelrate = 4; $::servoflag = "-DSERVO4K"; - } elsif ($param_speed eq "16K") { + } + case "16K" { $::rate = 60; $::modelrate = 16; $::servoflag = "-DSERVO16K"; - } elsif ($param_speed eq "32K") { + } + case "32K" { $::rate = 30; $::modelrate = 32; $::servoflag = "-DSERVO32K"; - } elsif ($param_speed eq "64K") { + } + case "64K" { $::rate = 15; $::modelrate = 64; $::servoflag = "-DSERVO64K"; - } elsif ($param_speed eq "128K") { + } + case "128K" { $::rate = 8; $::modelrate = 128; $::servoflag = "-DSERVO128K"; - } elsif ($param_speed eq "256K") { + } + case "256K" { $::rate = 4; $::modelrate = 256; $::servoflag = "-DSERVO256K"; - } elsif ($param_speed eq "512K") { + } + case "512K" { $::rate = 2; $::modelrate = 512; $::servoflag = "-DSERVO512K"; - } elsif ($param_speed eq "1024K") { - $::rate = 1; - $::modelrate = 1024; - $::servoflag = "-DSERVO1024K"; - } else { die "Invalid speed $param_speed specified\n"; } - - } elsif ($spp[0] eq "dcuid") { - print "Dcu Id is set to $spp[1]\n"; - $::dcuId = $spp[1]; - print "GDS node id is set to $::dcuId \n"; - $::gdsNodeId = $::dcuId; - } elsif ($spp[0] eq "host") { - print "Target host name is set to $spp[1]\n"; - $::targetHost = $spp[1]; - if ($RCG_HOST) { - $::targetHost = $RCG_HOST; - } - } elsif ($spp[0] eq "plant_name") { - print "Plant name is set to $spp[1]\n"; - $::plantName = $spp[1]; - } elsif ($spp[0] eq "daq_prefix") { - $::daq_prefix = $spp[1]; - } elsif ($spp[0] eq "no_sync" && $spp[1] == 1) { - # This essentially set up IOP for a Cymac - print "Will not sync up to 1PPS\n"; - $::no_sync = 1; - } elsif ($spp[0] eq "no_daq" && $spp[1] == 1) { - # Will compile code not to use DAQ - print "Will not connect to DAQ\n"; - $::no_daq = 1; - } elsif ($spp[0] eq "enable_fir" && $spp[1] == 1) { - # Will compile code to use FIR filtes - print "Will use FIR filters\n"; - $::useFIRs = 1; - } elsif ($spp[0] eq "no_oversampling" && $spp[1] == 1) { - print "Will not oversample\n"; - $::no_oversampling = 1; - } elsif ($spp[0] eq "no_dac_interpolation" && $spp[1] == 1) { - print "Will not interpolate DAC\n"; - $::no_dac_interpolation = 1; - } elsif ($spp[0] eq "specific_cpu") { - print "FE will run on CPU $spp[1]\n"; - $::specificCpu = $spp[1]; - } elsif ($spp[0] eq "adcMaster") { - print "FE will run as IOP\n"; - $::iopModel = $spp[1]; - } elsif ($spp[0] eq "iop_model") { - print "FE will run as IOP\n"; - $::iopModel = $spp[1]; - } elsif ($spp[0] eq "diagTest") { - print "FE Compiles as DIAG TEST CODE\n"; - $::diagTest = $spp[1]; - } elsif ($spp[0] eq "dacwdoverride") { - print "FE Compiles with override of bad DAC error\n"; - $::dacWdOverride = $spp[1]; - } elsif ($spp[0] eq "dolphin_time_xmit") { - $::dolphin_time_xmit = $spp[1]; - } elsif ($spp[0] eq "dolphin_recover") { - $::dolphin_recover = $spp[1]; - } elsif ($spp[0] eq "dolphin_time_rcvr") { - $::dolphinTiming = $spp[1]; - } elsif ($spp[0] eq "no_cpu_shutdown") { - $::no_cpu_shutdown = $spp[1]; - } elsif ($spp[0] eq "pciRfm") { - print "FE will run with PCIE RFM Network\n"; - $::pciNet = $spp[1]; - } elsif ($spp[0] eq "dolphingen") { - print "FE will run with PCIE RFM Network\n"; - # Set Dolphin Gen to run with; default=2 - $::dolphinGen = $spp[1]; - } elsif ($spp[0] eq "remoteGPS") { - print "FE will run with EPICS for GPS Time\n"; - $::remoteGPS = $spp[1]; - } elsif ($spp[0] eq "rfm_delay") { - $::rfmDelay = 1; - } elsif ($spp[0] eq "flip_signals") { - $::flipSignals = $spp[1]; - } elsif ($spp[0] eq "edcu") { - $::edcu = $spp[1]; - } elsif ($spp[0] eq "sdf") { - $::globalsdf = $spp[1]; - } elsif ($spp[0] eq "casdf") { - $::casdf = $spp[1]; - } elsif ($spp[0] eq "requireIOcnt") { - $::requireIOcnt = $spp[1]; - } elsif ($spp[0] eq "virtualIOP") { - $::virtualiop = $spp[1]; - } elsif ($spp[0] eq "use_shm_ipc") { - $::force_shm_ipc = $spp[1]; - } elsif ($spp[0] eq "adcclock") { - $::adcclock = $spp[1]; - } elsif ($spp[0] eq "clock_div") { - $::clock_div = $spp[1]; - } elsif ($spp[0] eq "sync") { - $::edcusync = $spp[1]; - } elsif ($spp[0] eq "optimizeIO") { - $::optimizeIO = $spp[1]; - } elsif ($spp[0] eq "no_zero_pad") { - $::noZeroPad = $spp[1]; - } elsif ($spp[0] eq "ipc_rate") { - # Specify IPC rate if lower than model rate - $::ipcrate = $spp[1]; - } - } + } + else { + $errmsg = "\n************\n"; + $errmsg .= "***ERROR: Invalid Parameter Block Entry: rate = $param_speed \n"; + $errmsg .= "************\n\n"; + die $errmsg; + } + } + } + + case "dcuid" + { + print "PARAM Dcu Id is set to $spp[1]\n"; + $::dcuId = $spp[1]; + print "GDS node id is set to $::dcuId \n"; + $::gdsNodeId = $::dcuId; + } + case "host" + { + print "PARAM Target host name is set to $spp[1]\n"; + $::targetHost = $spp[1]; + if ($RCG_HOST) { + $::targetHost = $RCG_HOST; + } + } + case "plant_name" + { + print "Plant name is set to $spp[1]\n"; + $::plantName = $spp[1]; + } + case "daq_prefix" + { + $::daq_prefix = $spp[1]; + } + case "no_sync" + { + # This essentially set up IOP for a Cymac + print "Will not sync up to 1PPS\n"; + $::no_sync = 1; + } + case "no_daq" + { + # Will compile code not to use DAQ + print "Will not connect to DAQ\n"; + $::no_daq = 1; + } + case "enable_fir" + { + # Will compile code to use FIR filtes + print "Will use FIR filters\n"; + $::useFIRs = 1; + } + case "no_oversampling" + { + print "Will not oversample\n"; + $::no_oversampling = 1; + } + case "no_dac_interpolation" + { + print "Will not interpolate DAC\n"; + $::no_dac_interpolation = 1; + } + case "specific_cpu" + { + print "PARAM FE will run on CPU $spp[1]\n"; + $::specificCpu = $spp[1]; + } + case "iop_model" + { + print "PARAM FE is IOP\n"; + print "FE will run as IOP\n"; + $::iopModel = $spp[1]; + } + case "diagTest" + { + print "PARAM FE Compiles as DIAG TEST CODE\n"; + $::diagTest = $spp[1]; + } + case "dacwdoverride" + { + print "FE Compiles with override of bad DAC error\n"; + $::dacWdOverride = $spp[1]; + } + case "dolphin_time_xmit" + { + $::dolphin_time_xmit = $spp[1]; + } + case "dolphin_recover" + { + $::dolphin_recover = $spp[1]; + } + case "dolphin_time_rcvr" + { + $::dolphinTiming = $spp[1]; + } + case "no_cpu_shutdown" + { + $::no_cpu_shutdown = $spp[1]; + } + case "pciRfm" + { + print "PARAM FE will run with PCIE RFM Network\n"; + $::pciNet = $spp[1]; + } + case "dolphingen" + { + print "PARAM FE will run with PCIE RFM Network\n"; + # Set Dolphin Gen to run with; default=2 + $::dolphinGen = $spp[1]; + } + case "remoteGPS" + { + print "FE will run with EPICS for GPS Time\n"; + $::remoteGPS = $spp[1]; + } + case "rfm_delay" + { + $::rfmDelay = 1; + } + case "flip_signals" + { + $::flipSignals = $spp[1]; + } + case "sdf" + { + $::globalsdf = $spp[1]; + } + case "casdf" + { + $::casdf = $spp[1]; + } + case "requireIOcnt" + { + $::requireIOcnt = $spp[1]; + } + case "virtualIOP" + { + $::virtualiop = $spp[1]; + } + case "use_shm_ipc" + { + $::force_shm_ipc = $spp[1]; + } + case "adcclock" + { + $::adcclock = $spp[1]; + } + case "clock_div" + { + $::clock_div = $spp[1]; + } + case "sync" + { + $::edcusync = $spp[1]; + } + case "optimizeIO" + { + $::optimizeIO = $spp[1]; + } + case "no_zero_pad" + { + $::noZeroPad = $spp[1]; + } + case "ipc_rate" + { + # Specify IPC rate if lower than model rate + $::ipcrate = $spp[1]; + } + # Following are old options that are no longer required + case "biquad" + { + $nolongerused = 1; + } + case "adcSlave" + { + $nolongerused = 2; + } + case "accum_overflow" + { + $nolongerused = 2; + } + case "shmem_daq" + { + $nolongerused = 2; + } + case "rfm_dma" + { + $nolongerused = 2; + } + else { + $errmsg = "***ERROR: Unknown Parameter Block Entry: "; + $errmsg .= $spp[0] . "\n"; + die $errmsg; + } + } + } } + # Check that all required Parameter block entries have been set + if($::ifo eq "dummy") + { + $errmsg = "\n************\n"; + $errmsg .= "***ERROR: Missing Required Parameter Block Entry: ifo\n"; + $errmsg .= "************\n\n"; + die $errmsg; + } + if($::targetHost eq "dummy") + { + $errmsg = "\n************\n"; + $errmsg .= "***ERROR: Missing Required Parameter Block Entry: host\n"; + $errmsg .= "********: Please add host=targetname, where: \n"; + $errmsg .= "********: \ttargetname is name of computer on which code will run\n"; + $errmsg .= "************\n\n"; + die $errmsg; + } + if($::rate eq 0) + { + $errmsg = "\n************\n"; + $errmsg .= "***ERROR: Missing Required Parameter Block Entry: rate\n"; + $errmsg .= "************\n\n"; + die $errmsg; + } + if($::dcuId eq 0) + { + $errmsg = "\n************\n"; + $errmsg .= "***ERROR: Missing Required Parameter Block Entry: dcuid\n"; + $errmsg .= "************\n\n"; + die $errmsg; + } + if($::specificCpu eq -1 && $::iopModel ne 1) + { + $errmsg = "\n************\n"; + $errmsg .= "***ERROR: Missing Required Parameter Block Entry: specific_cpu\n"; + $errmsg .= "********: Please add specific_cpu=x, where: \n"; + $errmsg .= "********: \tx = CPU core on which code will run\n"; + $errmsg .= "************\n\n"; + die $errmsg; + } } sub printHeaderStruct { @@ -223,6 +375,7 @@ sub printFrontEndVars { # Check inputs are connected sub checkInputConnect { my ($i) = @_; + print "PARAM doin connect check\n"; return ""; } diff --git a/src/epics/util/skeleton.st b/src/epics/util/skeleton.st index 6550232e0c7d293e57c5dd7ce75c6eb0550224e9..3192470178a98d982b20647aa54537a7c161b514 100644 --- a/src/epics/util/skeleton.st +++ b/src/epics/util/skeleton.st @@ -73,6 +73,7 @@ program %SEQUENCER_NAME% %% static %EPICS_TYPE% *pEpics; %% static unsigned int sysnum; %% extern void *findRfmCard(int); +%% extern int fmCreatePartial(char *, char *, char *);; #else %% static VME_COEF vmeCoeffSpace; %% static COEF coeffSpace; diff --git a/src/include/rcgversion.h b/src/include/rcgversion.h index 279329e5983096fd3c1f579fbb5b96142e7d8841..551eee401ec55133a251fcd8ba730fcd716d9fe8 100644 --- a/src/include/rcgversion.h +++ b/src/include/rcgversion.h @@ -1,4 +1,4 @@ #define RCG_VERSION_MAJOR 4 #define RCG_VERSION_MINOR 0 -#define RCG_VERSION_SUB 1 +#define RCG_VERSION_SUB 2 #define RCG_VERSION_REL 1