Skip to content

Commit

Permalink
Modifications for handling cycle based cfg for WaveRunner and debuggi…
Browse files Browse the repository at this point in the history
…ng after scripting changes

Signed-off-by: Johann Heyszl <[email protected]>
  • Loading branch information
Johann Heyszl committed Dec 5, 2023
1 parent 19a084e commit 7e178ea
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 26 deletions.
6 changes: 3 additions & 3 deletions capture/capture_aes.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,11 @@ def setup(cfg: dict, project: Path):
# Init scope.
scope_type = cfg["capture"]["scope_select"]

# Determine sampling rate, if necessary.
# Will determine sampling rate (for Husky only), if not given in cfg.
cfg[scope_type]["sampling_rate"] = determine_sampling_rate(cfg, scope_type)
# Convert number of cycles into number of samples, if necessary.
# Will convert number of cycles into number of samples if they are not given in cfg.
cfg[scope_type]["num_samples"] = convert_num_cycles(cfg, scope_type)
# Convert offset in cycles into offset in samples, if necessary.
# Will convert offset in cycles into offset in samples, if they are not given in cfg.
cfg[scope_type]["offset_samples"] = convert_offset_cycles(cfg, scope_type)

logger.info(f"Initializing scope {scope_type} with a sampling rate of {cfg[scope_type]['sampling_rate']}...") # noqa: E501
Expand Down
11 changes: 9 additions & 2 deletions capture/configs/aes_sca_cw310.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,15 @@ husky:
waverunner:
waverunner_ip: 100.107.71.10
num_segments: 20
num_samples: 6000
sample_offset: 0
# num_samples: 6000
# offset_samples: 0
# cycles will only be used if not given in samples
num_cycles: 60
offset_cycles: 0
# sampling rate needed for cycle to sample conversion
sampling_rate: 2500000000
channel: C1
sparsing: 0
capture:
scope_select: husky
# scope_select: waverunner
Expand Down
34 changes: 22 additions & 12 deletions capture/scopes/cycle_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@


def convert_num_cycles(cfg: dict, scope_type: str) -> int:
""" Convert number of cycles to number of samples.
""" Converts number of cycles to number of samples if samples not given.
As Husky is configured in number of samples, this function converts the
number of cycles to samples. The number of samples must be divisble by 3
for batch captures.
As the scopes are configured in number of samples, this function converts
the number of cycles to samples.
The number of samples must be divisble by 3 for batch captures on Husky
and is adjusted accordingly.
Args:
dict: The scope configuration.
Expand All @@ -17,15 +18,21 @@ def convert_num_cycles(cfg: dict, scope_type: str) -> int:
Returns:
The number of samples.
"""
sampling_target_ratio = cfg[scope_type].get("sampling_rate") / cfg["target"].get("target_freq")
num_samples = int(cfg[scope_type].get("num_cycles") * sampling_target_ratio)
if num_samples % 3:
num_samples = num_samples + 3 - (num_samples % 3)
return num_samples
if cfg[scope_type].get("num_samples") is None:
sampl_target_rat = cfg[scope_type].get("sampling_rate") / cfg["target"].get("target_freq")
num_samples = int(cfg[scope_type].get("num_cycles") * sampl_target_rat)

if scope_type == "husky":
if num_samples % 3:
num_samples = num_samples + 3 - (num_samples % 3)

return num_samples
else:
return cfg[scope_type].get("num_samples")


def convert_offset_cycles(cfg: dict, scope_type: str) -> int:
""" Convert offset in cycles to offset in samples.
""" Converts offset in cycles to offset in samples if not given in samples.
Args:
dict: The scope configuration.
Expand All @@ -34,5 +41,8 @@ def convert_offset_cycles(cfg: dict, scope_type: str) -> int:
Returns:
The offset in samples.
"""
sampling_target_ratio = cfg[scope_type].get("sampling_rate") / cfg["target"].get("target_freq")
return int(cfg[scope_type].get("offset_cycles") * sampling_target_ratio)
if cfg[scope_type].get("offset_samples") is None:
sampl_target_rat = cfg[scope_type].get("sampling_rate") / cfg["target"].get("target_freq")
return int(cfg[scope_type].get("offset_cycles") * sampl_target_rat)
else:
return cfg[scope_type].get("offset_samples")
23 changes: 16 additions & 7 deletions capture/scopes/scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

