mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-04-26 16:20:03 +02:00
Adding patterntools to slsdet (#1142)
* added patterntools from mythen3tools * refactored do use implementation from slsSupportLib
This commit is contained in:
parent
5a8213024e
commit
3c2f149c22
@ -40,6 +40,7 @@ set(SPHINX_SOURCE_FILES
|
|||||||
src/pydetector.rst
|
src/pydetector.rst
|
||||||
src/pyenums.rst
|
src/pyenums.rst
|
||||||
src/pyexamples.rst
|
src/pyexamples.rst
|
||||||
|
src/pyPatternGenerator.rst
|
||||||
src/servers.rst
|
src/servers.rst
|
||||||
src/receiver_api.rst
|
src/receiver_api.rst
|
||||||
src/result.rst
|
src/result.rst
|
||||||
|
@ -36,6 +36,7 @@ Welcome to slsDetectorPackage's documentation!
|
|||||||
pydetector
|
pydetector
|
||||||
pyenums
|
pyenums
|
||||||
pyexamples
|
pyexamples
|
||||||
|
pyPatternGenerator
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:caption: Command line
|
:caption: Command line
|
||||||
|
34
docs/src/pyPatternGenerator.rst
Normal file
34
docs/src/pyPatternGenerator.rst
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
PatternGenerator
|
||||||
|
=====================================================
|
||||||
|
|
||||||
|
Python class to generate patterns for the Chip Test Board.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from slsdet import PatternGenerator
|
||||||
|
|
||||||
|
p = PatternGenerator()
|
||||||
|
p.SB(5)
|
||||||
|
p.PW()
|
||||||
|
p.SB(8,9)
|
||||||
|
p.PW()
|
||||||
|
p.CB(5)
|
||||||
|
|
||||||
|
Created a pattern like this:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
patword 0x0000 0x0000000000000020
|
||||||
|
patword 0x0001 0x0000000000000320
|
||||||
|
patword 0x0002 0x0000000000000300
|
||||||
|
patioctrl 0x0000000000000000
|
||||||
|
patlimits 0x0000 0x0002
|
||||||
|
...
|
||||||
|
|
||||||
|
.. py:currentmodule:: slsdet
|
||||||
|
|
||||||
|
.. autoclass:: PatternGenerator
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
:inherited-members:
|
@ -27,6 +27,7 @@ set_target_properties(_slsdet PROPERTIES
|
|||||||
set( PYTHON_FILES
|
set( PYTHON_FILES
|
||||||
slsdet/__init__.py
|
slsdet/__init__.py
|
||||||
slsdet/adcs.py
|
slsdet/adcs.py
|
||||||
|
slsdet/bits.py
|
||||||
slsdet/dacs.py
|
slsdet/dacs.py
|
||||||
slsdet/powers.py
|
slsdet/powers.py
|
||||||
slsdet/decorators.py
|
slsdet/decorators.py
|
||||||
@ -38,6 +39,7 @@ set( PYTHON_FILES
|
|||||||
slsdet/errors.py
|
slsdet/errors.py
|
||||||
slsdet/gaincaps.py
|
slsdet/gaincaps.py
|
||||||
slsdet/pattern.py
|
slsdet/pattern.py
|
||||||
|
slsdet/PatternGenerator.py
|
||||||
slsdet/gotthard2.py
|
slsdet/gotthard2.py
|
||||||
slsdet/moench.py
|
slsdet/moench.py
|
||||||
slsdet/proxy.py
|
slsdet/proxy.py
|
||||||
|
226
python/slsdet/PatternGenerator.py
Normal file
226
python/slsdet/PatternGenerator.py
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
from . import Detector, Pattern
|
||||||
|
from .bits import setbit, clearbit
|
||||||
|
import textwrap
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
class PatternGenerator:
|
||||||
|
"""
|
||||||
|
Class to generate a pattern for the SLS detector. Intents to as closely as possible
|
||||||
|
mimic the old pattern generation in the C code.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self.pattern = Pattern()
|
||||||
|
self.iaddr = 0
|
||||||
|
|
||||||
|
def SB(self, *bits):
|
||||||
|
"""
|
||||||
|
Set one or several bits. Change will take affect with the next PW.
|
||||||
|
"""
|
||||||
|
for bit in bits:
|
||||||
|
self.pattern.word[self.iaddr] = setbit(bit, self.pattern.word[self.iaddr])
|
||||||
|
return self.pattern.word[self.iaddr]
|
||||||
|
|
||||||
|
def CB(self, *bits):
|
||||||
|
"""
|
||||||
|
Clear one or several bits. Change will take affect with the next PW.
|
||||||
|
"""
|
||||||
|
for bit in bits:
|
||||||
|
self.pattern.word[self.iaddr] = clearbit(bit, self.pattern.word[self.iaddr])
|
||||||
|
return self.pattern.word[self.iaddr]
|
||||||
|
|
||||||
|
|
||||||
|
def _pw(self, verbose = False):
|
||||||
|
if verbose:
|
||||||
|
print(f'{self.iaddr:#06x} {self.pattern.word[self.iaddr]:#018x}')
|
||||||
|
|
||||||
|
#Limits are inclusive so we need to increment the address before writing the next word
|
||||||
|
self.pattern.limits[1] = self.iaddr
|
||||||
|
self.iaddr += 1
|
||||||
|
self.pattern.word[self.iaddr] = self.pattern.word[self.iaddr-1]
|
||||||
|
|
||||||
|
def PW(self, x = 1, verbose = False):
|
||||||
|
for i in range(x):
|
||||||
|
self._pw(verbose)
|
||||||
|
|
||||||
|
# def REPEAT(self, x, verbose = False):
|
||||||
|
# for i in range(x):
|
||||||
|
# self._pw(verbose)
|
||||||
|
|
||||||
|
# def PW2(self, verbose = 0):
|
||||||
|
# self.REPEAT(2, verbose)
|
||||||
|
|
||||||
|
|
||||||
|
def CLOCKS(self, bit, times = 1, length = 1, verbose = False):
|
||||||
|
"""
|
||||||
|
clocks "bit" n "times", every half clock is long "length"
|
||||||
|
length is optional, default value is 1
|
||||||
|
"""
|
||||||
|
for i in range(0, times):
|
||||||
|
self.SB(bit); self.PW(length, verbose)
|
||||||
|
self.CB(bit); self.PW(length, verbose)
|
||||||
|
|
||||||
|
def CLOCK(self, bit, length = 1, verbose = 0):
|
||||||
|
self.CLOCKS(bit, 1, length ,verbose)
|
||||||
|
|
||||||
|
def serializer(self, value, serInBit, clkBit, nbits, msbfirst = True, length = 1):
|
||||||
|
"""serializer(value,serInBit,clkBit,nbits,msbfirst=1,length=1)
|
||||||
|
Produces the .pat file needed to serialize a word into a shift register.
|
||||||
|
value: value to be serialized
|
||||||
|
serInBit: control bit corresponding to serial in
|
||||||
|
clkBit: control bit corresponding to the clock
|
||||||
|
nbits: number of bits of the target register to load
|
||||||
|
msbfirst: if 1 pushes in the MSB first (default),
|
||||||
|
if 0 pushes in the LSB first
|
||||||
|
length: length of all the PWs in the pattern
|
||||||
|
It produces no output because it modifies directly the members of the class pat via SB and CB"""
|
||||||
|
|
||||||
|
c = value
|
||||||
|
self.CB(serInBit, clkBit)
|
||||||
|
self.PW(length) #generate initial line with clk and serIn to 0
|
||||||
|
|
||||||
|
start = 0
|
||||||
|
stop = nbits
|
||||||
|
step = 1
|
||||||
|
|
||||||
|
if msbfirst:
|
||||||
|
start = nbits - 1
|
||||||
|
stop = -1
|
||||||
|
step =- 1 #reverts loop if msb has to be pushed in first
|
||||||
|
|
||||||
|
for i in range(start, stop, step):
|
||||||
|
if c & (1<<i):
|
||||||
|
self.SB(serInBit)
|
||||||
|
self.PW(length)
|
||||||
|
else:
|
||||||
|
self.CB(serInBit)
|
||||||
|
self.PW(length)
|
||||||
|
self.SB(clkBit)
|
||||||
|
self.PW(length)
|
||||||
|
self.CB(clkBit)
|
||||||
|
self.PW(length)
|
||||||
|
|
||||||
|
self.CB(serInBit, clkBit)
|
||||||
|
self.PW(length) #generate final line with clk and serIn to 0
|
||||||
|
|
||||||
|
|
||||||
|
#NOT IMPLEMENTED YET
|
||||||
|
#TODO! What should setstop do? Or can we remove it?
|
||||||
|
#def setstop():
|
||||||
|
#
|
||||||
|
|
||||||
|
def setoutput(self, bit):
|
||||||
|
self.pattern.ioctrl = setbit(bit, self.pattern.ioctrl)
|
||||||
|
|
||||||
|
def setinput(self, bit):
|
||||||
|
self.pattern.ioctrl= clearbit(bit, self.pattern.ioctrl)
|
||||||
|
|
||||||
|
#TODO! What should setclk do? Or can we remove it?
|
||||||
|
# def setclk(bit):
|
||||||
|
# self.clkctrl=self.setbit(bit,self.clkctrl)
|
||||||
|
|
||||||
|
def setinputs(self, *args):
|
||||||
|
for i in args:
|
||||||
|
self.setinput(i)
|
||||||
|
|
||||||
|
def setoutputs(self, *args):
|
||||||
|
for i in args:
|
||||||
|
self.setoutput(i)
|
||||||
|
|
||||||
|
#def setclks(self, *args):
|
||||||
|
# for i in args:
|
||||||
|
# self.setclk(i)
|
||||||
|
|
||||||
|
def setnloop(self, i, reps):
|
||||||
|
self.pattern.nloop[i] = reps
|
||||||
|
|
||||||
|
def setstartloop(self, i):
|
||||||
|
"""
|
||||||
|
Set startloop[i] to the current address.
|
||||||
|
"""
|
||||||
|
self.pattern.startloop[i] = self.iaddr
|
||||||
|
|
||||||
|
def setstoploop(self, i):
|
||||||
|
"""
|
||||||
|
Set stoploop[i] to the current address.
|
||||||
|
"""
|
||||||
|
self.pattern.stoploop[i] = self.iaddr
|
||||||
|
|
||||||
|
|
||||||
|
def setstart(self):
|
||||||
|
"""
|
||||||
|
Set start of pattern to the current address.
|
||||||
|
"""
|
||||||
|
self.pattern.limits[0]=self.iaddr
|
||||||
|
|
||||||
|
|
||||||
|
def setstop(self,l):
|
||||||
|
"""
|
||||||
|
Set stop of pattern to the current address.
|
||||||
|
"""
|
||||||
|
self.pattern.limits[1] = self.iaddr
|
||||||
|
|
||||||
|
|
||||||
|
def setwaitpoint(self, i):
|
||||||
|
"""
|
||||||
|
Set wait[i] to the current address.
|
||||||
|
"""
|
||||||
|
self.pattern.wait[i] = self.iaddr
|
||||||
|
|
||||||
|
|
||||||
|
def setwaittime(self, i, t):
|
||||||
|
"""
|
||||||
|
Set waittime[i] to t.
|
||||||
|
"""
|
||||||
|
self.pattern.waittime[i] = t
|
||||||
|
|
||||||
|
|
||||||
|
def setwait(self, i, t):
|
||||||
|
"""
|
||||||
|
Set wait[i] to the current address and waittime[i] to t.
|
||||||
|
"""
|
||||||
|
self.setwait(i)
|
||||||
|
self.setwaittime(i, t)
|
||||||
|
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return textwrap.dedent(f"""\
|
||||||
|
PatternBuilder:
|
||||||
|
patlimits: {self.pattern.limits}
|
||||||
|
startloop: {self.pattern.startloop}
|
||||||
|
stoploop: {self.pattern.stoploop}
|
||||||
|
nloop: {self.pattern.nloop}
|
||||||
|
wait: {self.pattern.wait}
|
||||||
|
waittime: {self.pattern.waittime}""")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.pattern.str()
|
||||||
|
|
||||||
|
def print(self):
|
||||||
|
print(self)
|
||||||
|
|
||||||
|
def save(self, fname):
|
||||||
|
"""Save pattern to text file"""
|
||||||
|
fname = str(fname) #Accept also Path objects, but C++ code needs a string
|
||||||
|
self.pattern.save(fname)
|
||||||
|
|
||||||
|
def load(self, fname):
|
||||||
|
"""Load pattern from text file"""
|
||||||
|
fname = str(fname) #Accept also Path objects, but C++ code needs a string
|
||||||
|
n = self.pattern.load(fname)
|
||||||
|
|
||||||
|
#If the firs and only word is 0 we assume an empty pattern
|
||||||
|
if n == 1 and self.pattern.word[0] == 0:
|
||||||
|
n = 0
|
||||||
|
self.iaddr = n
|
||||||
|
|
||||||
|
#To make PW work as expected we need to set 1+last word to the last word
|
||||||
|
if n > 0:
|
||||||
|
self.pattern.word[n] = self.pattern.word[n-1]
|
||||||
|
|
||||||
|
|
||||||
|
def send_to_detector(self, det):
|
||||||
|
"""
|
||||||
|
Load the pattern into the detector.
|
||||||
|
"""
|
||||||
|
det.setPattern(self.pattern)
|
@ -12,6 +12,7 @@ from .gotthard2 import Gotthard2
|
|||||||
from .moench import Moench
|
from .moench import Moench
|
||||||
from .pattern import Pattern, patternParameters
|
from .pattern import Pattern, patternParameters
|
||||||
from .gaincaps import Mythen3GainCapsWrapper
|
from .gaincaps import Mythen3GainCapsWrapper
|
||||||
|
from .PatternGenerator import PatternGenerator
|
||||||
|
|
||||||
import _slsdet
|
import _slsdet
|
||||||
xy = _slsdet.xy
|
xy = _slsdet.xy
|
||||||
|
31
python/slsdet/bits.py
Normal file
31
python/slsdet/bits.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
def setbit(bit, word):
|
||||||
|
if isinstance(word, np.generic):
|
||||||
|
mask = word.dtype.type(1)
|
||||||
|
mask = mask << bit
|
||||||
|
else:
|
||||||
|
mask = 1 << bit
|
||||||
|
return word | mask
|
||||||
|
|
||||||
|
|
||||||
|
def setbit_arr(bit, arr):
|
||||||
|
arr |= arr.dtype.type(1 << bit)
|
||||||
|
|
||||||
|
|
||||||
|
def clearbit(bit, word):
|
||||||
|
"""
|
||||||
|
Clear the bit at position bit in word.
|
||||||
|
Two paths to avoid converting the types.
|
||||||
|
"""
|
||||||
|
if isinstance(word, np.generic):
|
||||||
|
mask = word.dtype.type(1)
|
||||||
|
mask = ~(mask << bit)
|
||||||
|
else:
|
||||||
|
mask = ~(1 << bit)
|
||||||
|
return word & mask
|
||||||
|
|
||||||
|
|
||||||
|
def clearbit_arr(bit, arr):
|
||||||
|
arr &= arr.dtype.type(~(1 << bit))
|
@ -20,8 +20,10 @@ void init_pattern(py::module &m) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
py::class_<sls::Pattern> Pattern(m, "Pattern");
|
py::class_<sls::Pattern> Pattern(m, "Pattern");
|
||||||
Pattern.def(py::init());
|
Pattern.def(py::init())
|
||||||
Pattern.def("load", &sls::Pattern::load);
|
.def("load", &sls::Pattern::load)
|
||||||
Pattern.def("data", (pat * (sls::Pattern::*)()) & sls::Pattern::data,
|
.def("save", &sls::Pattern::save)
|
||||||
|
.def("str", &sls::Pattern::str)
|
||||||
|
.def("data", (pat * (sls::Pattern::*)()) & sls::Pattern::data,
|
||||||
py::return_value_policy::reference);
|
py::return_value_policy::reference);
|
||||||
}
|
}
|
||||||
|
152
python/tests/test_PatternGenerator.py
Normal file
152
python/tests/test_PatternGenerator.py
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
import pytest
|
||||||
|
from slsdet import PatternGenerator
|
||||||
|
|
||||||
|
|
||||||
|
def apply_detconf(p):
|
||||||
|
"""
|
||||||
|
Hacky workaround to apply detConf_mh02 to a pattern
|
||||||
|
"""
|
||||||
|
DACMON = 0
|
||||||
|
cnt_en_3 = 1
|
||||||
|
pulse_counter_en = 2
|
||||||
|
cnt_en_1 = 3
|
||||||
|
par_load = 4
|
||||||
|
pulse_mux_ctr = 5
|
||||||
|
reset_cnt = 6
|
||||||
|
reset_periphery = 7
|
||||||
|
config_load = 8
|
||||||
|
cnt_en_0 = 9
|
||||||
|
tbl = 10
|
||||||
|
clk_ext = 11
|
||||||
|
trimbit_load_reg = 12
|
||||||
|
store = 13
|
||||||
|
data_in = 14
|
||||||
|
en_pll_clk = 15
|
||||||
|
cnt_en_2 = 16
|
||||||
|
DACINT = 17
|
||||||
|
data_out_slow = 18 #IN
|
||||||
|
COMP2_MON = 19 #IN
|
||||||
|
start_read = 20
|
||||||
|
dac_store = 21
|
||||||
|
CNT3_MON = 22 #IN
|
||||||
|
EN_PIX_DIG_MON = 23
|
||||||
|
clk_sel = 24
|
||||||
|
BUSY = 25 #IN
|
||||||
|
COMP3_MON = 26 #IN
|
||||||
|
CNT2_MON = 27 #IN
|
||||||
|
|
||||||
|
dbit_ena=62 #FIFO LATCH
|
||||||
|
adc_ena=63 #ADC ENABLE
|
||||||
|
|
||||||
|
#FPGA input/ouutputs
|
||||||
|
p.setoutput(DACMON)
|
||||||
|
p.setoutput(cnt_en_3)
|
||||||
|
p.setoutput(pulse_counter_en)
|
||||||
|
p.setoutput(cnt_en_1)
|
||||||
|
p.setoutput(par_load)
|
||||||
|
p.setoutput(pulse_mux_ctr)
|
||||||
|
p.setoutput(reset_cnt)
|
||||||
|
p.setoutput(reset_periphery)
|
||||||
|
p.setoutput(cnt_en_0)
|
||||||
|
p.setoutput(tbl)
|
||||||
|
p.setoutput(clk_ext)
|
||||||
|
p.setoutput(config_load)
|
||||||
|
p.setoutput(trimbit_load_reg)
|
||||||
|
p.setoutput(store)
|
||||||
|
p.setoutput(data_in)
|
||||||
|
p.setoutput(en_pll_clk)
|
||||||
|
p.setoutput(cnt_en_2)
|
||||||
|
p.setoutput(DACINT)
|
||||||
|
p.setinput(data_out_slow)
|
||||||
|
p.setinput(COMP2_MON)
|
||||||
|
p.setoutput(start_read)
|
||||||
|
p.setoutput(dac_store)
|
||||||
|
p.setinput(CNT3_MON)
|
||||||
|
p.setoutput(EN_PIX_DIG_MON)
|
||||||
|
p.setoutput(clk_sel)
|
||||||
|
p.setinput(BUSY)
|
||||||
|
p.setinput(COMP3_MON)
|
||||||
|
p.setinput(CNT2_MON)
|
||||||
|
|
||||||
|
#system signals
|
||||||
|
p.setoutput(adc_ena)
|
||||||
|
# FIFO LATCH
|
||||||
|
p.setoutput(dbit_ena)
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_first_two_PW():
|
||||||
|
p = PatternGenerator()
|
||||||
|
|
||||||
|
#The pattern is created with a single empty word
|
||||||
|
assert p.pattern.limits[0] == 0
|
||||||
|
assert p.pattern.limits[1] == 0
|
||||||
|
|
||||||
|
p.SB(8)
|
||||||
|
p.PW()
|
||||||
|
|
||||||
|
#When doing the first PW the empty word is overwritten
|
||||||
|
assert p.pattern.limits[0] == 0
|
||||||
|
assert p.pattern.limits[1] == 0
|
||||||
|
assert p.pattern.word[0] == 256
|
||||||
|
|
||||||
|
p.SB(9)
|
||||||
|
p.PW()
|
||||||
|
|
||||||
|
#When doing the second PW we add a new word
|
||||||
|
assert p.pattern.limits[0] == 0
|
||||||
|
assert p.pattern.limits[1] == 1
|
||||||
|
assert p.pattern.word[0] == 256
|
||||||
|
assert p.pattern.word[1] == 768
|
||||||
|
|
||||||
|
def test_simple_pattern():
|
||||||
|
"""
|
||||||
|
Using enable pll pattern for MH02
|
||||||
|
"""
|
||||||
|
en_pll_clk = 15
|
||||||
|
p = PatternGenerator()
|
||||||
|
p = apply_detconf(p)
|
||||||
|
p.SB(en_pll_clk)
|
||||||
|
p.PW()
|
||||||
|
p.PW()
|
||||||
|
|
||||||
|
lines = str(p).split("\n")
|
||||||
|
|
||||||
|
enable_pll_pattern = [
|
||||||
|
"patword 0x0000 0x0000000000008000",
|
||||||
|
"patword 0x0001 0x0000000000008000",
|
||||||
|
"patioctrl 0xc000000001b3ffff",
|
||||||
|
"patlimits 0x0000 0x0001",
|
||||||
|
"patloop 0 0x1fff 0x1fff",
|
||||||
|
"patnloop 0 0",
|
||||||
|
"patloop 1 0x1fff 0x1fff",
|
||||||
|
"patnloop 1 0",
|
||||||
|
"patloop 2 0x1fff 0x1fff",
|
||||||
|
"patnloop 2 0",
|
||||||
|
"patloop 3 0x1fff 0x1fff",
|
||||||
|
"patnloop 3 0",
|
||||||
|
"patloop 4 0x1fff 0x1fff",
|
||||||
|
"patnloop 4 0",
|
||||||
|
"patloop 5 0x1fff 0x1fff",
|
||||||
|
"patnloop 5 0",
|
||||||
|
"patwait 0 0x1fff",
|
||||||
|
"patwaittime 0 0",
|
||||||
|
"patwait 1 0x1fff",
|
||||||
|
"patwaittime 1 0",
|
||||||
|
"patwait 2 0x1fff",
|
||||||
|
"patwaittime 2 0",
|
||||||
|
"patwait 3 0x1fff",
|
||||||
|
"patwaittime 3 0",
|
||||||
|
"patwait 4 0x1fff",
|
||||||
|
"patwaittime 4 0",
|
||||||
|
"patwait 5 0x1fff",
|
||||||
|
"patwaittime 5 0",
|
||||||
|
]
|
||||||
|
|
||||||
|
assert len(lines) == len(enable_pll_pattern)
|
||||||
|
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
assert line == enable_pll_pattern[i]
|
50
python/tests/test_bits.py
Normal file
50
python/tests/test_bits.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
from slsdet.bits import clearbit, clearbit_arr, setbit, setbit_arr
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
def test_clearbit_on_python_int():
|
||||||
|
val = 5 # 0b101
|
||||||
|
r = clearbit(0, val)
|
||||||
|
assert r == 4
|
||||||
|
assert val == 5
|
||||||
|
|
||||||
|
def test_setbit_on_python_int():
|
||||||
|
val = 5 # 0b101
|
||||||
|
r = setbit(1, val)
|
||||||
|
assert r == 7
|
||||||
|
assert val == 5
|
||||||
|
|
||||||
|
|
||||||
|
def test_setbit_doesnt_change_type():
|
||||||
|
word = np.int32(5)
|
||||||
|
ret = setbit(0, word)
|
||||||
|
assert isinstance(ret, np.int32)
|
||||||
|
|
||||||
|
|
||||||
|
def test_clearbit_doesnt_change_type():
|
||||||
|
word = np.uint8(5)
|
||||||
|
ret = clearbit(0, word)
|
||||||
|
assert isinstance(ret, np.uint8)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_setbit_on_array_element():
|
||||||
|
arr = np.zeros(10, dtype=np.uint64)
|
||||||
|
arr[5] = setbit(0, arr[5])
|
||||||
|
arr[5] = setbit(1, arr[5])
|
||||||
|
arr[5] = setbit(4, arr[5])
|
||||||
|
assert arr[4] == 0
|
||||||
|
assert arr[5] == 19 # 0b10011
|
||||||
|
assert arr[6] == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_setbit_arr():
|
||||||
|
arr = np.zeros(10, dtype=np.int32)
|
||||||
|
setbit_arr(3, arr[3:9])
|
||||||
|
assert all(arr == np.array((0, 0, 0, 8, 8, 8, 8, 8, 8, 0), dtype=np.int32))
|
||||||
|
|
||||||
|
|
||||||
|
def test_clearbit_arr():
|
||||||
|
arr = np.array((5, 5, 5), dtype=np.int8)
|
||||||
|
clearbit_arr(0, arr)
|
||||||
|
assert all(arr == (4, 4, 4))
|
@ -23,6 +23,7 @@ typedef struct __attribute__((packed)) {
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
class Pattern {
|
class Pattern {
|
||||||
patternParameters *pat = new patternParameters{};
|
patternParameters *pat = new patternParameters{};
|
||||||
|
std::ostream& stream(std::ostream &os) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Pattern();
|
Pattern();
|
||||||
@ -34,7 +35,7 @@ class Pattern {
|
|||||||
patternParameters *data() const;
|
patternParameters *data() const;
|
||||||
size_t size() const noexcept { return sizeof(patternParameters); }
|
size_t size() const noexcept { return sizeof(patternParameters); }
|
||||||
void validate() const;
|
void validate() const;
|
||||||
void load(const std::string &fname);
|
size_t load(const std::string &fname);
|
||||||
void save(const std::string &fname);
|
void save(const std::string &fname);
|
||||||
std::string str() const;
|
std::string str() const;
|
||||||
};
|
};
|
||||||
|
@ -93,7 +93,8 @@ void Pattern::validate() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pattern::load(const std::string &fname) {
|
size_t Pattern::load(const std::string &fname) {
|
||||||
|
size_t numPatWords = 0;
|
||||||
std::ifstream input_file(fname);
|
std::ifstream input_file(fname);
|
||||||
if (!input_file) {
|
if (!input_file) {
|
||||||
throw RuntimeError("Could not open pattern file " + fname +
|
throw RuntimeError("Could not open pattern file " + fname +
|
||||||
@ -125,6 +126,7 @@ void Pattern::load(const std::string &fname) {
|
|||||||
throw RuntimeError("Invalid address for " + ToString(args));
|
throw RuntimeError("Invalid address for " + ToString(args));
|
||||||
}
|
}
|
||||||
pat->word[addr] = StringTo<uint64_t>(args[2]);
|
pat->word[addr] = StringTo<uint64_t>(args[2]);
|
||||||
|
++numPatWords;
|
||||||
} else if (cmd == "patioctrl") {
|
} else if (cmd == "patioctrl") {
|
||||||
if (nargs != 1) {
|
if (nargs != 1) {
|
||||||
throw RuntimeError("Invalid arguments for " +
|
throw RuntimeError("Invalid arguments for " +
|
||||||
@ -238,6 +240,41 @@ void Pattern::load(const std::string &fname) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return numPatWords;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& Pattern::stream(std::ostream &os) const{
|
||||||
|
for (uint32_t i = pat->limits[0]; i <= pat->limits[1]; ++i) {
|
||||||
|
os << "patword " << ToStringHex(i, 4) << " "
|
||||||
|
<< ToStringHex(pat->word[i], 16) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// patioctrl
|
||||||
|
os << "patioctrl " << ToStringHex(pat->ioctrl, 16) << std::endl;
|
||||||
|
|
||||||
|
// patlimits
|
||||||
|
os << "patlimits " << ToStringHex(pat->limits[0], 4) << " "
|
||||||
|
<< ToStringHex(pat->limits[1], 4) << std::endl;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MAX_PATTERN_LEVELS; ++i) {
|
||||||
|
// patloop
|
||||||
|
os << "patloop " << i << " "
|
||||||
|
<< ToStringHex(pat->startloop[i], 4) << " "
|
||||||
|
<< ToStringHex(pat->stoploop[i], 4) << std::endl;
|
||||||
|
// patnloop
|
||||||
|
os << "patnloop " << i << " " << pat->nloop[i] << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MAX_PATTERN_LEVELS; ++i) {
|
||||||
|
// patwait
|
||||||
|
os << "patwait " << i << " " << ToStringHex(pat->wait[i], 4)
|
||||||
|
<< std::endl;
|
||||||
|
// patwaittime
|
||||||
|
os << "patwaittime " << i << " " << pat->waittime[i];
|
||||||
|
if (i<MAX_PATTERN_LEVELS-1)
|
||||||
|
os << std::endl;
|
||||||
|
}
|
||||||
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pattern::save(const std::string &fname) {
|
void Pattern::save(const std::string &fname) {
|
||||||
@ -246,65 +283,12 @@ void Pattern::save(const std::string &fname) {
|
|||||||
throw RuntimeError("Could not open pattern file " + fname +
|
throw RuntimeError("Could not open pattern file " + fname +
|
||||||
" for writing");
|
" for writing");
|
||||||
}
|
}
|
||||||
std::ostringstream os;
|
stream(output_file);
|
||||||
// pattern word
|
|
||||||
for (uint32_t i = pat->limits[0]; i <= pat->limits[1]; ++i) {
|
|
||||||
output_file << "patword " << ToStringHex(i, 4) << " "
|
|
||||||
<< ToStringHex(pat->word[i], 16) << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// patioctrl
|
|
||||||
output_file << "patioctrl " << ToStringHex(pat->ioctrl, 16) << std::endl;
|
|
||||||
|
|
||||||
// patlimits
|
|
||||||
output_file << "patlimits " << ToStringHex(pat->limits[0], 4) << " "
|
|
||||||
<< ToStringHex(pat->limits[1], 4) << std::endl;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < MAX_PATTERN_LEVELS; ++i) {
|
|
||||||
// patloop
|
|
||||||
output_file << "patloop " << i << " "
|
|
||||||
<< ToStringHex(pat->startloop[i], 4) << " "
|
|
||||||
<< ToStringHex(pat->stoploop[i], 4) << std::endl;
|
|
||||||
// patnloop
|
|
||||||
output_file << "patnloop " << i << " " << pat->nloop[i] << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < MAX_PATTERN_LEVELS; ++i) {
|
|
||||||
// patwait
|
|
||||||
output_file << "patwait " << i << " " << ToStringHex(pat->wait[i], 4)
|
|
||||||
<< std::endl;
|
|
||||||
// patwaittime
|
|
||||||
output_file << "patwaittime " << i << " " << pat->waittime[i]
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Pattern::str() const {
|
std::string Pattern::str() const {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << '[' << std::setfill('0') << std::endl;
|
stream(oss);
|
||||||
int addr_width = 4;
|
|
||||||
int word_width = 16;
|
|
||||||
for (int i = 0; i < MAX_PATTERN_LENGTH; ++i) {
|
|
||||||
if (pat->word[i] != 0) {
|
|
||||||
oss << "patword " << ToStringHex(i, addr_width) << " "
|
|
||||||
<< ToStringHex(pat->word[i], word_width) << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
oss << "patioctrl " << ToStringHex(pat->ioctrl, word_width) << std::endl
|
|
||||||
<< "patlimits " << ToStringHex(pat->limits[0], addr_width) << " "
|
|
||||||
<< ToStringHex(pat->limits[1], addr_width) << std::endl;
|
|
||||||
|
|
||||||
for (int i = 0; i != MAX_PATTERN_LEVELS; ++i) {
|
|
||||||
oss << "patloop " << i << ' '
|
|
||||||
<< ToStringHex(pat->startloop[i], addr_width) << " "
|
|
||||||
<< ToStringHex(pat->stoploop[i], addr_width) << std::endl
|
|
||||||
<< "patnloop " << pat->nloop[i] << std::endl
|
|
||||||
<< "patwait " << i << ' ' << ToStringHex(pat->wait[i], addr_width)
|
|
||||||
<< std::endl
|
|
||||||
<< "patwaittime " << i << ' ' << pat->waittime[i] << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
oss << ']';
|
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user