def write_files(): fwrC = rogue.utilities.fileio.StreamWriter() fwrC.setBufferSize(BufferSize) fwrC.setMaxSize(MaxSize) fwrU = rogue.utilities.fileio.StreamWriter() fwrU.setBufferSize(BufferSize) fwrU.setMaxSize(MaxSize) prbs = rogue.utilities.Prbs() comp = rogue.utilities.StreamZip() pyrogue.streamConnect(prbs,fwrU.getChannel(0)) pyrogue.streamTap(prbs,comp) pyrogue.streamConnect(comp,fwrC.getChannel(0)) fwrC.open("compressed.dat") fwrU.open("uncompressed.dat") print("Writing data files") for _ in range(FrameCount): prbs.genFrame(FrameSize) time.sleep(5) fwrC.close() fwrU.close()
def __init__(self, name, description, root=None, txDevice=None, **kwargs): pyrogue.Device.__init__(self, name=name, description=description, **kwargs) # Add a data emulator module, at the beginning of the chain self.pre_data_emulator = pysmurf.core.emulators.StreamDataEmulatorI16( name="PreDataEmulator") self.add(self.pre_data_emulator) # Add a frame statistics module self.smurf_frame_stats = pysmurf.core.counters.FrameStatistics( name="FrameRxStats") self.add(self.smurf_frame_stats) # Add the SmurfProcessor C++ device. This module implements: channel mapping, # data unwrapping, filter, and downsampling. Python wrapper for these functions # are added here to give the same tree structure as the modular version. self.smurf_processor = smurf.core.processors.SmurfProcessor() self.smurf_mapper = SmurfChannelMapper(name="ChannelMapper", device=self.smurf_processor) self.add(self.smurf_mapper) self.smurf_unwrapper = Unwrapper(name="Unwrapper", device=self.smurf_processor) self.add(self.smurf_unwrapper) self.smurf_filter = GeneralAnalogFilter(name="Filter", device=self.smurf_processor) self.add(self.smurf_filter) self.smurf_downsampler = Downsampler(name="Downsampler", device=self.smurf_processor) self.add(self.smurf_downsampler) # This device doesn't have any user configurations, so we don't add it to the tree self.smurf_header2smurf = pysmurf.core.conventers.Header2Smurf( name="Header2Smurf") # Add a data emulator module, at the end of the chain self.post_data_emulator = pysmurf.core.emulators.StreamDataEmulatorI32( name="PostDataEmulator") self.add(self.post_data_emulator) # Use a standard Rogue file writer. # - Channel 0 will be use for the smurf data # - Channel 1 will be use for the configuration data (aka metadata) self.file_writer = pyrogue.utilities.fileio.StreamWriter( name='FileWriter') self.add(self.file_writer) # Add a Fifo. It will hold up to 100 copies of processed frames, to be processed by # downstream slaves. The frames will be tapped before the file writer. self.fifo = rogue.interfaces.stream.Fifo(100, 0, False) # Connect devices pyrogue.streamConnect(self.pre_data_emulator, self.smurf_frame_stats) pyrogue.streamConnect(self.smurf_frame_stats, self.smurf_processor) pyrogue.streamConnect(self.smurf_processor, self.smurf_header2smurf) pyrogue.streamConnect(self.smurf_header2smurf, self.post_data_emulator) pyrogue.streamConnect(self.post_data_emulator, self.file_writer.getChannel(0)) pyrogue.streamTap(self.post_data_emulator, self.fifo) # If a root was defined, connect it to the file writer, on channel 1 if root: pyrogue.streamConnect(root, self.file_writer.getChannel(1)) # If a TX device was defined, add it to the tree # and connect it to the chain, after the fifo if txDevice: self.transmitter = txDevice self.add(self.transmitter) # Connect the data channel to the FIFO. pyrogue.streamConnect(self.fifo, self.transmitter.getDataChannel()) # If a root was defined, connect it to the meta channel. # Use streamTap as it was already connected to the file writer. if root: pyrogue.streamTap(root, self.transmitter.getMetaChannel())
def __init__(self, name='Top', description='Container for FEB FPGA', ip=['10.0.0.1'], pollEn=True, initRead=True, configProm=False, advanceUser=False, refClkSel=['IntClk'], loadYaml=True, userYaml=[''], defaultFile='config/defaults.yml', **kwargs): super().__init__(name=name, description=description, **kwargs) # Set the min. firmware Version support by the software self.minFpgaVersion = 0x20000060 # Enable Init after config self.InitAfterConfig._default = True # Cache the parameters self.advanceUser = advanceUser self.configProm = configProm self.ip = ip self.numEthDev = len(ip) if (ip[0] != 'simulation') else 1 self._timeout = 1.0 if (ip[0] != 'simulation') else 100.0 self._pollEn = pollEn if (ip[0] != 'simulation') else False self._initRead = initRead if (ip[0] != 'simulation') else False self.usrLoadYaml = loadYaml self.userYaml = userYaml self.defaultFile = defaultFile self.pllConfig = [None for i in range(self.numEthDev)] # Check if missing refClkSel configuration if (len(refClkSel) < len(ip)): errMsg = f'len(refClkSel) = {len(refClkSel)} < len(ip) = {len(ip)}.\nMake sure to define a refClkSel for each IP address' click.secho(errMsg, bg='red') raise ValueError(errMsg) # Set the path of the PLL configuration file for i in range(self.numEthDev): if (refClkSel[i] == 'IntClk'): self.pllConfig[ i] = 'config/pll-config/Si5345-RevD-Registers-IntClk.csv' elif (refClkSel[i] == 'ExtSmaClk'): self.pllConfig[ i] = 'config/pll-config/Si5345-RevD-Registers-ExtSmaClk.csv' elif (refClkSel[i] == 'ExtLemoClk'): self.pllConfig[ i] = 'config/pll-config/Si5345-RevD-Registers-ExtLemoClk.csv' else: errMsg = f'refClkSel[{i}] argument must be either [IntClk,ExtSmaClk,ExtLemoClk]' click.secho(errMsg, bg='red') raise ValueError(errMsg) # File writer self.dataWriter = pr.utilities.fileio.StreamWriter() self.add(self.dataWriter) # Create arrays to be filled self.rudp = [None for i in range(self.numEthDev)] self.srpStream = [None for i in range(self.numEthDev)] self.dataStream = [None for i in range(self.numEthDev)] self.semStream = [None for i in range(self.numEthDev)] self.memMap = [None for i in range(self.numEthDev)] # SEM monitor streams self.semDataWriter = SemAsciiFileWriter() # Loop through the devices for i in range(self.numEthDev): ###################################################################### if (self.ip[0] == 'simulation'): self.srpStream[i] = rogue.interfaces.stream.TcpClient( 'localhost', 9000) self.dataStream[i] = rogue.interfaces.stream.TcpClient( 'localhost', 9002) else: self.rudp[i] = pr.protocols.UdpRssiPack(host=ip[i], port=8192, packVer=2, jumbo=False) self.srpStream[i] = self.rudp[i].application(0) self.dataStream[i] = self.rudp[i].application(1) self.semStream[i] = self.rudp[i].application(2) ###################################################################### # Connect the SRPv3 to PGPv3.VC[0] self.memMap[i] = rogue.protocols.srp.SrpV3() pr.streamConnectBiDir(self.memMap[i], self.srpStream[i]) # Check if not PROM loading if not self.configProm: # Connect data stream to file as channel to dataStream pr.streamConnect(self.dataStream[i], self.dataWriter.getChannel(i)) # Connect to the SEM monitor streams and file writer pr.streamConnect(self.semStream[i], self.semDataWriter) pr.streamTap(self.semStream[i], self.dataWriter.getChannel(i + 128)) ###################################################################### # Add devices self.add( common.Fpga( name=f'Fpga[{i}]', memBase=self.memMap[i], offset=0x00000000, configProm=self.configProm, advanceUser=self.advanceUser, expand=True, )) ###################################################################### self.add( pr.LocalVariable( name="LiveDisplayRst", mode="RW", value=0x0, hidden=True, )) @self.command() def LiveDisplayReset(arg): print('LiveDisplayReset()') self.LiveDisplayRst.set(1) for reset in self.reset_list: reset() self.LiveDisplayRst.set(0) @self.command( description= 'This command is intended to be executed before self.dataWriter is closed' ) def StopRun(arg): click.secho('StopRun()', bg='yellow') # Stop the Master First for i in range(self.numEthDev): if self.Fpga[i].Asic.Trig.TrigTypeSel.getDisp() == 'Master': self.Fpga[i].Asic.Trig.EnableReadout.set(0x0) click.secho( f'self.Fpga[{i}].Asic.Trig.EnableReadout.set(0x0)', bg='bright_magenta') # Stop the Slave after the Master for i in range(self.numEthDev): if self.Fpga[i].Asic.Trig.TrigTypeSel.getDisp() == 'Slave': self.Fpga[i].Asic.Trig.EnableReadout.set(0x0) click.secho( f'self.Fpga[{i}].Asic.Trig.EnableReadout.set(0x0)', bg='magenta') @self.command( description= 'This command is intended to be executed after self.dataWriter is opened' ) def StartRun(arg): click.secho('StartRun()', bg='blue') # Reset the sequence and trigger counters for i in range(self.numEthDev): self.Fpga[i].Asic.Trig.countReset() self.Fpga[i].Asic.Readout.SeqCntRst() # Start the Slave First for i in range(self.numEthDev): if self.Fpga[i].Asic.Trig.TrigTypeSel.getDisp() == 'Slave': self.Fpga[i].Asic.Trig.EnableReadout.set(0x1) click.secho( f'self.Fpga[{i}].Asic.Trig.EnableReadout.set(0x1)', bg='magenta') # Start the Master after the Slave for i in range(self.numEthDev): if self.Fpga[i].Asic.Trig.TrigTypeSel.getDisp() == 'Master': self.Fpga[i].Asic.Trig.EnableReadout.set(0x1) click.secho( f'self.Fpga[{i}].Asic.Trig.EnableReadout.set(0x1)', bg='bright_magenta') @self.command( description= 'This command is intended to be executed after self.dataWriter is opened' ) def ResumeRun(arg): click.secho('ResumeRun()', bg='blue') # Start the Slave First for i in range(self.numEthDev): if self.Fpga[i].Asic.Trig.TrigTypeSel.getDisp() == 'Slave': self.Fpga[i].Asic.Trig.EnableReadout.set(0x1) click.secho( f'self.Fpga[{i}].Asic.Trig.EnableReadout.set(0x1)', bg='magenta') # Start the Master after the Slave for i in range(self.numEthDev): if self.Fpga[i].Asic.Trig.TrigTypeSel.getDisp() == 'Master': self.Fpga[i].Asic.Trig.EnableReadout.set(0x1) click.secho( f'self.Fpga[{i}].Asic.Trig.EnableReadout.set(0x1)', bg='bright_magenta') ###################################################################### # Start the system self.start( pollEn=self._pollEn, initRead=self._initRead, timeout=self._timeout, )
def __init__(self, ip_addr, config_file, server_mode, group_name, epics_prefix,\ polling_en, comm_type, pcie_rssi_link, stream_pv_size, stream_pv_type,\ pv_dump_file): try: pyrogue.Root.__init__(self, name='AMCc', description='AMC Carrier') # File writer for streaming interfaces # DDR interface (TDEST 0x80 - 0x87) stm_data_writer = pyrogue.utilities.fileio.StreamWriter( name='streamDataWriter') self.add(stm_data_writer) # Streaming interface (TDEST 0xC0 - 0xC7) stm_interface_writer = pyrogue.utilities.fileio.StreamWriter( name='streamingInterface') self.add(stm_interface_writer) # Workaround to FpgaTopLelevel not supporting rssi = None if pcie_rssi_link == None: pcie_rssi_link = 0 # Instantiate Fpga top level fpga = FpgaTopLevel(ipAddr=ip_addr, commType=comm_type, pcieRssiLink=pcie_rssi_link) # Add devices self.add(fpga) # Add data streams (0-7) to file channels (0-7) for i in range(8): # DDR streams pyrogue.streamConnect(fpga.stream.application(0x80 + i), stm_data_writer.getChannel(i)) # Streaming interface streams #pyrogue.streamConnect(fpga.stream.application(0xC0 + i), # new commended out # stm_interface_writer.getChannel(i)) # Our receiver data_fifo = rogue.interfaces.stream.Fifo(1000, 0, 1) # new self.my_processor = MyModule.MyProcessor() self.my_processor.setDebug(False) #pyrogue.streamConnect(base.FpgaTopLevel.stream.application(0xC1), data_fifo) # new #pyrogue.streamConnect(base.FpgaTopLevel.stream.Application(0xC1), data_fifo) # new pyrogue.streamConnect(fpga.stream.application(0xC1), data_fifo) pyrogue.streamConnect(data_fifo, self.my_processor) #pyrogue.streamTap(fpga.stream.application(0xC1), rx) # Run control for streaming interfaces self.add( pyrogue.RunControl(name='streamRunControl', description='Run controller', cmd=fpga.SwDaqMuxTrig, rates={ 1: '1 Hz', 10: '10 Hz', 30: '30 Hz' })) # PVs for stream data, used on PCAS-based EPICS server if epics_prefix and stream_pv_size: if use_pcas: print("Enabling stream data on PVs (buffer size = {} points, data type = {})"\ .format(stream_pv_size,stream_pv_type)) # Add data streams (0-7) to local variables so they are expose as PVs # Also add PVs to select the data format for i in range(8): # Calculate number of bytes needed on the fifo if '16' in stream_pv_type: fifo_size = stream_pv_size * 2 else: fifo_size = stream_pv_size * 4 # Setup a FIFO tapped to the steram data and a Slave data buffer # Local variables will talk to the data buffer directly. stream_fifo = rogue.interfaces.stream.Fifo( 0, fifo_size, 0) data_buffer = DataBuffer(size=stream_pv_size, data_type=stream_pv_type) stream_fifo._setSlave(data_buffer) #pyrogue.streamTap(fpga.stream.application(0x80 + i), stream_fifo) # Variable to read the stream data stream_var = pyrogue.LocalVariable( name='Stream{}'.format(i), description='Stream {}'.format(i), mode='RO', value=0, localGet=data_buffer.read, update=False, hidden=True) # Set the buffer callback to update the variable data_buffer.set_callback(stream_var.updated) # Variable to set the data format data_format_var = pyrogue.LocalVariable( name='StreamDataFormat{}'.format(i), description='Type of data being unpacked', mode='RW', value=0, enum={ i: j for i, j in enumerate( data_buffer.get_data_format_list()) }, localSet=data_buffer.set_data_format, localGet=data_buffer.get_data_format, hidden=True) # Variable to set the data byte order byte_order_var = pyrogue.LocalVariable( name='StreamDataByteOrder{}'.format(i), description='Byte order of data being unpacked', mode='RW', value=0, enum={ i: j for i, j in enumerate( data_buffer.get_data_byte_order_list()) }, localSet=data_buffer.set_data_byte_order, localGet=data_buffer.get_data_byte_order, hidden=True) # Variable to read the data format string format_string_var = pyrogue.LocalVariable( name='StreamDataFormatString{}'.format(i), description='Format string used to unpack the data', mode='RO', value=0, localGet=data_buffer.get_data_format_string, hidden=True) # Add listener to update the format string readback variable # when the data format or data byte order is changed data_format_var.addListener(format_string_var) byte_order_var.addListener(format_string_var) # Add the local variable to self self.add(stream_var) self.add(data_format_var) self.add(byte_order_var) self.add(format_string_var) # lcaPut limits the maximun lenght of a string to 40 chars, as defined # in the EPICS R3.14 CA reference manual. This won't allowed to use the # command 'ReadConfig' with a long file path, which is usually the case. # This function is a workaround to that problem. Fomr matlab one can # just call this function without arguments an the function ReadConfig # will be called with a predefined file passed during startup # However, it can be usefull also win the GUI, so it is always added. self.config_file = config_file self.add( pyrogue.LocalCommand(name='setDefaults', description='Set default configuration', function=self.set_defaults_cmd)) self.add( pyrogue.LocalCommand(name='runGarbageCollection', description='runGarbageCollection', function=self.run_garbage_collection)) self.add( pyrogue.LocalVariable( name='smurfProcessorDebug', description='Enable smurf processor transmit debug', mode='RW', value=False, localSet=lambda value: self.my_processor.setDebug(value), hidden=False)) # Start the root if group_name: # Start with Pyro4 server host_name = get_host_name() print( "Starting rogue server with Pyro using group name \"{}\"". format(group_name)) self.start(pollEn=polling_en, pyroGroup=group_name, pyroHost=host_name, pyroNs=None) else: # Start without Pyro4 server print("Starting rogue server") self.start(pollEn=polling_en) self.ReadAll() except KeyboardInterrupt: print("Killing server creation...") super(LocalServer, self).stop() exit() # Show image build information try: print("") print("FPGA image build information:") print("===================================") print("BuildStamp : {}"\ .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.BuildStamp.get())) print("FPGA Version : 0x{:x}"\ .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.FpgaVersion.get())) print("Git hash : 0x{:x}"\ .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.GitHash.get())) except AttributeError as attr_error: print("Attibute error: {}".format(attr_error)) print("") # Start the EPICS server if epics_prefix: print("Starting EPICS server using prefix \"{}\"".format( epics_prefix)) # Choose the appropiate epics module: if use_pcas: self.epics = pyrogue.epics.EpicsCaServer(base=epics_prefix, root=self) else: self.epics = pyrogue.protocols.epics.EpicsCaServer( base=epics_prefix, root=self) # PVs for stream data, used on GDD-based EPICS server if stream_pv_size: print("Enabling stream data on PVs (buffer size = {} points, data type = {})"\ .format(stream_pv_size,stream_pv_type)) for i in range(8): stream_slave = self.epics.createSlave( name="AMCc:Stream{}".format(i), maxSize=stream_pv_size, type=stream_pv_type) # Calculate number of bytes needed on the fifo if '16' in stream_pv_type: fifo_size = stream_pv_size * 2 else: fifo_size = stream_pv_size * 4 stream_fifo = rogue.interfaces.stream.Fifo( 0, fifo_size, 0) # chnages stream_fifo._setSlave(stream_slave) pyrogue.streamTap(fpga.stream.application(0x80 + i), stream_fifo) self.epics.start() # Dump the PV list to the especified file if pv_dump_file: try: # Try to open the output file f = open(pv_dump_file, "w") except IOError: print("Could not open the PV dump file \"{}\"".format( pv_dump_file)) else: with f: print("Dumping PV list to \"{}\"...".format( pv_dump_file)) try: try: # Redirect the stdout to the output file momentarily original_stdout, sys.stdout = sys.stdout, f self.epics.dump() finally: sys.stdout = original_stdout print("Done!") except: # Capture error from epics.dump() if any print("Errors were found during epics.dump()") # If no in server Mode, start the GUI if not server_mode: create_gui(self) else: # Stop the server when Crtl+C is pressed print("") print("Running in server mode now. Press Ctrl+C to stop...") try: # Wait for Ctrl+C while True: time.sleep(1) except KeyboardInterrupt: pass
def __init__( self, *, config_file=None, epics_prefix="EpicsPrefix", polling_en=True, pv_dump_file=None, txDevice=None, fpgaTopLevel=None, stream_pv_size=2**19, # Not sub-classed stream_pv_type='Int16', # Not sub-classed configure=False, VariableGroups=None, server_port=0, **kwargs): pyrogue.Root.__init__(self, name="AMCc", initRead=True, pollEn=polling_en, streamIncGroups='stream', serverPort=server_port, **kwargs) ######################################################################################### # The following interfaces are expected to be defined at this point by a sub-class # self._streaming_stream # Data stream interface # self._ddr_streams # 4 DDR Interface Streams # self._fpga = Top level FPGA # Add PySmurf Application Block self.add(pysmurf.core.devices.SmurfApplication()) # Add FPGA self.add(self._fpga) # File writer for streaming interfaces # DDR interface (TDEST 0x80 - 0x87) self._stm_data_writer = pyrogue.utilities.fileio.StreamWriter( name='streamDataWriter') self.add(self._stm_data_writer) # Streaming interface (TDEST 0xC0 - 0xC7) self._stm_interface_writer = pyrogue.utilities.fileio.StreamWriter( name='streamingInterface') self.add(self._stm_interface_writer) # Add the SMuRF processor device self._smurf_processor = pysmurf.core.devices.SmurfProcessor( name="SmurfProcessor", description="Process the SMuRF Streaming Data Stream", root=self, txDevice=txDevice) self.add(self._smurf_processor) # Connect smurf processor pyrogue.streamConnect(self._streaming_stream, self._smurf_processor) # Add data streams (0-3) to file channels (0-3) for i in range(4): ## DDR streams pyrogue.streamConnect(self._ddr_streams[i], self._stm_data_writer.getChannel(i)) ## Streaming interface streams # We have already connected TDEST 0xC1 to the smurf_processor receiver, # so we need to tapping it to the data writer. pyrogue.streamTap(self._streaming_stream, self._stm_interface_writer.getChannel(0)) # TES Bias Update Function # smurf_processor bias index 0 = TesBiasDacDataRegCh[2] - TesBiasDacDataRegCh[1] # smurf_processor bias index l = TesBiasDacDataRegCh[4] - TesBiasDacDataRegCh[3] def _update_tes_bias(idx): v1 = self.FpgaTopLevel.AppTop.AppCore.RtmCryoDet.RtmSpiMax.node( f'TesBiasDacDataRegCh[{(2*idx)+2}]').value() v2 = self.FpgaTopLevel.AppTop.AppCore.RtmCryoDet.RtmSpiMax.node( f'TesBiasDacDataRegCh[{(2*idx)+1}]').value() val = (v1 - v2) // 2 # Pass to data processor self._smurf_processor.setTesBias(index=idx, val=val) # Register TesBias values configuration to update stream processor # Bias values are ranged 1 - 32, matching tes bias indexes 0 - 16 for i in range(1, 33): idx = (i - 1) // 2 try: v = self.FpgaTopLevel.AppTop.AppCore.RtmCryoDet.RtmSpiMax.node( f'TesBiasDacDataRegCh[{i}]') v.addListener( lambda path, value, lidx=idx: _update_tes_bias(lidx)) except Exception: print(f"TesBiasDacDataRegCh[{i}] not found... Skipping!") # Run control for streaming interfaces self.add( pyrogue.RunControl(name='streamRunControl', description='Run controller', cmd=self._fpga.SwDaqMuxTrig, rates={ 1: '1 Hz', 10: '10 Hz', 30: '30 Hz' })) # lcaPut limits the maximun lenght of a string to 40 chars, as defined # in the EPICS R3.14 CA reference manual. This won't allowed to use the # command 'ReadConfig' with a long file path, which is usually the case. # This function is a workaround to that problem. Fomr matlab one can # just call this function without arguments an the function ReadConfig # will be called with a predefined file passed during startup # However, it can be usefull also win the GUI, so it is always added. self._config_file = config_file self.add( pyrogue.LocalCommand(name='setDefaults', description='Set default configuration', function=self._set_defaults_cmd)) # Flag that indicates if the default configuration should be loaded # once the root is started. self._configure = configure # Variable groups self._VariableGroups = VariableGroups # Add epics interface self._epics = None if epics_prefix: print("Starting EPICS server using prefix \"{}\"".format( epics_prefix)) from pyrogue.protocols import epics self._epics = epics.EpicsCaServer(base=epics_prefix, root=self) self._pv_dump_file = pv_dump_file # PVs for stream data # This should be replaced with DataReceiver objects if stream_pv_size: print( "Enabling stream data on PVs (buffer size = {} points, data type = {})" .format(stream_pv_size, stream_pv_type)) self._stream_fifos = [] self._stream_slaves = [] for i in range(4): self._stream_slaves.append( self._epics.createSlave(name="AMCc:Stream{}".format(i), maxSize=stream_pv_size, type=stream_pv_type)) # Calculate number of bytes needed on the fifo if '16' in stream_pv_type: fifo_size = stream_pv_size * 2 else: fifo_size = stream_pv_size * 4 self._stream_fifos.append( rogue.interfaces.stream.Fifo(1000, fifo_size, True)) # changes pyrogue.streamConnect(self._stream_fifos[i], self._stream_slaves[i]) pyrogue.streamTap(self._ddr_streams[i], self._stream_fifos[i]) # Update SaveState to not read before saving self.SaveState.replaceFunction( lambda arg: self.saveYaml(name=arg, readFirst=False, modes=['RW', 'RO', 'WO'], incGroups=None, excGroups='NoState', autoPrefix='state', autoCompress=True)) # Update SaveConfig to not read before saving self.SaveConfig.replaceFunction( lambda arg: self.saveYaml(name=arg, readFirst=False, modes=['RW', 'WO'], incGroups=None, excGroups='NoConfig', autoPrefix='config', autoCompress=False))
def __init__( self, name='TimeToolDev', description='Container for TimeTool Dev', dataDebug=False, dev='/dev/datadev_0', # path to PCIe device version3=False, # true = PGPv3, false = PGP2b pollEn=True, # Enable automatic polling registers initRead=True, # Read all registers at start of the system numLane=1, # Number of PGP lanes **kwargs): super().__init__(name=name, description=description, dev=dev, version3=version3, pollEn=pollEn, initRead=initRead, numLane=numLane, **kwargs) # Check if not doing simulation if (dev != 'sim'): # Create arrays to be filled self._srp = [None for lane in range(numLane)] # Create the stream interface for lane in range(numLane): # SRP self._srp[lane] = rogue.protocols.srp.SrpV3() pr.streamConnectBiDir(self._dma[lane][0], self._srp[lane]) # CameraLink Feb Board self.add( feb.ClinkFeb( name=(f'ClinkFeb[{lane}]'), memBase=self._srp[lane], serial=[self._dma[lane][2], None], camType=['Piranha4', None], version3=version3, enableDeps=[ self.Hardware.PgpMon[lane].RxRemLinkReady ], # Only allow access if the PGP link is established # expand = False, )) # Else doing Rogue VCS simulation else: # Create arrays to be filled self._frameGen = [None for lane in range(numLane)] # Create the stream interface for lane in range(numLane): # Create the frame generator self._frameGen[lane] = MyCustomMaster() # Connect the frame generator pr.streamConnect(self._frameGen[lane], self._pgp[lane][1]) # Create a command to execute the frame generator self.add( pr.BaseCommand( name=f'GenFrame[{lane}]', function=lambda cmd: self._frameGen[lane].myFrameGen(), )) # Create arrays to be filled self._dbg = [None for lane in range(numLane)] # Create the stream interface for lane in range(numLane): # Debug slave if dataDebug: self._dbg[lane] = TimeToolRx(expand=False) pr.streamTap(self._dma[lane][1], self._dbg[lane]) self.add(self._dbg) # Time tool application self.add( timeTool.Application( memBase=self._memMap, offset=0x00C00000, numLane=numLane, )) # Start the system self.start( pollEn=self._pollEn, initRead=self._initRead, timeout=self._timeout, ) # Check if not simulation if (dev != 'sim'): # Read all the variables self.ReadAll() # Some initialization after starting root for lane in range(numLane): self.ClinkFeb[lane].ClinkTop.Ch[0].BaudRate.set(9600) self.ClinkFeb[lane].ClinkTop.Ch[0].SerThrottle.set(10000) self.ClinkFeb[lane].ClinkTop.Ch[0].LinkMode.setDisp('Full') self.ClinkFeb[lane].ClinkTop.Ch[0].DataMode.setDisp('8Bit') self.ClinkFeb[lane].ClinkTop.Ch[0].FrameMode.setDisp('Line') self.ClinkFeb[lane].ClinkTop.Ch[0].TapCount.set(8) self.ClinkFeb[lane].ClinkTop.Ch[0].UartPiranha4.SendEscape() self.ClinkFeb[lane].ClinkTop.Ch[0].UartPiranha4.SPF.setDisp( '0') self.ClinkFeb[lane].ClinkTop.Ch[0].UartPiranha4.GCP() else: # Disable the PGP PHY device (speed up the simulation) self.Hardware.enable.set(False) self.Hardware.hidden = True # Bypass the time AXIS channel eventDev = self.find(typ=batcher.AxiStreamBatcherEventBuilder) for dev in eventDev: dev.Bypass.set(0x1)
def __init__(self, ip_addr, config_file, server_mode, group_name, epics_prefix,\ polling_en, comm_type, pcie_rssi_link, stream_pv_size, stream_pv_type,\ pv_dump_file, disable_bay0, disable_bay1, disable_gc, windows_title, pcie_dev): try: pyrogue.Root.__init__(self, name='AMCc', description='AMC Carrier') # File writer for streaming interfaces # DDR interface (TDEST 0x80 - 0x87) stm_data_writer = pyrogue.utilities.fileio.StreamWriter( name='streamDataWriter') self.add(stm_data_writer) # Streaming interface (TDEST 0xC0 - 0xC7) stm_interface_writer = pyrogue.utilities.fileio.StreamWriter( name='streamingInterface') self.add(stm_interface_writer) # Workaround to FpgaTopLelevel not supporting rssi = None if pcie_rssi_link == None: pcie_rssi_link = 0 # Instantiate Fpga top level fpga = FpgaTopLevel(ipAddr=ip_addr, commType=comm_type, pcieRssiLink=pcie_rssi_link, disableBay0=disable_bay0, disableBay1=disable_bay1) # Add devices self.add(fpga) # Create stream interfaces self.ddr_streams = [] # DDR streams self.streaming_streams = [] # Streaming interface streams # If the packetizer is being used, the FpgaTopLevel class will defined a 'stream' interface exposing it. # Otherwise, we are using DMA engine without packetizer. Create the stream interface accordingly. if hasattr(fpga, 'stream'): for i in range(8): self.ddr_streams.append(fpga.stream.application(0x80 + i)) self.streaming_streams.append( fpga.stream.application(0xC0 + i)) else: for i in range(8): self.ddr_streams.append( rogue.hardware.axi.AxiStreamDma( pcie_dev, (pcie_rssi_link * 0x100 + 0x80 + i), True)) self.streaming_streams.append( rogue.hardware.axi.AxiStreamDma( pcie_dev, (pcie_rssi_link * 0x100 + 0xC0 + i), True)) # Our smurf_processor receiver # The data stream comes from TDEST 0xC1 # We use a FIFO between the stream data and the receiver: # Stream -> FIFO -> smurf_processor receiver self.smurf_processor = Smurf.SmurfProcessor() self.smurf_processor.setDebug(False) self.smurf_processor_fifo = rogue.interfaces.stream.Fifo( 1000, 0, True) pyrogue.streamConnect(self.streaming_streams[1], self.smurf_processor_fifo) pyrogue.streamConnect(self.smurf_processor_fifo, self.smurf_processor) # Add data streams (0-7) to file channels (0-7) for i in range(8): ## DDR streams pyrogue.streamConnect(self.ddr_streams[i], stm_data_writer.getChannel(i)) ## Streaming interface streams # We have already connected TDEST 0xC1 to the smurf_processor receiver, # so we need to tapping it to the data writer. if i == 1: pyrogue.streamTap(self.streaming_streams[i], stm_interface_writer.getChannel(i)) # The rest of channels are connected directly to the data writer. else: pyrogue.streamConnect(self.streaming_streams[i], stm_interface_writer.getChannel(i)) # Look for the TesBias registers # TesBias register are located on # FpgaTopLevel.AppTop.AppCore.RtmCryoDet.RtmSpiMax # And their name is TesBiasDacDataRegCh[n], where x = [0:31] self.TestBiasVars = [] self.TestBiasRegEx = re.compile('.*TesBiasDacDataRegCh\[(\d+)\]$') for var in self.FpgaTopLevel.AppTop.AppCore.RtmCryoDet.RtmSpiMax.variableList: m = self.TestBiasRegEx.match(var.name) if m: reg_index = int(m[1]) - 1 if reg_index < 32: print( f'Found TesBias register: {var.name}, with index {reg_index}' ) self.TestBiasVars.append(var) # Check that we have all 32 TesBias registers if len(self.TestBiasVars) == 32: print( f'Found 32 TesBias registers. Assigning listener functions' ) # Add listener to the TesBias registers for var in self.TestBiasVars: var.addListener(self.send_test_bias) # Prepare a buffer to holds the TesBias register values self.TesBiasValue = [0] * 32 else: print( f'Error: {len(self.TestBiasVars)} TesBias register were found instead of 32. Aborting' ) # Run control for streaming interfaces self.add( pyrogue.RunControl(name='streamRunControl', description='Run controller', cmd=fpga.SwDaqMuxTrig, rates={ 1: '1 Hz', 10: '10 Hz', 30: '30 Hz' })) # PVs for stream data, used on PCAS-based EPICS server if epics_prefix and stream_pv_size: if use_pcas: print("Enabling stream data on PVs (buffer size = {} points, data type = {})"\ .format(stream_pv_size,stream_pv_type)) # Add data streams (0-7) to local variables so they are expose as PVs # Also add PVs to select the data format self.stream_fifos = [] self.data_buffers = [] for i in range(8): # Calculate number of bytes needed on the fifo if '16' in stream_pv_type: fifo_size = stream_pv_size * 2 else: fifo_size = stream_pv_size * 4 # Setup a FIFO tapped to the steram data and a Slave data buffer # Local variables will talk to the data buffer directly. self.stream_fifos.append( rogue.interfaces.stream.Fifo(0, fifo_size, 0)) stream_fifo = self.stream_fifos[i] self.data_buffers.append( DataBuffer(size=stream_pv_size, data_type=stream_pv_type)) data_buffer = self.data_buffers[i] stream_fifo._setSlave(data_buffer) #pyrogue.streamTap(fpga.stream.application(0x80 + i), stream_fifo) # Variable to read the stream data stream_var = pyrogue.LocalVariable( name='Stream{}'.format(i), description='Stream {}'.format(i), mode='RO', value=0, localGet=data_buffer.read, update=False, hidden=True) # Set the buffer callback to update the variable data_buffer.set_callback(stream_var.updated) # Variable to set the data format data_format_var = pyrogue.LocalVariable( name='StreamDataFormat{}'.format(i), description='Type of data being unpacked', mode='RW', value=0, enum={ i: j for i, j in enumerate( data_buffer.get_data_format_list()) }, localSet=data_buffer.set_data_format, localGet=data_buffer.get_data_format, hidden=True) # Variable to set the data byte order byte_order_var = pyrogue.LocalVariable( name='StreamDataByteOrder{}'.format(i), description='Byte order of data being unpacked', mode='RW', value=0, enum={ i: j for i, j in enumerate( data_buffer.get_data_byte_order_list()) }, localSet=data_buffer.set_data_byte_order, localGet=data_buffer.get_data_byte_order, hidden=True) # Variable to read the data format string format_string_var = pyrogue.LocalVariable( name='StreamDataFormatString{}'.format(i), description='Format string used to unpack the data', mode='RO', value=0, localGet=data_buffer.get_data_format_string, hidden=True) # Add listener to update the format string readback variable # when the data format or data byte order is changed data_format_var.addListener(format_string_var) byte_order_var.addListener(format_string_var) # Add the local variable to self self.add(stream_var) self.add(data_format_var) self.add(byte_order_var) self.add(format_string_var) # lcaPut limits the maximun lenght of a string to 40 chars, as defined # in the EPICS R3.14 CA reference manual. This won't allowed to use the # command 'ReadConfig' with a long file path, which is usually the case. # This function is a workaround to that problem. Fomr matlab one can # just call this function without arguments an the function ReadConfig # will be called with a predefined file passed during startup # However, it can be usefull also win the GUI, so it is always added. self.config_file = config_file self.add( pyrogue.LocalCommand(name='setDefaults', description='Set default configuration', function=self.set_defaults_cmd)) # If Garbage collection was disable, add this local variable to allow users # to manually run the garbage collection. if disable_gc: self.add( pyrogue.LocalCommand(name='runGarbageCollection', description='runGarbageCollection', function=self.run_garbage_collection)) self.add( pyrogue.LocalVariable( name='smurfProcessorDebug', description='Enable smurf processor transmit debug', mode='RW', value=False, localSet=lambda value: self.smurf_processor.setDebug(value ), hidden=False)) # Lost frame counter from smurf_processor self.add( pyrogue.LocalVariable( name='frameLossCnt', description='Lost frame Counter', mode='RO', value=0, localGet=self.smurf_processor.getFrameLossCnt, pollInterval=1, hidden=False)) # Received frame counter from smurf_processor self.add( pyrogue.LocalVariable( name='frameRxCnt', description='Received frame Counter', mode='RO', value=0, localGet=self.smurf_processor.getFrameRxCnt, pollInterval=1, hidden=False)) # Out-of-order frame counter from smurf_processor self.add( pyrogue.LocalVariable( name='frameOutOrderCnt', description= 'Number of time out-of-order frames are detected', mode='RO', value=0, localGet=self.smurf_processor.getFrameOutOrderCnt, pollInterval=1, hidden=False)) # Command to clear all the frame counters on smurf_processor self.add( pyrogue.LocalCommand( name='clearFrameCnt', description='Clear all frame counters', function=self.smurf_processor.clearFrameCnt)) # Start the root if group_name: # Start with Pyro4 server host_name = get_host_name() print( "Starting rogue server with Pyro using group name \"{}\"". format(group_name)) self.start(pollEn=polling_en, pyroGroup=group_name, pyroHost=host_name, pyroNs=None) else: # Start without Pyro4 server print("Starting rogue server") self.start(pollEn=polling_en) self.ReadAll() # Call the get() method on the tesBias variable to force the call to # send_test_bias and update the array in Smurf2MCE for var in self.TestBiasVars: var.get() except KeyboardInterrupt: print("Killing server creation...") super(LocalServer, self).stop() exit() # Show image build information try: print("") print("FPGA image build information:") print("===================================") print("BuildStamp : {}"\ .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.BuildStamp.get())) print("FPGA Version : 0x{:x}"\ .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.FpgaVersion.get())) print("Git hash : 0x{:x}"\ .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.GitHash.get())) except AttributeError as attr_error: print("Attibute error: {}".format(attr_error)) print("") # Start the EPICS server if epics_prefix: print("Starting EPICS server using prefix \"{}\"".format( epics_prefix)) # Choose the appropiate epics module: if use_pcas: self.epics = pyrogue.epics.EpicsCaServer(base=epics_prefix, root=self) else: self.epics = pyrogue.protocols.epics.EpicsCaServer( base=epics_prefix, root=self) # PVs for stream data, used on GDD-based EPICS server if stream_pv_size: print("Enabling stream data on PVs (buffer size = {} points, data type = {})"\ .format(stream_pv_size,stream_pv_type)) self.stream_fifos = [] self.stream_slaves = [] for i in range(8): self.stream_slaves.append( self.epics.createSlave( name="AMCc:Stream{}".format(i), maxSize=stream_pv_size, type=stream_pv_type)) # Calculate number of bytes needed on the fifo if '16' in stream_pv_type: fifo_size = stream_pv_size * 2 else: fifo_size = stream_pv_size * 4 self.stream_fifos.append( rogue.interfaces.stream.Fifo( 1000, fifo_size, True)) # changes self.stream_fifos[i]._setSlave(self.stream_slaves[i]) pyrogue.streamTap(self.ddr_streams[i], self.stream_fifos[i]) self.epics.start() # Dump the PV list to the especified file if pv_dump_file: try: # Try to open the output file f = open(pv_dump_file, "w") except IOError: print("Could not open the PV dump file \"{}\"".format( pv_dump_file)) else: with f: print("Dumping PV list to \"{}\"...".format( pv_dump_file)) try: try: # Redirect the stdout to the output file momentarily original_stdout, sys.stdout = sys.stdout, f self.epics.dump() finally: sys.stdout = original_stdout print("Done!") except: # Capture error from epics.dump() if any print("Errors were found during epics.dump()") # If no in server Mode, start the GUI if not server_mode: create_gui(self, title=windows_title) else: # Stop the server when Crtl+C is pressed print("") print("Running in server mode now. Press Ctrl+C to stop...") try: # Wait for Ctrl+C while True: time.sleep(1) except KeyboardInterrupt: pass
def __init__(self, ip_addr, config_file, server_mode, epics_prefix,\ polling_en, comm_type, pcie_rssi_lane, stream_pv_size, stream_pv_type,\ pv_dump_file, disable_bay0, disable_bay1, disable_gc, windows_title,\ pcie_dev_rssi, pcie_dev_data): try: pyrogue.Root.__init__(self, name='AMCc', description='AMC Carrier') # File writer for streaming interfaces # DDR interface (TDEST 0x80 - 0x87) stm_data_writer = pyrogue.utilities.fileio.StreamWriter(name='streamDataWriter') self.add(stm_data_writer) # Streaming interface (TDEST 0xC0 - 0xC7) stm_interface_writer = pyrogue.utilities.fileio.StreamWriter(name='streamingInterface') self.add(stm_interface_writer) # Workaround to FpgaTopLelevel not supporting rssi = None if pcie_rssi_lane == None: pcie_rssi_lane = 0 # Instantiate Fpga top level fpga = FpgaTopLevel(ipAddr=ip_addr, commType=comm_type, pcieRssiLink=pcie_rssi_lane, disableBay0=disable_bay0, disableBay1=disable_bay1) # Add devices self.add(fpga) # Create stream interfaces self.ddr_streams = [] # DDR streams # Our smurf2mce receiver # The data stream comes from TDEST 0xC1 self.smurf2mce = MceTransmit.Smurf2MCE() self.smurf2mce.setDebug( False ) # Check if we are using PCIe or Ethernet communication. if 'pcie-' in comm_type: # If we are suing PCIe communication, used AxiStreamDmas to get the DDR and streaming streams. # DDR streams. We are only using the first 2 channel of each AMC daughter card, i.e. # channels 0, 1, 4, 5. for i in [0, 1, 4, 5]: self.ddr_streams.append( rogue.hardware.axi.AxiStreamDma(pcie_dev_rssi,(pcie_rssi_lane*0x100 + 0x80 + i), True)) # Streaming interface stream self.streaming_stream = \ rogue.hardware.axi.AxiStreamDma(pcie_dev_data,(pcie_rssi_lane*0x100 + 0xC1), True) # When PCIe communication is used, we connect the stream data directly to the receiver: # Stream -> smurf2mce receiver pyrogue.streamConnect(self.streaming_stream, self.smurf2mce) else: # If we are using Ethernet: DDR streams comes over the RSSI+packetizer channel, and # the streaming streams comes over a pure UDP channel. # DDR streams. The FpgaTopLevel class will defined a 'stream' interface exposing them. # We are only using the first 2 channel of each AMC daughter card, i.e. channels 0, 1, 4, 5. for i in [0, 1, 4, 5]: self.ddr_streams.append(fpga.stream.application(0x80 + i)) # Streaming interface stream. It comes over UDP, port 8195, without RSSI, # so we use an UDP Client receiver. self.streaming_stream = rogue.protocols.udp.Client(ip_addr, 8195, True) # When Ethernet communication is used, We use a FIFO between the stream data and the receiver: # Stream -> FIFO -> smurf2mce receiver self.smurf2mce_fifo = rogue.interfaces.stream.Fifo(100000,0,True) pyrogue.streamConnect(self.streaming_stream, self.smurf2mce_fifo) pyrogue.streamConnect(self.smurf2mce_fifo, self.smurf2mce) # Create a KeepAlive object and connect it to the UDP Client. # It is used to keep the UDP connection open. This in only needed when # using Ethernet communication, as the PCIe FW implements this functionality. self.keep_alive = KeepAlive() pyrogue.streamConnect(self.keep_alive, self.streaming_stream) # Start the KeepAlive thread self.keep_alive.start() # Add data streams (0-3) to file channels (0-3) for i in range(4): ## DDR streams pyrogue.streamConnect(self.ddr_streams[i], stm_data_writer.getChannel(i)) ## Streaming interface streams # We have already connected it to the smurf2mce receiver, # so we need to tapping it to the data writer. pyrogue.streamTap(self.streaming_stream, stm_interface_writer.getChannel(0)) # Add Local variable to set the TesBias scale factor. The variable has a listener function # which is called when a new value is written to it. self.add(pyrogue.LocalVariable( name='TesBiasSF', description='Scale factor apply to the TesBias values before writing it to the MCE header', value=1.0, mode='RW')) self.TesBiasSF.addListener(self.send_test_bias_sf) # Look for the TesBias registers # TesBias register are located on # FpgaTopLevel.AppTop.AppCore.RtmCryoDet.RtmSpiMax # And their name is TesBiasDacDataRegCh[n], where x = [0:31] self.TestBiasVars = [] self.TestBiasRegEx = re.compile('.*TesBiasDacDataRegCh\[(\d+)\]$') for var in self.FpgaTopLevel.AppTop.AppCore.RtmCryoDet.RtmSpiMax.variableList: m = self.TestBiasRegEx.match(var.name) if m: reg_index = int(m[1]) - 1 if reg_index < 32: print(f'Found TesBias register: {var.name}, with index {reg_index}') self.TestBiasVars.append(var) # Check that we have all 32 TesBias registers if len(self.TestBiasVars) == 32: print(f'Found 32 TesBias registers. Assigning listener functions') # Add listener to the TesBias registers for var in self.TestBiasVars: var.addListener(self.send_test_bias) # Prepare a buffer to holds the TesBias register values self.TesBiasValue = [0] * 32 else: print(f'Error: {len(self.TestBiasVars)} TesBias register were found instead of 32. Aborting') # Run control for streaming interfaces self.add(pyrogue.RunControl( name='streamRunControl', description='Run controller', cmd=fpga.SwDaqMuxTrig, rates={ 1: '1 Hz', 10: '10 Hz', 30: '30 Hz'})) # lcaPut limits the maximun lenght of a string to 40 chars, as defined # in the EPICS R3.14 CA reference manual. This won't allowed to use the # command 'ReadConfig' with a long file path, which is usually the case. # This function is a workaround to that problem. Fomr matlab one can # just call this function without arguments an the function ReadConfig # will be called with a predefined file passed during startup # However, it can be usefull also win the GUI, so it is always added. self.config_file = config_file self.add(pyrogue.LocalCommand( name='setDefaults', description='Set default configuration', function=self.set_defaults_cmd)) # If Garbage collection was disable, add this local variable to allow users # to manually run the garbage collection. if disable_gc: self.add(pyrogue.LocalCommand( name='runGarbageCollection', description='runGarbageCollection', function=self.run_garbage_collection)) self.add(pyrogue.LocalVariable( name='mcetransmitDebug', description='Enable mce transmit debug', mode='RW', value=False, localSet=lambda value: self.smurf2mce.setDebug(value), hidden=False)) # Lost frame counter from smurf2mce self.add(pyrogue.LocalVariable( name='frameLossCnt', description='Lost frame Counter', mode='RO', value=0, localGet=self.smurf2mce.getFrameLossCnt, pollInterval=1, hidden=False)) # Received frame counter from smurf2mce self.add(pyrogue.LocalVariable( name='frameRxCnt', description='Received frame Counter', mode='RO', value=0, localGet=self.smurf2mce.getFrameRxCnt, pollInterval=1, hidden=False)) # Out-of-order frame counter from smurf2mce self.add(pyrogue.LocalVariable( name='frameOutOrderCnt', description='Number of time out-of-order frames are detected', mode='RO', value=0, localGet=self.smurf2mce.getFrameOutOrderCnt, pollInterval=1, hidden=False)) # Bad frame counter self.add(pyrogue.LocalVariable( name='badFrameCnt', description='Number of lost frames due to a bad frame', mode='RO', value=0, localGet=self.smurf2mce.getBadFrameCnt, pollInterval=1, hidden=False)) # Command to clear all the frame counters on smurf2mce self.add(pyrogue.LocalCommand( name='clearFrameCnt', description='Clear all the frame counters', function=self.smurf2mce.clearFrameCnt)) # Start the root print("Starting rogue server") self.start(pollEn=polling_en) self.ReadAll() # Call the get() method on the tesBias variable to force the call to # send_test_bias and update the array in Smurf2MCE for var in self.TestBiasVars: var.get() # Call the get method on the tesBias variable to force the call to # send_tes_bias_sf and update the factor in Smurf2MCE self.TesBiasSF.get() except KeyboardInterrupt: print("Killing server creation...") super(LocalServer, self).stop() exit() # Show image build information try: print("") print("FPGA image build information:") print("===================================") print("BuildStamp : {}"\ .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.BuildStamp.get())) print("FPGA Version : 0x{:x}"\ .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.FpgaVersion.get())) print("Git hash : 0x{:x}"\ .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.GitHash.get())) except AttributeError as attr_error: print("Attibute error: {}".format(attr_error)) print("") # Start the EPICS server if epics_prefix: print("Starting EPICS server using prefix \"{}\"".format(epics_prefix)) self.epics = pyrogue.protocols.epics.EpicsCaServer(base=epics_prefix, root=self) # PVs for stream data if stream_pv_size: print("Enabling stream data on PVs (buffer size = {} points, data type = {})"\ .format(stream_pv_size,stream_pv_type)) self.stream_fifos = [] self.stream_slaves = [] for i in range(4): self.stream_slaves.append(self.epics.createSlave(name="AMCc:Stream{}".format(i), maxSize=stream_pv_size, type=stream_pv_type)) # Calculate number of bytes needed on the fifo if '16' in stream_pv_type: fifo_size = stream_pv_size * 2 else: fifo_size = stream_pv_size * 4 self.stream_fifos.append(rogue.interfaces.stream.Fifo(1000, fifo_size, True)) # changes self.stream_fifos[i]._setSlave(self.stream_slaves[i]) pyrogue.streamTap(self.ddr_streams[i], self.stream_fifos[i]) self.epics.start() # Dump the PV list to the specified file if pv_dump_file: try: # Try to open the output file f = open(pv_dump_file, "w") except IOError: print("Could not open the PV dump file \"{}\"".format(pv_dump_file)) else: with f: print("Dumping PV list to \"{}\"...".format(pv_dump_file)) try: try: # Redirect the stdout to the output file momentarily original_stdout, sys.stdout = sys.stdout, f self.epics.dump() finally: sys.stdout = original_stdout print("Done!") except: # Capture error from epics.dump() if any print("Errors were found during epics.dump()") # If no in server Mode, start the GUI if not server_mode: create_gui(self, title=windows_title) else: # Stop the server when Crtl+C is pressed print("") print("Running in server mode now. Press Ctrl+C to stop...") try: # Wait for Ctrl+C while True: time.sleep(1) except KeyboardInterrupt: pass
top = feb.Top( ip = args.ip, pollEn = args.pollEn, initRead = args.initRead, loadYaml = args.loadYaml, defaultFile = args.defaultFile, userYaml = args.userYaml, refClkSel = args.refClkSel, ) # Create the Event reader streaming interface if (args.printEvents): eventReader = feb.PrintEventReader() # Connect the file reader to the event reader pr.streamTap(top.dataStream[0], eventReader) # Create Live Display live_display_resets = [] if args.liveDisplay: for fpga_index in range( top.numEthDev ): # Create the fifo to ensure there is no back-pressure fifo = rogue.interfaces.stream.Fifo(100, 0, True) # Connect the device reader ---> fifo pr.streamTap(top.dataStream[fpga_index], fifo) # Create the pixelreader streaming interface event_display = feb.onlineEventDisplay( plot_title='FPGA ' + str(fpga_index), submitDir='display_snapshots', font_size=4, fig_size=(10,6),
def __init__(self): pyrogue.Root.__init__(self, 'evalBoard', 'Evaluation Board') # File writer dataWriter = pyrogue.utilities.fileio.StreamWriter('dataWriter') self.add(dataWriter) # Create the PGP interfaces pgpVc0 = rogue.hardware.pgp.PgpCard('/dev/pgpcard_0', 0, 0) # Registers pgpVc1 = rogue.hardware.pgp.PgpCard('/dev/pgpcard_0', 0, 1) # Data pgpVc3 = rogue.hardware.pgp.PgpCard('/dev/pgpcard_0', 0, 3) # Microblaze print("") print("PGP Card Version: %x" % (pgpVc0.getInfo().version)) # Create and Connect SRP to VC0 srp = rogue.protocols.srp.SrpV0() pyrogue.streamConnectBiDir(pgpVc0, srp) # Add configuration stream to file as channel 0 pyrogue.streamConnect(self, dataWriter.getChannel(0x0)) # Add data stream to file as channel 1 pyrogue.streamConnect(pgpVc1, dataWriter.getChannel(0x1)) ## Add microblaze console stream to file as channel 2 pyrogue.streamConnect(pgpVc3, dataWriter.getChannel(0x2)) # PRBS Receiver as secdonary receiver for VC1 prbsRx = pyrogue.utilities.prbs.PrbsRx('prbsRx') pyrogue.streamTap(pgpVc1, prbsRx) self.add(prbsRx) # Microblaze console monitor add secondary tap mbcon = MbDebug() pyrogue.streamTap(pgpVc3, mbcon) # Add Devices self.add(surf.axi.AxiVersion(memBase=srp, offset=0x0)) self.add(surf.protocols.ssi.SsiPrbsTx(memBase=srp, offset=0x30000)) self.smem = pyrogue.smem.SMemControl(group='rogueTest', root=self) # Run control self.add( pyrogue.RunControl(name='runControl', rates={ 1: '1 Hz', 10: '10 Hz', 30: '30 Hz' })) #cmd=self.SsiPrbsTx.oneShot())) # Export remote objects self.start(pyroGroup='rogueTest') # Create epics node pvMap = { 'evalBoard.AxiVersion.UpTimeCnt': 'testCnt', 'evalBoard.AxiVersion.ScratchPad': 'testPad' } pvMap = None # Comment out to enable map self.epics = pyrogue.epics.EpicsCaServer(base='rogueTest', root=self, pvMap=pvMap) self.epics.start()