mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-05-03 12:04:13 +02:00
Dev/ctb clocks fix (#1434)
* introduced new type Hz, typetraits, String conversions, command generation (not yet generated) * incorrect unit typo * cmd generation and compiles * default to MHz, removed space between units for consistency with timers, min and max checks for clks * in python, but need to change the default to Hz again for clean code and intuition * allow ints, doubles, implicit conversions * dont allow raw ints, doubles and implicit conversions * fixed tests * added operators for Hz in python * fix test for min clk for xilinx ctb * fix test * fix python tests * fixed xilinx period and default clks * test fix * removed the 3 clock cycle check for ctb and implemented properly the max adc clk frq for altera ctb * removing 3 clock cycle code from xilinx as well * formatting * loadpattern before 3 clk cycles code * actualtime and measurement time to be implemented in 100ns already in fw * fix tests * pyzmq dependency forthe tests * fixed pyctbgui for freq
This commit is contained in:
@@ -13,6 +13,7 @@ pybind11_add_module(_slsdet
|
||||
src/DurationWrapper.cpp
|
||||
src/pedestal.cpp
|
||||
src/bit.cpp
|
||||
src/frequency.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(_slsdet PUBLIC
|
||||
|
||||
@@ -34,6 +34,9 @@ scanParameters = _slsdet.scanParameters
|
||||
currentSrcParameters = _slsdet.currentSrcParameters
|
||||
DurationWrapper = _slsdet.DurationWrapper
|
||||
pedestalParameters = _slsdet.pedestalParameters
|
||||
Hz = _slsdet.Hz
|
||||
kHz = _slsdet.kHz
|
||||
MHz = _slsdet.MHz
|
||||
|
||||
import os
|
||||
def read_version():
|
||||
|
||||
+37
-38
@@ -14,11 +14,12 @@ powerIndex = slsDetectorDefs.powerIndex
|
||||
detectorType = slsDetectorDefs.detectorType
|
||||
streamingInterface = slsDetectorDefs.streamingInterface
|
||||
|
||||
|
||||
defs = slsDetectorDefs
|
||||
|
||||
from .utils import element_if_equal, all_equal, get_set_bits, list_to_bitmask
|
||||
from .utils import Geometry, to_geo, element, reduce_time, is_iterable, hostname_list
|
||||
from ._slsdet import xy, freeSharedMemory, getUserDetails
|
||||
from ._slsdet import xy, Hz, freeSharedMemory, getUserDetails
|
||||
from .gaincaps import Mythen3GainCapsWrapper
|
||||
from . import utils as ut
|
||||
from .proxy import JsonProxy, ClkDivProxy, MaxPhaseProxy, ClkFreqProxy, PatLoopProxy, PatNLoopProxy, PatWaitProxy, PatWaitTimeProxy
|
||||
@@ -3441,22 +3442,21 @@ class Detector(CppDetectorApi):
|
||||
@element
|
||||
def runclk(self):
|
||||
"""
|
||||
[Ctb][Xilinx Ctb] Sets Run clock frequency in MHz. \n
|
||||
Accepts decimal inputs
|
||||
"""
|
||||
[Ctb][Xilinx Ctb] Sets Run clock frequency.
|
||||
|
||||
freq_hz = element_if_equal(self.getRUNClock())
|
||||
if isinstance(freq_hz, list):
|
||||
return [value / 1e6 for value in freq_hz]
|
||||
return freq_hz / 1e6
|
||||
Example
|
||||
--------
|
||||
>>> d.runclk
|
||||
>>> 10MHz
|
||||
>>> d.runclk = MHz(5)
|
||||
>>> d.runclk = Hz(5 * 1000 * 1000)
|
||||
>>> d.runclk = kHz(2000)
|
||||
"""
|
||||
return self.getRUNClock()
|
||||
|
||||
@runclk.setter
|
||||
def runclk(self, freq):
|
||||
if isinstance(freq, dict):
|
||||
freq_hz = {key: int(round(value * 1e6)) for key, value in freq.items()}
|
||||
else:
|
||||
freq_hz = int(round(freq * 1e6))
|
||||
ut.set_using_dict(self.setRUNClock, freq_hz)
|
||||
ut.set_using_dict(self.setRUNClock, freq)
|
||||
|
||||
@property
|
||||
@element
|
||||
@@ -3533,21 +3533,21 @@ class Detector(CppDetectorApi):
|
||||
@element
|
||||
def dbitclk(self):
|
||||
"""
|
||||
[Ctb][Xilinx Ctb] Sets clock for latching the digital bits in MHz. \n
|
||||
Accepts decimal inputs
|
||||
[Ctb][Xilinx Ctb] Sets clock for latching the digital bits.
|
||||
|
||||
Example
|
||||
--------
|
||||
>>> d.dbitclk
|
||||
>>> 10MHz
|
||||
>>> d.dbitclk = MHz(5)
|
||||
>>> d.dbitclk = Hz(5 * 1000 * 1000)
|
||||
>>> d.dbitclk = kHz(2000)
|
||||
"""
|
||||
freq_hz = element_if_equal(self.getDBITClock())
|
||||
if isinstance(freq_hz, list):
|
||||
return [value / 1e6 for value in freq_hz]
|
||||
return freq_hz / 1e6
|
||||
return self.getDBITClock()
|
||||
|
||||
@dbitclk.setter
|
||||
def dbitclk(self, value):
|
||||
if isinstance(value, dict):
|
||||
value_hz = {key: int(round(item * 1e6)) for key, item in value.items()}
|
||||
else:
|
||||
value_hz = int(round(value * 1e6))
|
||||
ut.set_using_dict(self.setDBITClock, value_hz)
|
||||
ut.set_using_dict(self.setDBITClock, value)
|
||||
|
||||
@property
|
||||
@element
|
||||
@@ -3670,28 +3670,27 @@ class Detector(CppDetectorApi):
|
||||
@element
|
||||
def adcclk(self):
|
||||
"""
|
||||
[Ctb][Xilinx Ctb] Sets ADC clock frequency in MHz. \n
|
||||
Accepts decimal inputs
|
||||
"""
|
||||
[Ctb][Xilinx Ctb] Sets ADC clock frequency.
|
||||
|
||||
freq_hz = element_if_equal(self.getADCClock())
|
||||
if isinstance(freq_hz, list):
|
||||
return [value / 1e6 for value in freq_hz]
|
||||
return freq_hz / 1e6
|
||||
Example
|
||||
--------
|
||||
>>> d.adcclk
|
||||
>>> 10MHz
|
||||
>>> d.adcclk = MHz(5)
|
||||
>>> d.adcclk = Hz(5 * 1000 * 1000)
|
||||
>>> d.adcclk = kHz(2000)
|
||||
"""
|
||||
return self.getADCClock()
|
||||
|
||||
@adcclk.setter
|
||||
def adcclk(self, value):
|
||||
if isinstance(value, dict):
|
||||
value_hz = {key: int(round(item * 1e6)) for key, item in value.items()}
|
||||
else:
|
||||
value_hz = int(round(value * 1e6))
|
||||
ut.set_using_dict(self.setADCClock, value_hz)
|
||||
ut.set_using_dict(self.setADCClock, value)
|
||||
|
||||
@property
|
||||
@element
|
||||
def syncclk(self):
|
||||
"""
|
||||
[Ctb] Sync clock in MHz.
|
||||
[Ctb] Sync clock.
|
||||
|
||||
:setter: Not implemented
|
||||
"""
|
||||
@@ -3724,7 +3723,7 @@ class Detector(CppDetectorApi):
|
||||
[Ctb][Mythen3][Xilinx Ctb] Gets the pattern file name including path of the last pattern uploaded. Returns an empty if nothing was uploaded or via a server default
|
||||
file
|
||||
"""
|
||||
return self.getPatterFileName()
|
||||
return self.getPatternFileName()
|
||||
|
||||
def patternstart(self):
|
||||
"""[Ctb][Mythen3][Xilinx Ctb] Starts pattern. """
|
||||
|
||||
+15
-15
@@ -1529,23 +1529,31 @@ void init_det(py::module &m) {
|
||||
Detector::setNumberOfAnalogSamples,
|
||||
py::arg(), py::arg() = Positions{});
|
||||
CppDetectorApi.def("getADCClock",
|
||||
(Result<int>(Detector::*)(sls::Positions) const) &
|
||||
(Result<defs::Hz>(Detector::*)(sls::Positions) const) &
|
||||
Detector::getADCClock,
|
||||
py::arg() = Positions{});
|
||||
CppDetectorApi.def("setADCClock",
|
||||
(void (Detector::*)(int, sls::Positions)) &
|
||||
(void (Detector::*)(defs::Hz, sls::Positions)) &
|
||||
Detector::setADCClock,
|
||||
py::arg(), py::arg() = Positions{});
|
||||
CppDetectorApi.def("getRUNClock",
|
||||
(Result<int>(Detector::*)(sls::Positions) const) &
|
||||
(Result<defs::Hz>(Detector::*)(sls::Positions) const) &
|
||||
Detector::getRUNClock,
|
||||
py::arg() = Positions{});
|
||||
CppDetectorApi.def("setRUNClock",
|
||||
(void (Detector::*)(int, sls::Positions)) &
|
||||
(void (Detector::*)(defs::Hz, sls::Positions)) &
|
||||
Detector::setRUNClock,
|
||||
py::arg(), py::arg() = Positions{});
|
||||
CppDetectorApi.def("getDBITClock",
|
||||
(Result<defs::Hz>(Detector::*)(sls::Positions) const) &
|
||||
Detector::getDBITClock,
|
||||
py::arg() = Positions{});
|
||||
CppDetectorApi.def("setDBITClock",
|
||||
(void (Detector::*)(defs::Hz, sls::Positions)) &
|
||||
Detector::setDBITClock,
|
||||
py::arg(), py::arg() = Positions{});
|
||||
CppDetectorApi.def("getSYNCClock",
|
||||
(Result<int>(Detector::*)(sls::Positions) const) &
|
||||
(Result<defs::Hz>(Detector::*)(sls::Positions) const) &
|
||||
Detector::getSYNCClock,
|
||||
py::arg() = Positions{});
|
||||
CppDetectorApi.def("getPowerList",
|
||||
@@ -1646,14 +1654,6 @@ void init_det(py::module &m) {
|
||||
(void (Detector::*)(defs::readoutMode, sls::Positions)) &
|
||||
Detector::setReadoutMode,
|
||||
py::arg(), py::arg() = Positions{});
|
||||
CppDetectorApi.def("getDBITClock",
|
||||
(Result<int>(Detector::*)(sls::Positions) const) &
|
||||
Detector::getDBITClock,
|
||||
py::arg() = Positions{});
|
||||
CppDetectorApi.def("setDBITClock",
|
||||
(void (Detector::*)(int, sls::Positions)) &
|
||||
Detector::setDBITClock,
|
||||
py::arg(), py::arg() = Positions{});
|
||||
CppDetectorApi.def("getExternalSamplingSource",
|
||||
(Result<int>(Detector::*)(sls::Positions) const) &
|
||||
Detector::getExternalSamplingSource,
|
||||
@@ -1891,9 +1891,9 @@ void init_det(py::module &m) {
|
||||
Detector::configureTransceiver,
|
||||
py::arg() = Positions{});
|
||||
CppDetectorApi.def(
|
||||
"getPatterFileName",
|
||||
"getPatternFileName",
|
||||
(Result<std::string>(Detector::*)(sls::Positions) const) &
|
||||
Detector::getPatterFileName,
|
||||
Detector::getPatternFileName,
|
||||
py::arg() = Positions{});
|
||||
CppDetectorApi.def(
|
||||
"setPattern",
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
/*
|
||||
This file contains Python bindings for the Hz and for conversion to other units from and to string.
|
||||
*/
|
||||
#include "py_headers.h"
|
||||
#include <cmath>
|
||||
|
||||
#include "sls/ToString.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
constexpr double kHz = 1e3;
|
||||
constexpr double MHz = 1e6;
|
||||
|
||||
void init_freq(py::module &m) {
|
||||
|
||||
py::class_<slsDetectorDefs::Hz> Hz(m, "Hz");
|
||||
Hz.def(py::init<int>());
|
||||
Hz.def_readwrite("value", &slsDetectorDefs::Hz::value);
|
||||
Hz.def("__repr__", [](const slsDetectorDefs::Hz &f) {
|
||||
return sls::ToString(f);
|
||||
});
|
||||
Hz.def("__str__", [](const slsDetectorDefs::Hz &f) {
|
||||
return sls::ToString(f);
|
||||
});
|
||||
|
||||
Hz.def(py::self == py::self);
|
||||
Hz.def("__mul__", [](const slsDetectorDefs::Hz &h, int x) {
|
||||
return slsDetectorDefs::Hz(h.value * x);
|
||||
}, py::is_operator());
|
||||
Hz.def("__rmul__", [](const slsDetectorDefs::Hz &h, int x) {
|
||||
return slsDetectorDefs::Hz(h.value * x);
|
||||
}, py::is_operator());
|
||||
Hz.def("__truediv__", [](const slsDetectorDefs::Hz &h, int x) {
|
||||
return slsDetectorDefs::Hz(h.value / x);
|
||||
}, py::is_operator());
|
||||
Hz.def("__add__", [](const slsDetectorDefs::Hz &a,
|
||||
const slsDetectorDefs::Hz &b) {
|
||||
return slsDetectorDefs::Hz(a.value + b.value);
|
||||
}, py::is_operator());
|
||||
Hz.def("__sub__", [](const slsDetectorDefs::Hz &a,
|
||||
const slsDetectorDefs::Hz &b) {
|
||||
return slsDetectorDefs::Hz(a.value - b.value);
|
||||
}, py::is_operator());
|
||||
|
||||
m.def("kHz", [](double v) {
|
||||
return slsDetectorDefs::Hz(static_cast<int>(std::round(v * kHz)));
|
||||
});
|
||||
|
||||
m.def("MHz", [](double v) {
|
||||
return slsDetectorDefs::Hz(static_cast<int>(std::round(v * MHz)));
|
||||
});
|
||||
}
|
||||
@@ -21,6 +21,7 @@ void init_source(py::module &);
|
||||
void init_duration(py::module &);
|
||||
void init_pedestal(py::module &);
|
||||
void init_bit(py::module &);
|
||||
void init_freq(py::module &);
|
||||
|
||||
PYBIND11_MODULE(_slsdet, m) {
|
||||
m.doc() = R"pbdoc(
|
||||
@@ -42,6 +43,7 @@ PYBIND11_MODULE(_slsdet, m) {
|
||||
init_duration(m);
|
||||
init_pedestal(m);
|
||||
init_bit(m);
|
||||
init_freq(m);
|
||||
// init_experimental(m);
|
||||
|
||||
py::module io = m.def_submodule("io", "Submodule for io");
|
||||
|
||||
@@ -396,6 +396,193 @@ def test_patternstart(session_simulator, request):
|
||||
Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed")
|
||||
|
||||
|
||||
|
||||
@pytest.mark.detectorintegration
|
||||
def test_runclk(session_simulator, request):
|
||||
""" Test using runclk for ctb and xilinx_ctb."""
|
||||
det_type, num_interfaces, num_mods, d = session_simulator
|
||||
assert d is not None
|
||||
|
||||
from slsdet import Hz, MHz, kHz
|
||||
|
||||
if det_type in ['ctb', 'xilinx_ctb']:
|
||||
prev_runclk = d.getRUNClock()
|
||||
|
||||
d.runclk
|
||||
|
||||
# invalid value type
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.runclk = 5e6
|
||||
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.runclk = 5 * 1000 * 1000
|
||||
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.runclk = Hz(5e6)
|
||||
|
||||
d.runclk = MHz(15)
|
||||
assert d.runclk.value == 15_000_000
|
||||
|
||||
d.runclk = MHz(14.5)
|
||||
assert d.runclk.value == 14_500_000
|
||||
|
||||
d.runclk = kHz(15000.5)
|
||||
assert d.runclk.value == 15_000_500
|
||||
|
||||
# invalid values from server
|
||||
# max is 300MHz
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.runclk = MHz(301)
|
||||
|
||||
# min is 2MHz for ctb and 10MHz for xilinx_ctb
|
||||
if det_type == 'ctb':
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.runclk = MHz(1)
|
||||
else:
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.runclk = MHz(9)
|
||||
|
||||
c = MHz(2)
|
||||
for rc in [5, 10, 15, 20]:
|
||||
d.runclk = rc * c
|
||||
assert d.runclk.value == 40_000_000
|
||||
|
||||
for i in range(len(d)):
|
||||
d.setRUNClock(prev_runclk[i], [i])
|
||||
|
||||
Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed")
|
||||
|
||||
|
||||
@pytest.mark.detectorintegration
|
||||
def test_adcclk(session_simulator, request):
|
||||
""" Test using adcclk for ctb and xilinx_ctb."""
|
||||
det_type, num_interfaces, num_mods, d = session_simulator
|
||||
assert d is not None
|
||||
|
||||
from slsdet import Hz, MHz, kHz
|
||||
|
||||
if det_type in ['ctb', 'xilinx_ctb']:
|
||||
prev_adcclk = d.getADCClock()
|
||||
|
||||
d.adcclk
|
||||
|
||||
# invalid value type
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.adcclk = 5e6
|
||||
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.adcclk = 5 * 1000 * 1000
|
||||
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.adcclk = Hz(5e6)
|
||||
|
||||
d.adcclk = MHz(15)
|
||||
assert d.adcclk.value == 15_000_000
|
||||
|
||||
d.adcclk = MHz(14.5)
|
||||
assert d.adcclk.value == 14_500_000
|
||||
|
||||
d.adcclk = kHz(15000.5)
|
||||
assert d.adcclk.value == 15_000_500
|
||||
|
||||
# invalid values from server
|
||||
# max is 300MHz for xilinx and 54 MHz for ctb
|
||||
if det_type == 'ctb':
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.adcclk = MHz(66)
|
||||
else:
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.adcclk = MHz(301)
|
||||
|
||||
# min is 2MHz for ctb and 10MHz for xilinx_ctb
|
||||
if det_type == 'ctb':
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.adcclk = MHz(1)
|
||||
else:
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.adcclk = MHz(9)
|
||||
|
||||
c = MHz(2)
|
||||
for rc in [5, 10, 15, 20]:
|
||||
d.adcclk = rc * c
|
||||
assert d.adcclk.value == 40_000_000
|
||||
|
||||
for i in range(len(d)):
|
||||
d.setADCClock(prev_adcclk[i], [i])
|
||||
|
||||
Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed")
|
||||
|
||||
|
||||
@pytest.mark.detectorintegration
|
||||
def test_dbitclk(session_simulator, request):
|
||||
""" Test using dbitclk for ctb and xilinx_ctb."""
|
||||
det_type, num_interfaces, num_mods, d = session_simulator
|
||||
assert d is not None
|
||||
|
||||
from slsdet import Hz, MHz, kHz
|
||||
|
||||
if det_type in ['ctb', 'xilinx_ctb']:
|
||||
prev_dbitclk = d.getDBITClock()
|
||||
|
||||
d.dbitclk
|
||||
|
||||
# invalid value type
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.dbitclk = 5e6
|
||||
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.dbitclk = 5 * 1000 * 1000
|
||||
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.dbitclk = Hz(5e6)
|
||||
|
||||
d.dbitclk = MHz(15)
|
||||
assert d.dbitclk.value == 15_000_000
|
||||
|
||||
d.dbitclk = MHz(14.5)
|
||||
assert d.dbitclk.value == 14_500_000
|
||||
|
||||
d.dbitclk = kHz(15000.5)
|
||||
assert d.dbitclk.value == 15_000_500
|
||||
|
||||
# invalid values from server
|
||||
# max is 300MHz
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.dbitclk = MHz(301)
|
||||
|
||||
# min is 2MHz for ctb and 10MHz for xilinx_ctb
|
||||
if det_type == 'ctb':
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.dbitclk = MHz(1)
|
||||
else:
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.dbitclk = MHz(9)
|
||||
|
||||
c = MHz(2)
|
||||
for rc in [5, 10, 15, 20]:
|
||||
d.dbitclk = rc * c
|
||||
assert d.dbitclk.value == 40_000_000
|
||||
|
||||
for i in range(len(d)):
|
||||
d.setDBITClock(prev_dbitclk[i], [i])
|
||||
|
||||
Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed")
|
||||
|
||||
|
||||
|
||||
@pytest.mark.detectorintegration
|
||||
def test_syncclk(session_simulator, request):
|
||||
""" Test using syncclk for ctb."""
|
||||
det_type, num_interfaces, num_mods, d = session_simulator
|
||||
assert d is not None
|
||||
|
||||
if det_type in ['ctb']:
|
||||
d.syncclk
|
||||
|
||||
Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed")
|
||||
|
||||
|
||||
|
||||
@pytest.mark.detectorintegration
|
||||
def test_v_limit(session_simulator, request):
|
||||
"""Test v_limit."""
|
||||
@@ -450,7 +637,7 @@ def test_v_limit(session_simulator, request):
|
||||
Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed")
|
||||
|
||||
|
||||
@pytest.mark.detectorintegration
|
||||
|
||||
def test_v_abcd(session_simulator, request):
|
||||
"""Test v_a, v_b, v_c, v_d, v_io are deprecated comands."""
|
||||
det_type, num_interfaces, num_mods, d = session_simulator
|
||||
@@ -715,3 +902,4 @@ def test_dac(session_simulator, request):
|
||||
|
||||
|
||||
Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed")
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
from slsdet import Hz, MHz, kHz
|
||||
|
||||
def test_Hz():
|
||||
f = Hz(1)
|
||||
assert f.value == 1
|
||||
f = Hz(1 * 1000)
|
||||
assert f.value == 1000
|
||||
f = MHz(5)
|
||||
assert f.value == 5_000_000
|
||||
f = MHz(0.5)
|
||||
assert f.value == 500_000
|
||||
f = kHz(2.5)
|
||||
assert f.value == 2500
|
||||
f = kHz(5000)
|
||||
assert f.value == 5_000_000
|
||||
|
||||
def test_rounding_exact():
|
||||
f = MHz(1.234)
|
||||
assert f.value == round(1.234 * 1_000_000)
|
||||
|
||||
|
||||
def test_mul():
|
||||
c = MHz(1)
|
||||
assert (c * 2).value == 2_000_000
|
||||
assert (c * 4).value == 4_000_000
|
||||
|
||||
|
||||
def test_rmul():
|
||||
c = MHz(1)
|
||||
assert (2 * c).value == 2_000_000
|
||||
assert (4 * c).value == 4_000_000
|
||||
|
||||
c = c * 2
|
||||
assert c.value == 2_000_000
|
||||
|
||||
for rc in [1, 2, 4, 8]:
|
||||
c = rc * c
|
||||
assert c.value == 128_000_000
|
||||
|
||||
|
||||
def test_div():
|
||||
c = MHz(1)
|
||||
assert (c / 2).value == 500_000
|
||||
|
||||
def test_eq():
|
||||
assert MHz(1) == MHz(1)
|
||||
assert MHz(1) != MHz(2)
|
||||
assert MHz(1) == kHz(1000)
|
||||
Reference in New Issue
Block a user