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
# of this distribution and at: # https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. # No part of the rogue_example software, including this file, may be # copied, modified, propagated, or distributed except according to the terms # contained in the LICENSE.txt file. #----------------------------------------------------------------------------- import rogue.utilities import MyModule import pyrogue import time # Data generator prbsTx = rogue.utilities.Prbs() # Our receiver rx = MyModule.MyProcessor() # Connect the stream pyrogue.streamConnect(prbsTx, rx) # Generate Data #prbsTx.enable(1000) try: while (True): prbsTx.genFrame(2176) #print(" Rx: Count {}, Bytes {}, Last {}".format(rx.getCount(), rx.getBytes(), rx.getLast())) time.sleep(.0025) rx.printTransmitStatistic()