import re
from dataclasses import dataclass
from typing import Optional

Expand Down Expand Up @@ -31,7 +32,7 @@ def determine_sampling_rate(cfg: dict, scope_type: str) -> int:
""" Determine sampling rate.
If no sampling rate is provided, calculate for Husky or receive from
Waverunner.
WaveRunner.
Args:
dict: The scope configuration.
Expand All @@ -40,7 +41,7 @@ def determine_sampling_rate(cfg: dict, scope_type: str) -> int:
Returns:
Sampling rate
"""
if not cfg[scope_type].get("sampling_rate"):
if cfg[scope_type].get("sampling_rate") is None:
if scope_type == "husky":
# If no sampling rate is provided, calculte it. Max. sampling
# rate of Husky is 200e6. As adc_mul needs to be an integer,
Expand All @@ -49,9 +50,9 @@ def determine_sampling_rate(cfg: dict, scope_type: str) -> int:
adc_mul = int(SAMPLING_RATE_MAX // cfg["target"]["pll_frequency"])
return (adc_mul * cfg["target"]["pll_frequency"])
else:
# TODO: Implement for Waverunner. Get sampling rate from scope and
# return.
return None
# Waverunner init not done yet, so cannot be read from WaveRunner.
raise RuntimeError("WAVERUNNER: ERROR: Sampling rate for WaveRunner "
"not given in configuration.")
else:
return cfg[scope_type].get("sampling_rate")

Expand Down Expand Up @@ -84,10 +85,18 @@ def _init_scope(self):
scope.configure_batch_mode()
return scope
elif self.scope_cfg.scope_type == "waverunner":
# TODO WaveRunner needs to be adapted to new cycle-based config.
# (Issue lowrisc/ot-sca#210)
if self.scope_cfg.ip:
scope = WaveRunner(self.scope_cfg.ip)

# Get current sampling rate from scope compare to cfg for sanity
setup_data = scope._ask("PANEL_SETUP?")
scope._get_and_print_cmd_error()
tmp_sampling_rate = int(re.findall(r'SampleRate = \d+', setup_data)[0][13:])
if self.scope_cfg.sampling_rate is not None:
if self.scope_cfg.sampling_rate != tmp_sampling_rate:
raise RuntimeError("WAVERUNNER: Error: WaveRunner sampling "
"rate does not match given configuration!")

scope.configure_waveform_transfer_general(
num_segments = self.scope_cfg.num_segments,
sparsing = self.scope_cfg.sparsing,
Expand Down
9 changes: 7 additions & 2 deletions capture/scopes/waverunner/waverunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,12 @@ def _parse_waveform(self, data):
len_ = int(data[13:22])
# Note: We use frombufer to minimize processing overhead.
waves = np.frombuffer(data, np.int8, int(len_), 22)
waves = waves.reshape((self.num_segments, self.num_samples))
# Reshape
waves = waves.reshape((self.num_segments, int(waves.shape[0] / self.num_segments)))
if waves.shape[1] != self.num_samples:
print("WAVERUNNER: ERROR: scope returned too many samples per trace or segment")
# Truncate, but means scope returns more samples than expected!
waves = waves[:, 0:self.num_samples]
return waves

def capture_and_transfer_waves(self):
Expand All @@ -390,7 +395,7 @@ def capture_and_transfer_waves(self):
elif self.acqu_channel == "C4":
data = self._ask_raw(b"C4:WF? DAT1")
else:
print("WAVERUNNER: Error: Channel selection invalid")
raise RuntimeError("WAVERUNNER: Error: Channel selection invalid")
waves = self._parse_waveform(data)
# Put into uint8 range
waves = waves + 128
Expand Down

0 comments on commit 7e178ea

Please sign in to comment.