forked from M-Labs/artiq
comm_analyzer, waveform add ndecimals
This commit is contained in:
parent
efb8aaf9f9
commit
720cbb4490
|
@ -8,11 +8,15 @@ from enum import Enum
|
||||||
import struct
|
import struct
|
||||||
import logging
|
import logging
|
||||||
import socket
|
import socket
|
||||||
|
import math
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_REF_PERIOD = 1e-9
|
||||||
|
|
||||||
|
|
||||||
class MessageType(Enum):
|
class MessageType(Enum):
|
||||||
output = 0b00
|
output = 0b00
|
||||||
input = 0b01
|
input = 0b01
|
||||||
|
@ -228,7 +232,7 @@ class VCDManager:
|
||||||
def set_timescale_ps(self, timescale):
|
def set_timescale_ps(self, timescale):
|
||||||
self.out.write("$timescale {}ps $end\n".format(round(timescale)))
|
self.out.write("$timescale {}ps $end\n".format(round(timescale)))
|
||||||
|
|
||||||
def get_channel(self, name, width, ty):
|
def get_channel(self, name, width, ty, ndecimals=0):
|
||||||
code = next(self.codes)
|
code = next(self.codes)
|
||||||
self.out.write("$var wire {width} {code} {name} $end\n"
|
self.out.write("$var wire {width} {code} {name} $end\n"
|
||||||
.format(name=name, code=code, width=width))
|
.format(name=name, code=code, width=width))
|
||||||
|
@ -265,9 +269,9 @@ class WaveformManager:
|
||||||
def set_timescale_ps(self, timescale):
|
def set_timescale_ps(self, timescale):
|
||||||
self.trace["timescale"] = int(timescale)
|
self.trace["timescale"] = int(timescale)
|
||||||
|
|
||||||
def get_channel(self, name, width, ty):
|
def get_channel(self, name, width, ty, ndecimals=0):
|
||||||
if ty == WaveformType.LOG:
|
if ty == WaveformType.LOG:
|
||||||
self.trace["logs"][self.current_scope + name] = (width, ty)
|
self.trace["logs"][self.current_scope + name] = (width, ty, ndecimals)
|
||||||
data = self.trace["data"][self.current_scope + name] = list()
|
data = self.trace["data"][self.current_scope + name] = list()
|
||||||
channel = WaveformChannel(data, self.current_time)
|
channel = WaveformChannel(data, self.current_time)
|
||||||
self.channels.append(channel)
|
self.channels.append(channel)
|
||||||
|
@ -318,8 +322,8 @@ class ChannelSignatureManager:
|
||||||
self.current_scope = ""
|
self.current_scope = ""
|
||||||
self.channels = dict()
|
self.channels = dict()
|
||||||
|
|
||||||
def get_channel(self, name, width, ty):
|
def get_channel(self, name, width, ty, ndecimals=0):
|
||||||
self.channels[self.current_scope + name] = (width, ty)
|
self.channels[self.current_scope + name] = (width, ty, ndecimals)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
|
@ -361,8 +365,9 @@ class TTLClockGenHandler:
|
||||||
def __init__(self, manager, name, ref_period):
|
def __init__(self, manager, name, ref_period):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.ref_period = ref_period
|
self.ref_period = ref_period
|
||||||
|
ndecimals = max(0, math.ceil(math.log10(2**24 * ref_period)))
|
||||||
self.channel_frequency = manager.get_channel(
|
self.channel_frequency = manager.get_channel(
|
||||||
"ttl_clkgen/" + name, 64, ty=WaveformType.ANALOG)
|
"ttl_clkgen/" + name, 64, ty=WaveformType.ANALOG, ndecimals=ndecimals)
|
||||||
|
|
||||||
def process_message(self, message):
|
def process_message(self, message):
|
||||||
if isinstance(message, OutputMessage):
|
if isinstance(message, OutputMessage):
|
||||||
|
@ -383,11 +388,17 @@ class DDSHandler:
|
||||||
|
|
||||||
def add_dds_channel(self, name, dds_channel_nr):
|
def add_dds_channel(self, name, dds_channel_nr):
|
||||||
dds_channel = dict()
|
dds_channel = dict()
|
||||||
|
frequency_decimals = max(0, math.ceil(math.log10(2**32 / self.sysclk)))
|
||||||
|
phase_decimals = max(0, math.ceil(math.log10(2**16)))
|
||||||
with self.manager.scope("dds", name):
|
with self.manager.scope("dds", name):
|
||||||
dds_channel["vcd_frequency"] = \
|
dds_channel["vcd_frequency"] = \
|
||||||
self.manager.get_channel(name + "/frequency", 64, ty=WaveformType.ANALOG)
|
self.manager.get_channel(name + "/frequency", 64,
|
||||||
|
ty=WaveformType.ANALOG,
|
||||||
|
ndecimals=frequency_decimals)
|
||||||
dds_channel["vcd_phase"] = \
|
dds_channel["vcd_phase"] = \
|
||||||
self.manager.get_channel(name + "/phase", 64, ty=WaveformType.ANALOG)
|
self.manager.get_channel(name + "/phase", 64,
|
||||||
|
ty=WaveformType.ANALOG,
|
||||||
|
ndecimals=phase_decimals)
|
||||||
dds_channel["ftw"] = [None, None]
|
dds_channel["ftw"] = [None, None]
|
||||||
dds_channel["pow"] = None
|
dds_channel["pow"] = None
|
||||||
self.dds_channels[dds_channel_nr] = dds_channel
|
self.dds_channels[dds_channel_nr] = dds_channel
|
||||||
|
@ -662,8 +673,12 @@ def get_channel_list(devices):
|
||||||
manager = ChannelSignatureManager()
|
manager = ChannelSignatureManager()
|
||||||
create_channel_handlers(manager, devices, 1e-9, 3e9, False)
|
create_channel_handlers(manager, devices, 1e-9, 3e9, False)
|
||||||
manager.get_channel("timestamp", 64, ty=WaveformType.VECTOR)
|
manager.get_channel("timestamp", 64, ty=WaveformType.VECTOR)
|
||||||
manager.get_channel("interval", 64, ty=WaveformType.ANALOG)
|
ref_period = get_ref_period(devices)
|
||||||
manager.get_channel("rtio_slack", 64, ty=WaveformType.ANALOG)
|
if ref_period is None:
|
||||||
|
ref_period = DEFAULT_REF_PERIOD
|
||||||
|
ndecimals = max(0, math.ceil(math.log10(1 / ref_period)))
|
||||||
|
manager.get_channel("interval", 64, ty=WaveformType.ANALOG, ndecimals=ndecimals)
|
||||||
|
manager.get_channel("rtio_slack", 64, ty=WaveformType.ANALOG, ndecimals=ndecimals)
|
||||||
return manager.channels
|
return manager.channels
|
||||||
|
|
||||||
|
|
||||||
|
@ -685,12 +700,11 @@ def decoded_dump_to_waveform_data(devices, dump, uniform_interval=False):
|
||||||
def decoded_dump_to_target(manager, devices, dump, uniform_interval):
|
def decoded_dump_to_target(manager, devices, dump, uniform_interval):
|
||||||
ref_period = get_ref_period(devices)
|
ref_period = get_ref_period(devices)
|
||||||
|
|
||||||
if ref_period is not None:
|
if ref_period is None:
|
||||||
if not uniform_interval:
|
|
||||||
manager.set_timescale_ps(ref_period*1e12)
|
|
||||||
else:
|
|
||||||
logger.warning("unable to determine core device ref_period")
|
logger.warning("unable to determine core device ref_period")
|
||||||
ref_period = 1e-9 # guess
|
ref_period = DEFAULT_REF_PERIOD
|
||||||
|
if not uniform_interval:
|
||||||
|
manager.set_timescale_ps(ref_period*1e12)
|
||||||
dds_sysclk = get_dds_sysclk(devices)
|
dds_sysclk = get_dds_sysclk(devices)
|
||||||
if dds_sysclk is None:
|
if dds_sysclk is None:
|
||||||
logger.warning("unable to determine DDS sysclk")
|
logger.warning("unable to determine DDS sysclk")
|
||||||
|
|
|
@ -122,7 +122,8 @@ class _BackgroundItem(pg.GraphicsWidgetAnchor, pg.GraphicsWidget):
|
||||||
class _BaseWaveform(pg.PlotWidget):
|
class _BaseWaveform(pg.PlotWidget):
|
||||||
cursorMove = QtCore.pyqtSignal(float)
|
cursorMove = QtCore.pyqtSignal(float)
|
||||||
|
|
||||||
def __init__(self, name, width, parent=None, pen="r", stepMode="right", connect="finite"):
|
def __init__(self, name, width, ndecimals,
|
||||||
|
parent=None, pen="r", stepMode="right", connect="finite"):
|
||||||
pg.PlotWidget.__init__(self,
|
pg.PlotWidget.__init__(self,
|
||||||
parent=parent,
|
parent=parent,
|
||||||
x=None,
|
x=None,
|
||||||
|
@ -138,6 +139,8 @@ class _BaseWaveform(pg.PlotWidget):
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
self.width = width
|
self.width = width
|
||||||
|
self.ndecimals = ndecimals
|
||||||
|
|
||||||
self.x_data = []
|
self.x_data = []
|
||||||
self.y_data = []
|
self.y_data = []
|
||||||
|
|
||||||
|
@ -223,8 +226,8 @@ class _BaseWaveform(pg.PlotWidget):
|
||||||
|
|
||||||
|
|
||||||
class BitWaveform(_BaseWaveform):
|
class BitWaveform(_BaseWaveform):
|
||||||
def __init__(self, name, width, parent=None):
|
def __init__(self, name, width, ndecimals, parent=None):
|
||||||
_BaseWaveform.__init__(self, name, width, parent)
|
_BaseWaveform.__init__(self, name, width, ndecimals, parent)
|
||||||
self._arrows = []
|
self._arrows = []
|
||||||
|
|
||||||
def onDataChange(self, data):
|
def onDataChange(self, data):
|
||||||
|
@ -266,8 +269,9 @@ class BitWaveform(_BaseWaveform):
|
||||||
|
|
||||||
|
|
||||||
class AnalogWaveform(_BaseWaveform):
|
class AnalogWaveform(_BaseWaveform):
|
||||||
def __init__(self, name, width, parent=None):
|
def __init__(self, name, width, ndecimals, parent=None):
|
||||||
_BaseWaveform.__init__(self, name, width, parent)
|
_BaseWaveform.__init__(self, name, width, ndecimals, parent)
|
||||||
|
self._format_string = "{:." + str(ndecimals) + "f}"
|
||||||
|
|
||||||
def onDataChange(self, data):
|
def onDataChange(self, data):
|
||||||
_BaseWaveform.onDataChange(self, data)
|
_BaseWaveform.onDataChange(self, data)
|
||||||
|
@ -283,12 +287,15 @@ class AnalogWaveform(_BaseWaveform):
|
||||||
|
|
||||||
def onCursorMove(self, x):
|
def onCursorMove(self, x):
|
||||||
_BaseWaveform.onCursorMove(self, x)
|
_BaseWaveform.onCursorMove(self, x)
|
||||||
self.cursor_label.setText(self.cursor_y)
|
t = None
|
||||||
|
if self.cursor_y is not None:
|
||||||
|
t = self._format_string.format(self.cursor_y)
|
||||||
|
self.cursor_label.setText(t)
|
||||||
|
|
||||||
|
|
||||||
class BitVectorWaveform(_BaseWaveform):
|
class BitVectorWaveform(_BaseWaveform):
|
||||||
def __init__(self, name, width, parent=None):
|
def __init__(self, name, width, ndecimals, parent=None):
|
||||||
_BaseWaveform.__init__(self, name, width, parent)
|
_BaseWaveform.__init__(self, name, width, ndecimals, parent)
|
||||||
self._labels = []
|
self._labels = []
|
||||||
self._format_string = "{:0=" + str(math.ceil(width / 4)) + "X}"
|
self._format_string = "{:0=" + str(math.ceil(width / 4)) + "X}"
|
||||||
self.view_box.sigTransformChanged.connect(self._update_labels)
|
self.view_box.sigTransformChanged.connect(self._update_labels)
|
||||||
|
@ -345,8 +352,8 @@ class BitVectorWaveform(_BaseWaveform):
|
||||||
|
|
||||||
|
|
||||||
class LogWaveform(_BaseWaveform):
|
class LogWaveform(_BaseWaveform):
|
||||||
def __init__(self, name, width, parent=None):
|
def __init__(self, name, width, ndecimals, parent=None):
|
||||||
_BaseWaveform.__init__(self, name, width, parent)
|
_BaseWaveform.__init__(self, name, width, ndecimals, parent)
|
||||||
self.plot_data_item.opts['pen'] = None
|
self.plot_data_item.opts['pen'] = None
|
||||||
self.plot_data_item.opts['symbol'] = 'x'
|
self.plot_data_item.opts['symbol'] = 'x'
|
||||||
self._labels = []
|
self._labels = []
|
||||||
|
@ -454,8 +461,9 @@ class _WaveformView(QtWidgets.QWidget):
|
||||||
def onDataChange(self, top, bottom, roles):
|
def onDataChange(self, top, bottom, roles):
|
||||||
first = top.row()
|
first = top.row()
|
||||||
last = bottom.row()
|
last = bottom.row()
|
||||||
|
data_row = self._model.headers.index("data")
|
||||||
for i in range(first, last + 1):
|
for i in range(first, last + 1):
|
||||||
data = self._model.data(self._model.index(i, 3))
|
data = self._model.data(self._model.index(i, data_row))
|
||||||
self._splitter.widget(i).onDataChange(data)
|
self._splitter.widget(i).onDataChange(data)
|
||||||
|
|
||||||
def onInsert(self, parent, first, last):
|
def onInsert(self, parent, first, last):
|
||||||
|
@ -481,16 +489,15 @@ class _WaveformView(QtWidgets.QWidget):
|
||||||
self._splitter.widget(i).onCursorMove(x)
|
self._splitter.widget(i).onCursorMove(x)
|
||||||
|
|
||||||
def _create_waveform(self, row):
|
def _create_waveform(self, row):
|
||||||
name = self._model.data(self._model.index(row, 0))
|
name, ty, width, ndecimals = (
|
||||||
ty = self._model.data(self._model.index(row, 1))
|
self._model.data(self._model.index(row, i)) for i in range(4))
|
||||||
width = self._model.data(self._model.index(row, 2))
|
|
||||||
waveform_cls = {
|
waveform_cls = {
|
||||||
WaveformType.BIT: BitWaveform,
|
WaveformType.BIT: BitWaveform,
|
||||||
WaveformType.VECTOR: BitVectorWaveform,
|
WaveformType.VECTOR: BitVectorWaveform,
|
||||||
WaveformType.ANALOG: AnalogWaveform,
|
WaveformType.ANALOG: AnalogWaveform,
|
||||||
WaveformType.LOG: LogWaveform
|
WaveformType.LOG: LogWaveform
|
||||||
}[ty]
|
}[ty]
|
||||||
w = waveform_cls(name, width, parent=self._splitter)
|
w = waveform_cls(name, width, ndecimals, parent=self._splitter)
|
||||||
w.setXLink(self._ref_vb)
|
w.setXLink(self._ref_vb)
|
||||||
w.setStoppedX(self._stopped_x)
|
w.setStoppedX(self._stopped_x)
|
||||||
w.setTimescale(self._timescale)
|
w.setTimescale(self._timescale)
|
||||||
|
@ -516,7 +523,7 @@ class _WaveformView(QtWidgets.QWidget):
|
||||||
class _WaveformModel(QtCore.QAbstractTableModel):
|
class _WaveformModel(QtCore.QAbstractTableModel):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.backing_struct = []
|
self.backing_struct = []
|
||||||
self.headers = ["name", "type", "width", "data"]
|
self.headers = ["name", "type", "width", "ndecimals", "data"]
|
||||||
QtCore.QAbstractTableModel.__init__(self)
|
QtCore.QAbstractTableModel.__init__(self)
|
||||||
|
|
||||||
def rowCount(self, parent=QtCore.QModelIndex()):
|
def rowCount(self, parent=QtCore.QModelIndex()):
|
||||||
|
@ -557,11 +564,11 @@ class _WaveformModel(QtCore.QAbstractTableModel):
|
||||||
self.endRemoveRows()
|
self.endRemoveRows()
|
||||||
|
|
||||||
def export_list(self):
|
def export_list(self):
|
||||||
return [[row[0], row[1].value, row[2]] for row in self.backing_struct]
|
return [[row[0], row[1].value, row[2], row[3]] for row in self.backing_struct]
|
||||||
|
|
||||||
def import_list(self, channel_list):
|
def import_list(self, channel_list):
|
||||||
self.clear()
|
self.clear()
|
||||||
data = [[row[0], WaveformType(row[1]), row[2], []] for row in channel_list]
|
data = [[row[0], WaveformType(row[1]), row[2], row[3], []] for row in channel_list]
|
||||||
self.extend(data)
|
self.extend(data)
|
||||||
|
|
||||||
def update_data(self, waveform_data, top, bottom):
|
def update_data(self, waveform_data, top, bottom):
|
||||||
|
@ -669,8 +676,8 @@ class _AddChannelDialog(QtWidgets.QDialog):
|
||||||
for select in selection:
|
for select in selection:
|
||||||
key = self._model.index_to_key(select)
|
key = self._model.index_to_key(select)
|
||||||
if key is not None:
|
if key is not None:
|
||||||
width, ty = self._model[key].ref
|
width, ty, ndecimals = self._model[key].ref
|
||||||
channels.append([key, ty, width, []])
|
channels.append([key, ty, width, ndecimals, []])
|
||||||
self.accepted.emit(channels)
|
self.accepted.emit(channels)
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue