diff --git a/.gitignore b/.gitignore index 6657ec99697c479852eaeed4bfb4755f8af38d8c..ae518f6aba543317eae6f128989895b1920d855a 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ cmake-build-* # editor environments .idea +fontconfig/ # left overs from autotools setups config.log diff --git a/src/drv/mbuf/mbuf_probe/CMakeLists.txt b/src/drv/mbuf/mbuf_probe/CMakeLists.txt index 715c84526de9b13845521d82de3b363b3743c6b5..302c0fb74c13349db5941008865338ca9aaf3615 100644 --- a/src/drv/mbuf/mbuf_probe/CMakeLists.txt +++ b/src/drv/mbuf/mbuf_probe/CMakeLists.txt @@ -5,10 +5,13 @@ add_executable(mbuf_probe mbuf_decoders.cc analyze_daq_multi_dc.cc analyze_rmipc.cc + analyze_awg_data.cc + analyze_header.cc check_size.cc) target_include_directories(mbuf_probe PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/../../include + ${CMAKE_SOURCE_DIR}/src/shmem ) target_link_libraries(mbuf_probe PUBLIC driver::shmem driver::ini_parsing) target_requires_cpp11(mbuf_probe PRIVATE) diff --git a/src/drv/mbuf/mbuf_probe/analyze_awg_data.cc b/src/drv/mbuf/mbuf_probe/analyze_awg_data.cc new file mode 100644 index 0000000000000000000000000000000000000000..e3bd6897086185a99a65cfca8c9ad82a32245406 --- /dev/null +++ b/src/drv/mbuf/mbuf_probe/analyze_awg_data.cc @@ -0,0 +1,79 @@ +// +// Created by erik.vonreis on 4/29/21. +// + +#include <iostream> +#include "shmem_awg.h" +#include "analyze_awg_data.hh" +#include "analyze_header.hh" + + +using namespace std; + +namespace analyze +{ + + + void dump_awg_data(volatile AWG_DATA *awg_data) + { + int hunt_state = 0; + int slot = 0; + + auto detected_type = analyze_header(awg_data); + if(detected_type != MBUF_AWG_DATA) + { + cout << "WARNING: attempting to analyze AWG_DATA structure, but structure was of type " << detected_type << endl; + } + + while(true) + { + int page_index = FIND_PAGE_INDEX(slot,0); + volatile AWG_DATA_PAGE * page = & awg_data->page[page_index]; + + printf("slot: %1d status: %4x d: ", slot, page->status); + for ( int i = 0; i < 4; ++i ) + { + printf("%12.5g", page->buf[i]); + } + cout << "\r" << flush; + + // update slot if necessary to look for active slots + switch(hunt_state) + { + case 1: + case 0: + if(page->status != 0) + { + ++hunt_state; + } + else + { + hunt_state = 0; + } + break; + case 2: + if(page->status != 0) + { + slot = (++slot) % AWG_SLOTS; + } + else + { + hunt_state = 0; + } + + } + + usleep(20000); + } + } + + void analyze_awg_data( volatile void* buffer, + std::size_t size, + const ConfigOpts& options ) + { + + dump_awg_data( + reinterpret_cast<volatile AWG_DATA *>(buffer) + ); + } +} \ No newline at end of file diff --git a/src/drv/mbuf/mbuf_probe/analyze_awg_data.hh b/src/drv/mbuf/mbuf_probe/analyze_awg_data.hh new file mode 100644 index 0000000000000000000000000000000000000000..1a546a4b55169fac87b9e5119b2264648347c534 --- /dev/null +++ b/src/drv/mbuf/mbuf_probe/analyze_awg_data.hh @@ -0,0 +1,18 @@ +// +// Created by erik.vonreis on 4/29/21. +// + +#ifndef DAQD_TRUNK_ANALYZE_AWG_DATA_HH +#define DAQD_TRUNK_ANALYZE_AWG_DATA_HH + +#include <cstddef> +#include "mbuf_probe.hh" + +namespace analyze +{ + void analyze_awg_data( volatile void* buffer, + std::size_t size, + const ConfigOpts& options ); +} + +#endif // DAQD_TRUNK_ANALYZE_AWG_DATA_HH diff --git a/src/drv/mbuf/mbuf_probe/analyze_header.cc b/src/drv/mbuf/mbuf_probe/analyze_header.cc new file mode 100644 index 0000000000000000000000000000000000000000..29c143292edc3ef51593663f9227bdf033195b50 --- /dev/null +++ b/src/drv/mbuf/mbuf_probe/analyze_header.cc @@ -0,0 +1,57 @@ +// +// Created by erik.vonreis on 4/29/21. +// + +#include <iostream> + +#include "analyze_header.hh" +#include "shmem_all.h" + +using namespace std; + +namespace analyze +{ + MBufStructures analyze_header(volatile void * header_void) + { + auto header = reinterpret_cast<volatile SHMEM_HEADER *>(header_void); + + auto version = SHMEM_GET_VERSION(header); + auto id = SHMEM_GET_ID(header); + + MBufStructures detected_type = MBUF_INVALID; + + if(id) + { + switch(id) + { + case AWG_DATA_ID: + detected_type = MBUF_AWG_DATA; + cout << "Detected AWG_DATA struct "; + break; + } + } + else + { + //couldn't identify + cout << "Could not identify structure\n"; + } + + if(version) + { + cout << "version " << version << endl; + } + else + { + if(id) + { + cout << "version 0 (illegal. version should be positive) \n"; + } + else + { + //ignore bad version if id was also bad. + } + } + return detected_type; + } + +} \ No newline at end of file diff --git a/src/drv/mbuf/mbuf_probe/analyze_header.hh b/src/drv/mbuf/mbuf_probe/analyze_header.hh new file mode 100644 index 0000000000000000000000000000000000000000..4eac820411a74d3294a596ecb92370807d53425e --- /dev/null +++ b/src/drv/mbuf/mbuf_probe/analyze_header.hh @@ -0,0 +1,22 @@ +// +// Created by erik.vonreis on 4/29/21. +// + +#ifndef DAQD_TRUNK_ANALYZE_HEADER_H +#define DAQD_TRUNK_ANALYZE_HEADER_H + +#endif // DAQD_TRUNK_ANALYZE_HEADER_H + +#include <cstddef> +#include "mbuf_probe.hh" + +namespace analyze +{ + + /** + * Prints info from standard mbuf header for certain mbuf structures. + * Returns the structure type if it can be determined and is + * incorporated in MBufStructures, otherwise returns MBUF_INVALID + */ + MBufStructures analyze_header(volatile void * header); +} \ No newline at end of file diff --git a/src/drv/mbuf/mbuf_probe/mbuf_probe.cc b/src/drv/mbuf/mbuf_probe/mbuf_probe.cc index e1879d55910c472e9732592555a8e1c38112b584..2cff9cbc1894933c8e3e11225aa200e678f76e56 100644 --- a/src/drv/mbuf/mbuf_probe/mbuf_probe.cc +++ b/src/drv/mbuf/mbuf_probe/mbuf_probe.cc @@ -27,6 +27,7 @@ #include "mbuf_probe.hh" #include "analyze_daq_multi_dc.hh" #include "analyze_rmipc.hh" +#include "analyze_awg_data.hh" #include "gap_check.hh" #include "check_size.hh" @@ -73,6 +74,7 @@ usage( const char* progname ) std::cout << "\trmIpcStr (or rmipcstr) Analyze a models output buffer\n"; std::cout << "\tdaq_multi_cycle Analyze the output of a streamer/local_dc\n"; + std::cout << "\tAWG_DATA Analyze the data streaming from awg.\n"; } ConfigOpts @@ -94,6 +96,10 @@ parse_options( int argc, char* argv[] ) struct_lookup.insert( std::make_pair( "rmipcstr", MBUF_RMIPC ) ); struct_lookup.insert( std::make_pair( "daq_multi_cycle", MBUF_DAQ_MULTI_DC ) ); + struct_lookup.insert( + std::make_pair( "awg_data", MBUF_AWG_DATA) ); + struct_lookup.insert( + std::make_pair( "AWG_DATA", MBUF_AWG_DATA) ); std::deque< std::string > args; for ( int i = 1; i < argc; ++i ) @@ -355,8 +361,12 @@ handle_analyze( const ConfigOpts& opts ) case MBUF_DAQ_MULTI_DC: analyze::analyze_multi_dc( buffer, opts.buffer_size, opts ); break; + case MBUF_AWG_DATA: + analyze::analyze_awg_data(buffer, opts.buffer_size, opts); + break; + case MBUF_INVALID: default: - std::cout << "Unknown analysis type\n"; + std::cout << "Unknown analysis type: " << opts.analysis_type << std::endl; return ERROR; } return OK; @@ -391,7 +401,7 @@ handle_check_size( const ConfigOpts& opts ) check_mbuf_sizes::check_size_multi( buffer, opts.buffer_size, opts ); break; default: - std::cout << "Unknown analysis type for the check size commandn"; + std::cout << "Unknown analysis type for the check size command"; return ERROR; } return OK; diff --git a/src/drv/mbuf/mbuf_probe/mbuf_probe.hh b/src/drv/mbuf/mbuf_probe/mbuf_probe.hh index 9609af1d65deb0c970b37f9ee354c95245580baa..58b9cb04933dbc2d61465a366f9bb39e037a8f33 100644 --- a/src/drv/mbuf/mbuf_probe/mbuf_probe.hh +++ b/src/drv/mbuf/mbuf_probe/mbuf_probe.hh @@ -35,6 +35,7 @@ enum MBufStructures MBUF_INVALID, MBUF_RMIPC, MBUF_DAQ_MULTI_DC, + MBUF_AWG_DATA, }; struct ConfigOpts diff --git a/src/fe/moduleLoadCommon.c b/src/fe/moduleLoadCommon.c index 4d6e76cd4a838bca24acd062737c04273144e4fd..9c675d53c77ef86ca6b2b8ed149c25260dd95451 100644 --- a/src/fe/moduleLoadCommon.c +++ b/src/fe/moduleLoadCommon.c @@ -16,6 +16,8 @@ print_io_info( CDS_HARDWARE* cdsp , int iopmodel) #endif printf( "" SYSTEM_NAME_STRING_LOWER ":EPICSM at 0x%lx\n", (unsigned long)_epics_shm ); + printf( "" SYSTEM_NAME_STRING_LOWER ":AWGSM at 0x%lx\n", + (unsigned long)_awg_shm ); printf( "" SYSTEM_NAME_STRING_LOWER ":IPC at 0x%lx\n", (unsigned long)_ipc_shm ); printf( "" SYSTEM_NAME_STRING_LOWER ":IOMEM at 0x%lx size 0x%lx\n", @@ -250,6 +252,8 @@ detach_shared_memory( ) char fname[ 128 ]; ret = mbuf_release_area( SYSTEM_NAME_STRING_LOWER, _epics_shm ); + sprintf( fname, "%s%s", SYSTEM_NAME_STRING_LOWER, SHMEM_AWG_SUFFIX); + ret = mbuf_release_area( fname, _awg_shm ); ret = mbuf_release_area( "ipc", _ipc_shm ); ret = mbuf_release_area( "shmipc", _shmipc_shm ); sprintf( fname, "%s_daq", SYSTEM_NAME_STRING_LOWER ); @@ -276,6 +280,18 @@ attach_shared_memory( ) pLocalEpics = (CDS_EPICS*)&( (RFM_FE_COMMS*)_epics_shm )->epicsSpace; pLocalEpics->epicsOutput.fe_status = 0; + /// Allocate AWG data memory area + ret = mbuf_allocate_area("" SYSTEM_NAME_STRING_LOWER SHMEM_AWG_SUFFIX, SHMEM_AWG_SIZE, 0 ); + if ( ret < 0 ) + { + printk( "" SYSTEM_NAME_STRING_LOWER + ": ERROR: mbuf_allocate_area(awg) failed; ret = %d\n", + ret ); + return -12; + } + // Set pointer to AWG area + _awg_shm = (volatile AWG_DATA *)( kmalloc_area[ ret ] ); + /// Allocate IPC memory area ret = mbuf_allocate_area( "ipc", 32 * 1024 * 1024, 0 ); if ( ret < 0 ) diff --git a/src/fe/rcguserCommon.c b/src/fe/rcguserCommon.c index fb0c38a4208d25afbf9184f823963a19a6d9351f..925861f4b83b2b4ddf5704b6597cc48e8813bb88 100644 --- a/src/fe/rcguserCommon.c +++ b/src/fe/rcguserCommon.c @@ -28,7 +28,18 @@ attach_shared_memory( char* sysname ) return -1; } printf( "EPICSM at 0x%lx\n", (long)_epics_shm ); - + + // awg data shm used to stream data from awgtpman + sprintf( shm_name, "%s%s", sysname, SHMEM_AWG_SUFFIX ); + findSharedMemory( sysname ); + _awg_shm = (volatile AWG_DATA *)addr; + if ( (uint64_t)_awg_shm < 0 ) + { + printf( "mbuf_allocate_area() failed; ret = %d\n", _awg_shm ); + return -1; + } + printf( "AWGSM at 0x%lx\n", (long)_awg_shm ); + // ipc_shm used to communicate with IOP findSharedMemory( "ipc" ); _ipc_shm = (char*)addr; diff --git a/src/gds/awgtpman/CMakeLists.txt b/src/gds/awgtpman/CMakeLists.txt index e438f3483e474bb5fe0d6b9fffcf3d86152df928..a603b4433200c0d0c74885c5ce7b1647e45c2f72 100644 --- a/src/gds/awgtpman/CMakeLists.txt +++ b/src/gds/awgtpman/CMakeLists.txt @@ -25,14 +25,17 @@ add_executable(awgtpman confserver.c sockutil.c tconv.c + shared_memory.c ../../util/modelrate.c - ) + ../../drv/shmem.c) target_include_directories(awgtpman PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/../../include + ${CMAKE_SOURCE_DIR}/src/include ${RPC_OUTPUT_DIR} + ${CMAKE_SOURCE_DIR}/src/shmem + ${CMAKE_SOURCE_DIR}/src/drv/mbuf ) target_link_libraries(awgtpman PRIVATE diff --git a/src/gds/awgtpman/awg.c b/src/gds/awgtpman/awg.c index bec0f9210d5e16474a799904d155cd2cd8bafd91..2a803bf5373510e33c92517ec0393995a8ccee89 100644 --- a/src/gds/awgtpman/awg.c +++ b/src/gds/awgtpman/awg.c @@ -82,12 +82,12 @@ static char *versionId = "Version $Id$" ; #include "dtt/testpoint.h" #include "dtt/testpointinfo.h" #endif -#include "dtt/map.h" +#include "shmem_awg.h" #include "dtt/targets.h" #include "dtt/hardware.h" #include "dtt/rmorg.h" #include "dtt/rmapi.h" - +#include "shared_memory.h" /*----------------------------------------------------------------------*/ /* */ @@ -148,9 +148,7 @@ static char *versionId = "Version $Id$" ; #else #define _MAX_BUF 8 #endif -/* This will need to go higher for systems faster than 32 kHz */ -/* or if DCU block size is increased */ -#define _MAX_PAGE (DAQ_DCU_SIZE/256) + #define _DAC_PAGE 1024 #define _LSCTP_PAGE TP_LSC_CHN_LEN #define _ASCTP_PAGE TP_ASC_CHN_LEN @@ -252,21 +250,28 @@ Organization of generating waveforms: }; typedef struct filter_coeff_t filter_coeff_t; - struct awgpagebuf_t { - /* ouput type */ - AWG_OutputType otype; - /* output pointer (testpoints) */ - float* optr; - /* channel number (DAC) */ - int onum; - /* page length */ - int pagelen; - /* status of page buffer */ - int status; - /* buffer for page */ - float page [_MAX_PAGE]; - }; - typedef struct awgpagebuf_t awgpagebuf_t; + + + /** + * + */ + struct awgpagebuf_t { + /* ouput type */ + AWG_OutputType otype; + /* output pointer (testpoints) */ + float* optr; + /* page index into shared memory */ + int page_index; + /* channel number (DAC) */ + int onum; + /* page length */ + int pagelen; + /* status of page buffer */ + int status; + /* buffer for page */ + float page [_MAX_PAGE]; + }; + typedef struct awgpagebuf_t awgpagebuf_t; struct awgbuf_t { /* ready flag: 0 - not ready, 1 - ready, 2 - in process */ @@ -315,6 +320,8 @@ Organization of generating waveforms: #endif + + /*----------------------------------------------------------------------*/ /* */ /* Globals: AWG[] - configuration and status of module */ @@ -409,7 +416,7 @@ Organization of generating waveforms: static int readTPinfo (taisec_t tai, int epoch); #endif static int getTPslot (AWG_OutputType type, int tpID, - taisec_t time, int epoch, float** tpptr); + taisec_t time, int epoch, float** tpptr, int *page_index); static int invalidateTPslots (int epoch); static void retireAWGComp (tainsec_t time); #ifdef _AWG_DAC @@ -955,23 +962,27 @@ Organization of generating waveforms: awgpagebuf_t* p; /* pointer to awg page */ for (i = 0, p = buf->buf; i < MAX_NUM_AWG; i++, p++) { /* test whether valid test point channel */ + + AWG_DATA_PAGE *target_page; switch (p->otype) { case awgLSCtp: case awgDAC: /* copy DAC channel into LSC EXC if necessary */ { if ((p->pagelen != _LSCTP_PAGE) || - (p->optr == NULL)) { + (p->page_index < 0)){ continue; } + target_page = &shmemAwgData->page[p->page_index]; break; } case awgASCtp: { if ((p->pagelen != _ASCTP_PAGE) || - (p->optr == NULL)) { + (p->page_index < 0)) { continue; } + target_page = &shmemAwgData->page[p->page_index]; break; } case awgMem: @@ -980,6 +991,7 @@ Organization of generating waveforms: (p->optr == NULL)) { continue; } + target_page = (AWG_DATA_PAGE *)p->optr; break; } default: @@ -987,96 +999,13 @@ Organization of generating waveforms: continue; } } - + + + /* now start transfer */ - /* memcpy ((void*) p->optr, (void*) p->page, - p->pagelen * sizeof (float)); */ - /* don't forget to write status */ - p->status = 0; - { - static int cnt = 0; - if (buf->epoch == 0) { - cnt = 0; - #if 0 - printf ("addr = 0x%x size = %d\n", (int) p->optr, - (int) (p->pagelen + 1) * sizeof (float)); - printf ("values = %g %g %g %g\n", - p->page[p->pagelen-1], p->page[p->pagelen-2], - p->page[p->pagelen-3], p->page[p->pagelen-4]); - #endif - } - /* - if (1 || buf->epoch == 8) { - float x[4]; - static int ofs[100] = {0, 0, 0, 0, 0, 0}; - if (buf->epoch == 0) { - ofs[i] = (int) p->optr + - (p->pagelen - 3) * sizeof (float); - } - if (ofs[i]) { - if (i == 2) { - printf ("ofs[2] = %i\n", ofs[i]); - } - rmRead (_RM_ID, (char*)x, ofs[i], - 4 * sizeof (float), 0); - printf ("values prev. = %g %g %g %g\n", - x[3], x[2], x[1], x[0]); - } - } - */ - } - #if RMEM_LAYOUT == 1 - /* Interleave the writes to slow network blasting a bit */ - { - int j, k; - int sz = (p->pagelen + 1) * sizeof (float); - int nc = sz/awgInterleave; - void *srcptr = (void*) &p->status; - int destidx = (int) p->optr; - for(j = 0; j < nc; j++) { - rmWrite (0, srcptr, destidx, awgInterleave, 0); - #if TARGET != (TARGET_L1_GDS_AWG1 + 20) && TARGET != (TARGET_L1_GDS_AWG1 + 21) - if (AWG[i].rmem) rmWrite (1, srcptr, destidx, awgInterleave, 0); - #endif - srcptr += awgInterleave; - destidx += awgInterleave; - - /* VME accesses to slow things down */ - for (k = 0; k < awgVmeReadDelay; k++) statusTimingCard(); - /* *((int *) (ICS115_0_BASE_ADDRESS+0x50008)) = 0;*/ - } - rmWrite (0, srcptr, destidx, sz - awgInterleave*nc, 0); - if (AWG[i].rmem) rmWrite (1, srcptr, destidx, sz - awgInterleave*nc, 0); - } - #if 0 - rmWrite (0, (void*) &p->status, (int) p->optr, - (p->pagelen + 1) * sizeof (float), 0); - rmWrite (1, (void*) &p->status, (int) p->optr, - (p->pagelen + 1) * sizeof (float), 0); - #endif - #else - {int i; - for (i = 0; i < 5; ++i) - rmWrite (_RM_ID, (void*) &p->status, (int) p->optr, - (p->pagelen + 1) * sizeof (float), 0); - } - #endif - /*{ - if (1 || buf->epoch == 0) { - float x[4]; - static int ofs[100] = {0, 0, 0, 0, 0, 0}; - if (buf->epoch == 0) { - ofs[i] = (int) p->optr + - (p->pagelen - 3) * sizeof (float); - } - if (ofs[i]) { - rmRead (_RM_ID, (char*)x, ofs[i], - 4 * sizeof (float), 0); - printf ("values prev. = %g %g %g %g\n", - x[3], x[2], x[1], x[0]); - } - } - }*/ + memcpy(target_page->buf, p->page, p->pagelen * sizeof(float)); + target_page->status = 0; + } } #endif @@ -1269,12 +1198,13 @@ Organization of generating waveforms: /* time - time of waveform */ /* epoch - epoch of waveform */ /* tpptr - pointer to TP data */ +/* pageindex - index into shared memory page array */ /* */ /* Procedure Returns: slot # if successful, <0 otherwise */ /* */ /*----------------------------------------------------------------------*/ int getTPslot (AWG_OutputType type, int tpID, - taisec_t time, int epoch, float** tpptr) + taisec_t time, int epoch, float** tpptr, int *page_index) { #ifdef _NO_TESTPOINTS return -1; @@ -1330,6 +1260,7 @@ Organization of generating waveforms: break; } } + *page_index = -1; /* calculate address in reflective memory */ if ((slot >= 0) && (tpptr != NULL)) { #if 0 && RMEM_LAYOUT == 1 @@ -1338,7 +1269,9 @@ Organization of generating waveforms: /* Don't forget status word at beginning of channel data! */ tpBase += slot * TP_DATUM_LEN * (tpChnLen + 1); #endif - *tpptr = (float*) CHN_ADDR (tpBase, tpSize, epoch); + //*tpptr = (float*) CHN_ADDR (tpBase, tpSize, epoch); + *tpptr = NULL; + *page_index = FIND_PAGE_INDEX(slot, epoch); } else if (tpptr != NULL) { *tpptr = NULL; @@ -1369,52 +1302,12 @@ Organization of generating waveforms: return -1; #else - int tplistlen; /* length of testpoint list */ - long tpBase; /* offset to TP data block */ - long tpSize; /* size of TP data block */ - long tpChnLen; /* length of tp channel */ - int i; /* index */ - int slot; /* test point slot */ - int tpptr; /* pointer to test point slot */ - int status; /* channel status flag */ - - status = _INVALID_RM_CHANNEL; - for (i = 0; i < 2; i++) { - /* LSC or DAC */ - if (i == 0) { - tplistlen = TP_LSC_EX_NUM; - tpBase = _LSCX_BASE; - tpSize = _LSCX_SIZE; - tpChnLen = TP_LSC_CHN_LEN; - } - /* ASC */ - else { - tplistlen = TP_ASC_EX_NUM; - tpBase = _ASCX_BASE; - tpSize = _ASCX_SIZE; - tpChnLen = TP_ASC_CHN_LEN; - } - /* go through tp slot list */ - tpptr = CHN_ADDR (tpBase, tpSize, epoch); - for (slot = 0; slot < tplistlen; slot++) { - #if RMEM_LAYOUT > 0 - rmWrite (0, (char*) &status, tpptr, TP_DATUM_LEN, 0); - #if TARGET != (TARGET_L1_GDS_AWG1 + 20) && TARGET != (TARGET_L1_GDS_AWG1 + 21) - rmWrite (1, (char*) &status, tpptr, TP_DATUM_LEN, 0); - #endif - /*printf("inv tpslot 0/1 at 0x%x len=%d values=0x%x\n", - tpptr, TP_DATUM_LEN, status);*/ - /* for (k = 0; k < awgVmeReadDelay; k++) - *((int *) 0x50201000) = 0;*/ - #else - rmWrite (_RM_ID, (char*) &status, tpptr, TP_DATUM_LEN, 0); - #endif - /* Don't forget status word at beginning of channel data! */ - tpptr += TP_DATUM_LEN * (tpChnLen + 1); - } - } - - return 0; + for (int slot = 0; slot < AWG_SLOTS; slot++) { + + int page_index = FIND_PAGE_INDEX(slot, epoch); + shmemAwgData->page[page_index].status = _INVALID_RM_CHANNEL; + } + return 0; #endif } @@ -1977,7 +1870,7 @@ Organization of generating waveforms: { /* complete buffer information */ if (getTPslot (AWG[ID].otype, AWG[ID].ID, - time, epoch, &pbuf->optr) >= 0) { + time, epoch, &pbuf->optr, &pbuf->page_index) >= 0) { pbuf->otype = AWG[ID].otype; pbuf->onum = AWG[ID].ID; pbuf->pagelen = AWG[ID].pagesize; @@ -1996,7 +1889,7 @@ Organization of generating waveforms: pbuf->optr = NULL; /* copy into LSC testpoint as well? */ if (getTPslot (awgLSCtp, TP_ID_DAC_OFS + AWG[ID].ID, - time, epoch, &pbuf->optr) < 0) { + time, epoch, &pbuf->optr, &pbuf->page_index) < 0) { pbuf->optr = NULL; } break; diff --git a/src/gds/awgtpman/awgtpman.c b/src/gds/awgtpman/awgtpman.c index e6bbb012000f30b365350329b6892a1ce8747374..aaedcb6e624c84c2f4f56d118cc09e3bb0bea1bc 100644 --- a/src/gds/awgtpman/awgtpman.c +++ b/src/gds/awgtpman/awgtpman.c @@ -16,6 +16,8 @@ static char *versionId = "Version $Id$" ; #include "dtt/rmapi.h" #include "drv/cdsHardware.h" #include "modelrate.h" +#include "shmem_awg.h" +#include "shared_memory.h" #ifdef OS_VXWORKS #define _PRIORITY_TPMAN 40 @@ -289,6 +291,14 @@ CDS_HARDWARE cdsPciModules; #ifdef __linux__ initReflectiveMemory(); #endif + if(!OpenAwgDataSharedMemory(system_name)) + { + fprintf(stderr, "Failed to open mbuf for awg streaming.\n"); + _exit(2); + } + + + if (run_awg) { nice(-20); } diff --git a/src/gds/awgtpman/dtt/awgtype.h b/src/gds/awgtpman/dtt/awgtype.h index 64aa74b6aafa22cab46d4fc2046844f265e47ac7..9d2f110e1b95524c8427ae5c32391760b85342b6 100644 --- a/src/gds/awgtpman/dtt/awgtype.h +++ b/src/gds/awgtpman/dtt/awgtype.h @@ -75,6 +75,10 @@ extern "C" { #include "dtt/gdsrand.h" #include "tconv.h" #include "dtt/gdstask.h" +#include "hardware.h" +#include "map.h" +#include "shmem_awg.h" + #endif /**@name Arbitrary Waveform Generator Type Definitions @@ -320,7 +324,7 @@ extern "C" { @author MRP, Apr. 1998 @see Arbitrary Waveform Generator *********************************************************************/ -#define MAX_NUM_AWG 9 +#define MAX_NUM_AWG AWG_SLOTS /** Maximum number of components per waveform. This number has to be large enough to hold all scheduled components. This number @@ -496,48 +500,7 @@ extern "C" { /*@{*/ -/** Identification for an LSC test point channel - - @author DS, Jul. 1998 - @see Arbitrary Waveform Generator -*********************************************************************/ -#define AWG_LSC_TESTPOINT 1 - -/** Identification for an ASC test point channel - @author DS, Jul. 1998 - @see Arbitrary Waveform Generator -*********************************************************************/ -#define AWG_ASC_TESTPOINT 2 - -/** Identification for a DAC channel - - @author DS, Jul. 1998 - @see Arbitrary Waveform Generator -*********************************************************************/ -#define AWG_DAC_CHANNEL 3 - -/** Identification for a DS340 channel - - @author DS, Jul. 1998 - @see Arbitrary Waveform Generator -*********************************************************************/ -#define AWG_DS340_CHANNEL 4 - -/** Identification for a channel which gets written to file. - - @author DS, Jul. 1998 - @see Arbitrary Waveform Generator -*********************************************************************/ -#define AWG_FILE_CHANNEL 5 - -/** Identification for a channel which gets written to an aboslute - address in reflective memory. - - @author DS, Jul. 1998 - @see Arbitrary Waveform Generator -*********************************************************************/ -#define AWG_MEM_CHANNEL 6 /*@}*/ @@ -647,33 +610,7 @@ extern "C" { }; typedef enum AWG_WaveType AWG_WaveType; -/** Recognized output modes. - The output of an arbitrary waveform generator can be an LSC or - ASC test point, a DAC channel, a DS340 channel or a file (test - only). - - @author MRP, Apr. 1998 - @see Arbitrary Waveform Generator -*********************************************************************/ - enum AWG_OutputType { - #if 0 - /** output disabled */ - awgNone = 0, - #endif - /** output to an LSC tespoint */ - awgLSCtp = AWG_LSC_TESTPOINT, - /** output to an ASC tespoint */ - awgASCtp = AWG_ASC_TESTPOINT, - /** output to a DAC channel */ - awgDAC = AWG_DAC_CHANNEL, - /** output to a DS340 function generator */ - awgDS340 = AWG_DS340_CHANNEL, - /** output to a file */ - awgFile = AWG_FILE_CHANNEL, - /** output to an absolute memory location */ - awgMem = AWG_MEM_CHANNEL - }; - typedef enum AWG_OutputType AWG_OutputType; + /** Structure to describe a component of a waveform. @@ -723,6 +660,29 @@ extern "C" { }; typedef struct AWG_Gain AWG_Gain; + /** Recognized output modes. + The output of an arbitrary waveform generator can be an LSC or + ASC test point, a DAC channel, a DS340 channel or a file (test + only). + + @author MRP, Apr. 1998 + @see Arbitrary Waveform Generator + *********************************************************************/ + enum AWG_OutputType { + /** output to an LSC tespoint */ + awgLSCtp = AWG_LSC_TESTPOINT, + /** output to an ASC tespoint */ + awgASCtp = AWG_ASC_TESTPOINT, + /** output to a DAC channel */ + awgDAC = AWG_DAC_CHANNEL, + /** output to a DS340 function generator */ + awgDS340 = AWG_DS340_CHANNEL, + /** output to a file */ + awgFile = AWG_FILE_CHANNEL, + /** output to an absolute memory location */ + awgMem = AWG_MEM_CHANNEL + }; + typedef enum AWG_OutputType AWG_OutputType; #ifndef _GDS_AWGAPI_H /** Structure to describe an arbitrary waveform generator. diff --git a/src/gds/awgtpman/dtt/rmorg.h b/src/gds/awgtpman/dtt/rmorg.h index fddb34df349984f9ddb28c84799a4a89dd1eb6c1..8a483b6c72fbcb5c3e6cd1dd0262a0e6272f1866 100644 --- a/src/gds/awgtpman/dtt/rmorg.h +++ b/src/gds/awgtpman/dtt/rmorg.h @@ -72,7 +72,7 @@ extern "C" { /* Header File List: */ #include "dtt/hardware.h" -#include "dtt/map.h" +#include "map.h" /** @name Reflective Memory Organization This module defines the organizational structure of the reflective diff --git a/src/gds/awgtpman/shared_memory.c b/src/gds/awgtpman/shared_memory.c new file mode 100644 index 0000000000000000000000000000000000000000..876fd7f1fc09560ddc1f32be896745d5380ef283 --- /dev/null +++ b/src/gds/awgtpman/shared_memory.c @@ -0,0 +1,24 @@ +// +// Created by erik.vonreis on 4/27/21. +// + +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include "shared_memory.h" +#include "shmem_awg.h" +#include "drv/shmem.h" + +volatile AWG_DATA *shmemAwgData = NULL; + +int OpenAwgDataSharedMemory(const char *model_name) +{ + char buff[256]; + strncpy(buff, model_name, sizeof(buff)); + buff[sizeof(buff)-1] = 0; + strncat(buff, SHMEM_AWG_SUFFIX, sizeof(buff)); + shmemAwgData = (volatile AWG_DATA *)shmem_open_segment(buff, SHMEM_AWG_SIZE); + AWG_DATA_INIT(shmemAwgData); + return (shmemAwgData!=NULL) ? -1 : 0; +} \ No newline at end of file diff --git a/src/gds/awgtpman/shared_memory.h b/src/gds/awgtpman/shared_memory.h new file mode 100644 index 0000000000000000000000000000000000000000..37ae79f493ce58941cc3af2a114c6f64df685188 --- /dev/null +++ b/src/gds/awgtpman/shared_memory.h @@ -0,0 +1,21 @@ +// +// Created by erik.vonreis on 4/27/21. +// functions for interfacing AWG with shared memory +// + +#ifndef DAQD_TRUNK_SHARED_MEMORY_H +#define DAQD_TRUNK_SHARED_MEMORY_H + +#include <stdint.h> + +#include "shmem_awg.h" + +extern volatile AWG_DATA *shmemAwgData; + +/** + * Open up the awg streaming into a global pointer, shmemAwgData + * @returns 0 on failuer, nonzero on success + */ +int OpenAwgDataSharedMemory(const char *model_name); + +#endif // DAQD_TRUNK_SHARED_MEMORY_H diff --git a/src/include/controller.h b/src/include/controller.h index 2343226f180e486e0d6c3e837ef5a9cea3b5a698..c36335724492a8ce64d212ba2d647c8087764d0f 100644 --- a/src/include/controller.h +++ b/src/include/controller.h @@ -289,9 +289,12 @@ char fp[ 64 * 1024 ]; #define PERIOD_COUNT 1 #define MAX_UDELAY 19999 +#include "../shmem/shmem_all.h" + char* build_date = __DATE__ " " __TIME__; extern int iop_rfm_valid; volatile char* _epics_shm; ///< Ptr to EPICS shared memory area +volatile AWG_DATA *_awg_shm; char* _ipc_shm; ///< Ptr to inter-process communication area char* _daq_shm; ///< Ptr to frame builder comm shared mem area // char* _gds_shm; ///< Ptr to frame builder comm shared mem area diff --git a/src/include/drv/daqLib.c b/src/include/drv/daqLib.c index c9775957bd0ee7124159f63ff8c8d43520978f63..993df275fff2eb7f9e15d5f44355508e37b843a9 100644 --- a/src/include/drv/daqLib.c +++ b/src/include/drv/daqLib.c @@ -2,9 +2,12 @@ * \brief File contains routines to support DAQ on realtime systems. \n * \author R.Bork, A. Ivanov */ + +#include "../../shmem/shmem_all.h" volatile DAQ_INFO_BLOCK* pInfo; ///< Ptr to DAQ config in shmem. extern volatile char* _epics_shm; ///< Ptr to EPICS shmem block +extern volatile AWG_DATA *_awg_shm; extern long daqBuffer; ///< Address of daqLib swing buffers. extern char* _daq_shm; ///< Pointer to DAQ base address in shared memory. struct rmIpcStr* dipc; ///< Pointer to DAQ IPC data in shared memory. @@ -123,7 +126,7 @@ daqWrite( int flag, static int tpNumNet[ DAQ_GDS_MAX_TP_ALLOWED ]; /* TP/EXC selects to send to FB. */ static int totalChans; /* DAQ + TP + EXC chans selected. */ - int* statusPtr; + volatile float* dataPtr; /* Ptr to excitation chan data. */ int exChanOffset; /* shmem offset to next EXC value. */ int tpx; @@ -696,25 +699,23 @@ daqWrite( int flag, if ( localTable[ ii ].type < DAQ_SRC_FM_EXC ) continue; - exChanOffset = localTable[ ii ].sigNum * excDataSize; - statusPtr = - (int*)( exciteDataPtr + excBlockNum * DAQ_DCU_BLOCK_SIZE + - exChanOffset ); - if ( *statusPtr == 0 ) + //find right page for the excitation + int page_index = FIND_PAGE_INDEX(localTable[ ii ].sigNum, excBlockNum); + AWG_DATA_PAGE *awg_page = _awg_shm->page + page_index; + + if ( awg_page->status == 0 ) { validEx = FE_ERROR_EXC_SET; - dataPtr = (float*)( exciteDataPtr + - excBlockNum * DAQ_DCU_BLOCK_SIZE + - exChanOffset + excSlot * 4 + 4 ); + if ( localTable[ ii ].type == DAQ_SRC_FM_EXC ) { dspPtr->data[ localTable[ ii ].fmNum ].exciteInput = - *dataPtr; + awg_page->buf[excSlot]; } else if ( localTable[ ii ].type == DAQ_SRC_NFM_EXC ) { // extra excitation - excSignal[ localTable[ ii ].fmNum ] = *dataPtr; + excSignal[ localTable[ ii ].fmNum ] = awg_page->buf[excSlot]; } } // else dspPtr->data[localTable[ii].fmNum].exciteInput = 0.0; diff --git a/src/nds/CMakeLists.txt b/src/nds/CMakeLists.txt index 356a947811e5176936ee2620d0ca7bd68586cf9b..7842c5a76e81d22b846dd265284a558229db146f 100644 --- a/src/nds/CMakeLists.txt +++ b/src/nds/CMakeLists.txt @@ -8,7 +8,7 @@ set( NDS_SRC main.cc spec.cc scanarchivedir.cc - ) + ../shmem/awg_data.h ../shmem/shmem_header.h ../shmem/shmem_all.h) execute_process(COMMAND uname -a OUTPUT_VARIABLE NDS_UNAME) diff --git a/src/shmem/awg_data.h b/src/shmem/awg_data.h new file mode 100644 index 0000000000000000000000000000000000000000..3639473ac2d54afb900cf8f28b5571a2d7ba5f72 --- /dev/null +++ b/src/shmem/awg_data.h @@ -0,0 +1,56 @@ +// +// Created by erik.vonreis on 4/27/21. +// + +#ifndef DAQD_TRUNK_AWG_DATA_H +#define DAQD_TRUNK_AWG_DATA_H + +#include "daq_core_defs.h" +#include "shmem_header.h" + +// maximum supported model rate in samples per second. +#define MAX_MODEL_RATE_SPS (64 * 1024) + +// maximum supported width of a single datum in the awg data +#define MAX_SAMPLE_WIDTH_BYTES (sizeof(float)) + +// Maximum page size. Awg is streamed one page per epoch per slot. +// _max_page_size is 2^20 samples per second ( > 1 megasample) * sizeof(double) / 16 epochs per second +#define _MAX_PAGE (MAX_MODEL_RATE_SPS * MAX_SAMPLE_WIDTH_BYTES / DAQ_NUM_DATA_BLOCKS_PER_SECOND) + +typedef struct AWG_DATA_PAGE +{ + uint32_t status; + float buf[_MAX_PAGE]; +} AWG_DATA_PAGE; + +// number channels of excitation that can be run at once per model (DCU). +#define AWG_SLOTS (9) + +// number of epochs buffered per slot. +// If we wanted to increase this number beyond the number of epochs per second, +// then FIND_PAGE_INDEX would have to be changed. +#define AWG_EPOCHS_PER_SLOT (16) + +// total number of data pages in the awg shared memory. +#define AWG_PAGE_COUNT (AWG_SLOTS * AWG_EPOCHS_PER_SLOT) + +/** + * Primary structure for awg shared memory + * Contains all the pages passed between awg and the models. + */ +typedef struct AWG_DATA +{ + SHMEM_HEADER _header; + AWG_DATA_PAGE page[AWG_PAGE_COUNT]; +} AWG_DATA; + +#define AWG_DATA_ID (1) // structure identification. Should be unique to the structure. +#define AWG_DATA_VERSION (1) + +#define AWG_DATA_INIT(AD_PTR) SHMEM_SET_VERSION(AD_PTR, AWG_DATA_ID, AWG_DATA_VERSION) + +// convert a slot number and epoch count into +#define FIND_PAGE_INDEX(SLOT, EPOCH) ((SLOT*AWG_EPOCHS_PER_SLOT) + (EPOCH % AWG_EPOCHS_PER_SLOT)) + +#endif // DAQD_TRUNK_AWG_DATA_H diff --git a/src/gds/awgtpman/dtt/map.h b/src/shmem/map.h similarity index 89% rename from src/gds/awgtpman/dtt/map.h rename to src/shmem/map.h index 8560591f619d8e3c2f748a5b5bd1fbb7b2d38cac..29d597e0c9182be2325af09711a774883e9df078 100644 --- a/src/gds/awgtpman/dtt/map.h +++ b/src/shmem/map.h @@ -1,5 +1,5 @@ /* Version: $Id$ */ -#include "hardware.h" +//#include "dtt/hardware.h" #if (RMEM_LAYOUT == 0) #error #include "map_v1.h" diff --git a/src/gds/awgtpman/dtt/map_v3.h b/src/shmem/map_v3.h similarity index 88% rename from src/gds/awgtpman/dtt/map_v3.h rename to src/shmem/map_v3.h index 9a77000029cd0cdb5b9e3125895a1b11745e4f5b..eeec839615826966a37ff417fc73faf368cfb402 100644 --- a/src/gds/awgtpman/dtt/map_v3.h +++ b/src/shmem/map_v3.h @@ -6,19 +6,14 @@ * DAQ system inter-processor communication definitions. */ -#define DCU_COUNT 26 +#include "daq_core_defs.h" + #define DAQ_BASE_ADDRESS 0x2000000 #define DAQ_DATA_BASE_ADD (DAQ_BASE_ADDRESS + 0x100000) -#define DAQ_DCU_SIZE 0x400000 -#define DAQ_DCU_BLOCK_SIZE (DAQ_DCU_SIZE/16) - #define DAQ_EDCU_SIZE 0x400000 #define DAQ_EDCU_BLOCK_SIZE 0x20000 -#define DAQ_NUM_DATA_BLOCKS 16 -#define DAQ_NUM_DATA_BLOCKS_PER_SECOND 16 - /* * Inter-processor communication structures */ @@ -46,6 +41,48 @@ struct rmIpcStr { /* IPC area structure */ blockPropT bp [DAQ_NUM_DATA_BLOCKS]; /* An array of block property structures */ }; +/** Identification for an LSC test point channel + + @author DS, Jul. 1998 + @see Arbitrary Waveform Generator +*********************************************************************/ +#define AWG_LSC_TESTPOINT 1 + +/** Identification for an ASC test point channel + + @author DS, Jul. 1998 + @see Arbitrary Waveform Generator +*********************************************************************/ +#define AWG_ASC_TESTPOINT 2 + +/** Identification for a DAC channel + + @author DS, Jul. 1998 + @see Arbitrary Waveform Generator +*********************************************************************/ +#define AWG_DAC_CHANNEL 3 + +/** Identification for a DS340 channel + + @author DS, Jul. 1998 + @see Arbitrary Waveform Generator +*********************************************************************/ +#define AWG_DS340_CHANNEL 4 + +/** Identification for a channel which gets written to file. + + @author DS, Jul. 1998 + @see Arbitrary Waveform Generator +*********************************************************************/ +#define AWG_FILE_CHANNEL 5 + +/** Identification for a channel which gets written to an aboslute + address in reflective memory. + + @author DS, Jul. 1998 + @see Arbitrary Waveform Generator +*********************************************************************/ +#define AWG_MEM_CHANNEL 6 /* * DCU IDs */ @@ -210,7 +247,7 @@ static unsigned int const dcuNet[DCU_COUNT] = {3,3,3,3,0, #define DAQ_GDS_DCU_NUM 4 /* Total number of channels allowed per DCU */ -#define DCU_MAX_CHANNELS 128 +#define DCU_MAX_CHANNELS 512 /* RFM offset of DCU DAQ configuration area; used for communicating configuration from Epics processor to a front-end processor */ diff --git a/src/shmem/readme.txt b/src/shmem/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..151457bf29adde622672e77285d1afebd6082c9c --- /dev/null +++ b/src/shmem/readme.txt @@ -0,0 +1,7 @@ +The shmem directory contains header files describing the name, size and structure used for a shared memory block. + +The definitive version of the structure is also defined here under a separate file. + +shared memories can either be host-wide, or model-specific. +For host-wide shared memories, the full name is given as shmem_<memname>_name. +For model_specific shared memories, a suffix is given as shmem_<memname>_suffix. Append this suffix to the model name to get the shared memory name. diff --git a/src/shmem/shmem_all.h b/src/shmem/shmem_all.h new file mode 100644 index 0000000000000000000000000000000000000000..4cf7c4dadc7977643606071a971940941ed9c885 --- /dev/null +++ b/src/shmem/shmem_all.h @@ -0,0 +1,10 @@ +// +// Created by erik.vonreis on 4/29/21. +// + +#ifndef DAQD_TRUNK_SHMEM_ALL_H +#define DAQD_TRUNK_SHMEM_ALL_H + +#include "shmem_awg.h" + +#endif // DAQD_TRUNK_SHMEM_ALL_H diff --git a/src/shmem/shmem_awg.h b/src/shmem/shmem_awg.h new file mode 100644 index 0000000000000000000000000000000000000000..2747ee7d8518b21dd48355a23f725a7c98169346 --- /dev/null +++ b/src/shmem/shmem_awg.h @@ -0,0 +1,11 @@ +#ifndef SHMEM_AWG_H +#define SHMEM_AWG_H + +#include "awg_data.h" + +#define SHMEM_AWG_SUFFIX "_awg" +#define SHMEM_AWG_SIZE (64*(1024)*(1024)) + +#define SHMEM_AWG_STRUCT AWG_DATA; + +#endif //SHMEM_AWG_H diff --git a/src/shmem/shmem_header.h b/src/shmem/shmem_header.h new file mode 100644 index 0000000000000000000000000000000000000000..88f854e75053f56f599170fc42cf2bdc7aba7e23 --- /dev/null +++ b/src/shmem/shmem_header.h @@ -0,0 +1,38 @@ +// +// Created by erik.vonreis on 4/27/21. +// + +#ifndef DAQD_TRUNK_SHMEM_HEADER_H +#define DAQD_TRUNK_SHMEM_HEADER_H + +// header to suppport version control for shared memory structures. +typedef struct SHMEM_HEADER +{ + uint32_t magic_bytes; // used to verify structure is using this header + uint32_t struct_id; //unique id that identifies the structure type (1 = AWG_DATA, 2 = ... + uint32_t version; // should be 1 or more +} SHMEM_HEADER; + +#define SHMEM_HEADER_MAGIC_BYTES (0xf000beef) + +/** + * Pass a pointer to the header, and a version number. + * Sets version number and magic bytes. + */ +#define SHMEM_SET_VERSION(HEADER_PTR, ID, VERSION) { SHMEM_HEADER *_h_p_ = HEADER_PTR; \ + _h_p_->magic_bytes = SHMEM_HEADER_MAGIC_BYTES; \ + _h_p_->struct_id = ID; \ + _h_p_->version = VERSION; } + +/** + * Get the version number of a shared memory structure + * Returns 0 if the structure does not start with a properly intialized + * SHMEM_HEADER + */ +#define SHMEM_GET_VERSION(HDR_PTR) ( (((SHMEM_HEADER *)HDR_PTR)->magic_bytes == SHMEM_HEADER_MAGIC_BYTES) \ + ? ((SHMEM_HEADER *)HDR_PTR)->version : 0 ) + +#define SHMEM_GET_ID(HDR_PTR) ( (((SHMEM_HEADER *)HDR_PTR)->magic_bytes == SHMEM_HEADER_MAGIC_BYTES) \ + ? ((SHMEM_HEADER *)HDR_PTR)->struct_id : 0 ) + +#endif // DAQD_TRUNK_SHMEM_HEADER_H