pyxcp 0.23.0__cp311-cp311-win_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyxcp might be problematic. Click here for more details.
- pyxcp/__init__.py +20 -0
- pyxcp/aml/EtasCANMonitoring.a2l +82 -0
- pyxcp/aml/EtasCANMonitoring.aml +67 -0
- pyxcp/aml/XCP_Common.aml +408 -0
- pyxcp/aml/XCPonCAN.aml +78 -0
- pyxcp/aml/XCPonEth.aml +33 -0
- pyxcp/aml/XCPonFlx.aml +113 -0
- pyxcp/aml/XCPonSxI.aml +66 -0
- pyxcp/aml/XCPonUSB.aml +106 -0
- pyxcp/aml/ifdata_CAN.a2l +20 -0
- pyxcp/aml/ifdata_Eth.a2l +11 -0
- pyxcp/aml/ifdata_Flx.a2l +94 -0
- pyxcp/aml/ifdata_SxI.a2l +13 -0
- pyxcp/aml/ifdata_USB.a2l +81 -0
- pyxcp/asam/__init__.py +0 -0
- pyxcp/asam/types.py +131 -0
- pyxcp/asamkeydll.c +116 -0
- pyxcp/asamkeydll.sh +2 -0
- pyxcp/checksum.py +732 -0
- pyxcp/cmdline.py +52 -0
- pyxcp/config/__init__.py +1113 -0
- pyxcp/config/legacy.py +120 -0
- pyxcp/constants.py +47 -0
- pyxcp/cpp_ext/__init__.py +0 -0
- pyxcp/cpp_ext/bin.hpp +104 -0
- pyxcp/cpp_ext/blockmem.hpp +58 -0
- pyxcp/cpp_ext/cpp_ext.cp310-win_arm64.pyd +0 -0
- pyxcp/cpp_ext/cpp_ext.cp311-win_arm64.pyd +0 -0
- pyxcp/cpp_ext/daqlist.hpp +206 -0
- pyxcp/cpp_ext/event.hpp +67 -0
- pyxcp/cpp_ext/extension_wrapper.cpp +100 -0
- pyxcp/cpp_ext/helper.hpp +280 -0
- pyxcp/cpp_ext/mcobject.hpp +246 -0
- pyxcp/cpp_ext/tsqueue.hpp +46 -0
- pyxcp/daq_stim/__init__.py +232 -0
- pyxcp/daq_stim/optimize/__init__.py +67 -0
- pyxcp/daq_stim/optimize/binpacking.py +41 -0
- pyxcp/daq_stim/scheduler.cpp +62 -0
- pyxcp/daq_stim/scheduler.hpp +75 -0
- pyxcp/daq_stim/stim.cp310-win_arm64.pyd +0 -0
- pyxcp/daq_stim/stim.cp311-win_arm64.pyd +0 -0
- pyxcp/daq_stim/stim.cpp +13 -0
- pyxcp/daq_stim/stim.hpp +604 -0
- pyxcp/daq_stim/stim_wrapper.cpp +50 -0
- pyxcp/dllif.py +100 -0
- pyxcp/errormatrix.py +878 -0
- pyxcp/examples/conf_can.toml +19 -0
- pyxcp/examples/conf_can_user.toml +16 -0
- pyxcp/examples/conf_can_vector.json +11 -0
- pyxcp/examples/conf_can_vector.toml +11 -0
- pyxcp/examples/conf_eth.toml +9 -0
- pyxcp/examples/conf_nixnet.json +20 -0
- pyxcp/examples/conf_socket_can.toml +12 -0
- pyxcp/examples/conf_sxi.json +9 -0
- pyxcp/examples/conf_sxi.toml +7 -0
- pyxcp/examples/run_daq.py +163 -0
- pyxcp/examples/xcp_policy.py +60 -0
- pyxcp/examples/xcp_read_benchmark.py +38 -0
- pyxcp/examples/xcp_skel.py +49 -0
- pyxcp/examples/xcp_unlock.py +38 -0
- pyxcp/examples/xcp_user_supplied_driver.py +44 -0
- pyxcp/examples/xcphello.py +78 -0
- pyxcp/examples/xcphello_recorder.py +107 -0
- pyxcp/master/__init__.py +9 -0
- pyxcp/master/errorhandler.py +442 -0
- pyxcp/master/master.py +2047 -0
- pyxcp/py.typed +0 -0
- pyxcp/recorder/__init__.py +101 -0
- pyxcp/recorder/build_clang.cmd +1 -0
- pyxcp/recorder/build_clang.sh +2 -0
- pyxcp/recorder/build_gcc.cmd +1 -0
- pyxcp/recorder/build_gcc.sh +2 -0
- pyxcp/recorder/build_gcc_arm.sh +2 -0
- pyxcp/recorder/converter/__init__.py +450 -0
- pyxcp/recorder/lz4.c +2829 -0
- pyxcp/recorder/lz4.h +879 -0
- pyxcp/recorder/lz4hc.c +2041 -0
- pyxcp/recorder/lz4hc.h +413 -0
- pyxcp/recorder/mio.hpp +1714 -0
- pyxcp/recorder/reader.hpp +139 -0
- pyxcp/recorder/reco.py +277 -0
- pyxcp/recorder/recorder.rst +0 -0
- pyxcp/recorder/rekorder.cp310-win_arm64.pyd +0 -0
- pyxcp/recorder/rekorder.cp311-win_arm64.pyd +0 -0
- pyxcp/recorder/rekorder.cpp +59 -0
- pyxcp/recorder/rekorder.hpp +274 -0
- pyxcp/recorder/setup.py +41 -0
- pyxcp/recorder/test_reko.py +34 -0
- pyxcp/recorder/unfolder.hpp +1332 -0
- pyxcp/recorder/wrap.cpp +189 -0
- pyxcp/recorder/writer.hpp +302 -0
- pyxcp/scripts/__init__.py +0 -0
- pyxcp/scripts/pyxcp_probe_can_drivers.py +20 -0
- pyxcp/scripts/xcp_examples.py +64 -0
- pyxcp/scripts/xcp_fetch_a2l.py +40 -0
- pyxcp/scripts/xcp_id_scanner.py +19 -0
- pyxcp/scripts/xcp_info.py +144 -0
- pyxcp/scripts/xcp_profile.py +27 -0
- pyxcp/scripts/xmraw_converter.py +31 -0
- pyxcp/stim/__init__.py +0 -0
- pyxcp/tests/test_asam_types.py +24 -0
- pyxcp/tests/test_binpacking.py +186 -0
- pyxcp/tests/test_can.py +1324 -0
- pyxcp/tests/test_checksum.py +95 -0
- pyxcp/tests/test_daq.py +193 -0
- pyxcp/tests/test_daq_opt.py +426 -0
- pyxcp/tests/test_frame_padding.py +156 -0
- pyxcp/tests/test_master.py +2006 -0
- pyxcp/tests/test_transport.py +81 -0
- pyxcp/tests/test_utils.py +30 -0
- pyxcp/timing.py +60 -0
- pyxcp/transport/__init__.py +10 -0
- pyxcp/transport/base.py +440 -0
- pyxcp/transport/base_transport.hpp +0 -0
- pyxcp/transport/can.py +556 -0
- pyxcp/transport/eth.py +219 -0
- pyxcp/transport/sxi.py +135 -0
- pyxcp/transport/transport_wrapper.cpp +0 -0
- pyxcp/transport/usb_transport.py +213 -0
- pyxcp/types.py +1000 -0
- pyxcp/utils.py +128 -0
- pyxcp/vector/__init__.py +0 -0
- pyxcp/vector/map.py +82 -0
- pyxcp-0.23.0.dist-info/LICENSE +165 -0
- pyxcp-0.23.0.dist-info/METADATA +107 -0
- pyxcp-0.23.0.dist-info/RECORD +128 -0
- pyxcp-0.23.0.dist-info/WHEEL +4 -0
- pyxcp-0.23.0.dist-info/entry_points.txt +9 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
# from pprint import pprint
|
|
4
|
+
from time import time_ns
|
|
5
|
+
from typing import Dict, List, Optional, TextIO
|
|
6
|
+
|
|
7
|
+
from pyxcp import types
|
|
8
|
+
from pyxcp.config import get_application
|
|
9
|
+
from pyxcp.cpp_ext.cpp_ext import DaqList
|
|
10
|
+
from pyxcp.daq_stim.optimize import make_continuous_blocks
|
|
11
|
+
from pyxcp.daq_stim.optimize.binpacking import first_fit_decreasing
|
|
12
|
+
from pyxcp.recorder import DaqOnlinePolicy as _DaqOnlinePolicy
|
|
13
|
+
from pyxcp.recorder import DaqRecorderPolicy as _DaqRecorderPolicy
|
|
14
|
+
from pyxcp.recorder import MeasurementParameters
|
|
15
|
+
from pyxcp.utils import CurrentDatetime
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
DAQ_ID_FIELD_SIZE = {
|
|
19
|
+
"IDF_ABS_ODT_NUMBER": 1,
|
|
20
|
+
"IDF_REL_ODT_NUMBER_ABS_DAQ_LIST_NUMBER_BYTE": 2,
|
|
21
|
+
"IDF_REL_ODT_NUMBER_ABS_DAQ_LIST_NUMBER_WORD": 3,
|
|
22
|
+
"IDF_REL_ODT_NUMBER_ABS_DAQ_LIST_NUMBER_WORD_ALIGNED": 4,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
DAQ_TIMESTAMP_SIZE = {
|
|
26
|
+
"S1": 1,
|
|
27
|
+
"S2": 2,
|
|
28
|
+
"S4": 4,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class DaqProcessor:
|
|
33
|
+
def __init__(self, daq_lists: List[DaqList]):
|
|
34
|
+
# super().__init__()
|
|
35
|
+
self.daq_lists = daq_lists
|
|
36
|
+
self.log = get_application().log
|
|
37
|
+
|
|
38
|
+
def setup(self, start_datetime: Optional[CurrentDatetime] = None, write_multiple: bool = True):
|
|
39
|
+
if not self.xcp_master.slaveProperties.supportsDaq:
|
|
40
|
+
raise RuntimeError("DAQ functionality is not supported.")
|
|
41
|
+
self.daq_info = self.xcp_master.getDaqInfo(include_event_lists=False)
|
|
42
|
+
if start_datetime is None:
|
|
43
|
+
start_datetime = CurrentDatetime(time_ns())
|
|
44
|
+
self.start_datetime = start_datetime
|
|
45
|
+
# print(self.start_datetime)
|
|
46
|
+
try:
|
|
47
|
+
processor = self.daq_info.get("processor")
|
|
48
|
+
properties = processor.get("properties")
|
|
49
|
+
resolution = self.daq_info.get("resolution")
|
|
50
|
+
if properties["configType"] == "STATIC":
|
|
51
|
+
raise TypeError("DAQ configuration is static, cannot proceed.")
|
|
52
|
+
self.supports_timestampes = properties["timestampSupported"]
|
|
53
|
+
self.supports_prescaler = properties["prescalerSupported"]
|
|
54
|
+
self.supports_pid_off = properties["pidOffSupported"]
|
|
55
|
+
if self.supports_timestampes:
|
|
56
|
+
mode = resolution.get("timestampMode")
|
|
57
|
+
self.ts_fixed = mode.get("fixed")
|
|
58
|
+
self.ts_size = DAQ_TIMESTAMP_SIZE[mode.get("size")]
|
|
59
|
+
ts_factor = types.DAQ_TIMESTAMP_UNIT_TO_NS[mode.get("unit")]
|
|
60
|
+
ts_ticks = resolution.get("timestampTicks")
|
|
61
|
+
self.ts_scale_factor = ts_factor * ts_ticks
|
|
62
|
+
else:
|
|
63
|
+
self.ts_size = 0
|
|
64
|
+
self.ts_fixed = False
|
|
65
|
+
self.ts_scale_factor = 0.0
|
|
66
|
+
key_byte = processor.get("keyByte")
|
|
67
|
+
header_len = DAQ_ID_FIELD_SIZE[key_byte["identificationField"]]
|
|
68
|
+
max_dto = self.xcp_master.slaveProperties.maxDto
|
|
69
|
+
self.min_daq = processor.get("minDaq")
|
|
70
|
+
max_odt_entry_size = resolution.get("maxOdtEntrySizeDaq")
|
|
71
|
+
max_payload_size = min(max_odt_entry_size, max_dto - header_len)
|
|
72
|
+
# First ODT may contain timestamp.
|
|
73
|
+
self.selectable_timestamps = False
|
|
74
|
+
if not self.supports_timestampes:
|
|
75
|
+
max_payload_size_first = max_payload_size
|
|
76
|
+
# print("NO TIMESTAMP SUPPORT")
|
|
77
|
+
else:
|
|
78
|
+
if self.ts_fixed:
|
|
79
|
+
# print("Fixed timestamp")
|
|
80
|
+
max_payload_size_first = max_payload_size - self.ts_size
|
|
81
|
+
else:
|
|
82
|
+
# print("timestamp variable.")
|
|
83
|
+
self.selectable_timestamps = True
|
|
84
|
+
|
|
85
|
+
except Exception as e:
|
|
86
|
+
raise TypeError(f"DAQ_INFO corrupted: {e}") from e
|
|
87
|
+
|
|
88
|
+
# DAQ optimization.
|
|
89
|
+
for daq_list in self.daq_lists:
|
|
90
|
+
if self.selectable_timestamps:
|
|
91
|
+
if daq_list.enable_timestamps:
|
|
92
|
+
max_payload_size_first = max_payload_size - self.ts_size
|
|
93
|
+
else:
|
|
94
|
+
max_payload_size_first = max_payload_size
|
|
95
|
+
ttt = make_continuous_blocks(daq_list.measurements, max_payload_size, max_payload_size_first)
|
|
96
|
+
daq_list.measurements_opt = first_fit_decreasing(ttt, max_payload_size, max_payload_size_first)
|
|
97
|
+
byte_order = 0 if self.xcp_master.slaveProperties.byteOrder == "INTEL" else 1
|
|
98
|
+
self._first_pids = []
|
|
99
|
+
daq_count = len(self.daq_lists)
|
|
100
|
+
self.xcp_master.freeDaq()
|
|
101
|
+
|
|
102
|
+
# Allocate
|
|
103
|
+
self.xcp_master.allocDaq(daq_count)
|
|
104
|
+
measurement_list = []
|
|
105
|
+
for i, daq_list in enumerate(self.daq_lists, self.min_daq):
|
|
106
|
+
measurements = daq_list.measurements_opt
|
|
107
|
+
measurement_list.append((i, measurements))
|
|
108
|
+
odt_count = len(measurements)
|
|
109
|
+
self.xcp_master.allocOdt(i, odt_count)
|
|
110
|
+
# Iterate again over ODT entries -- we need to respect sequencing requirements.
|
|
111
|
+
for i, measurements in measurement_list:
|
|
112
|
+
for j, measurement in enumerate(measurements):
|
|
113
|
+
entry_count = len(measurement.entries)
|
|
114
|
+
self.xcp_master.allocOdtEntry(i, j, entry_count)
|
|
115
|
+
# Write DAQs
|
|
116
|
+
for i, daq_list in enumerate(self.daq_lists, self.min_daq):
|
|
117
|
+
measurements = daq_list.measurements_opt
|
|
118
|
+
for j, measurement in enumerate(measurements):
|
|
119
|
+
if len(measurement.entries) == 0:
|
|
120
|
+
continue # CAN special case: No room for data in first ODT.
|
|
121
|
+
self.xcp_master.setDaqPtr(i, j, 0)
|
|
122
|
+
for entry in measurement.entries:
|
|
123
|
+
self.xcp_master.writeDaq(0xFF, entry.length, entry.ext, entry.address)
|
|
124
|
+
|
|
125
|
+
# arm DAQ lists -- this is technically a function on its own.
|
|
126
|
+
for i, daq_list in enumerate(self.daq_lists, self.min_daq):
|
|
127
|
+
# print(daq_list.name, daq_list.event_num, daq_list.stim)
|
|
128
|
+
mode = 0x00
|
|
129
|
+
if self.supports_timestampes and (self.ts_fixed or (self.selectable_timestamps and daq_list.enable_timestamps)):
|
|
130
|
+
mode = 0x10
|
|
131
|
+
if daq_list.stim:
|
|
132
|
+
mode |= 0x02
|
|
133
|
+
###
|
|
134
|
+
## mode |= 0x20
|
|
135
|
+
###
|
|
136
|
+
self.xcp_master.setDaqListMode(
|
|
137
|
+
daq_list_number=i,
|
|
138
|
+
mode=mode,
|
|
139
|
+
event_channel_number=daq_list.event_num,
|
|
140
|
+
prescaler=daq_list.prescaler,
|
|
141
|
+
priority=daq_list.priority,
|
|
142
|
+
)
|
|
143
|
+
res = self.xcp_master.startStopDaqList(0x02, i)
|
|
144
|
+
self._first_pids.append(res.firstPid)
|
|
145
|
+
if start_datetime:
|
|
146
|
+
pass
|
|
147
|
+
self.measurement_params = MeasurementParameters(
|
|
148
|
+
byte_order,
|
|
149
|
+
header_len,
|
|
150
|
+
self.supports_timestampes,
|
|
151
|
+
self.ts_fixed,
|
|
152
|
+
self.supports_prescaler,
|
|
153
|
+
self.selectable_timestamps,
|
|
154
|
+
self.ts_scale_factor,
|
|
155
|
+
self.ts_size,
|
|
156
|
+
self.min_daq,
|
|
157
|
+
self.start_datetime,
|
|
158
|
+
self.daq_lists,
|
|
159
|
+
self._first_pids,
|
|
160
|
+
)
|
|
161
|
+
self.set_parameters(self.measurement_params)
|
|
162
|
+
|
|
163
|
+
def start(self):
|
|
164
|
+
self.xcp_master.startStopSynch(0x01)
|
|
165
|
+
|
|
166
|
+
def stop(self):
|
|
167
|
+
self.xcp_master.startStopSynch(0x00)
|
|
168
|
+
|
|
169
|
+
def first_pids(self):
|
|
170
|
+
return self._first_pids
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class DaqRecorder(DaqProcessor, _DaqRecorderPolicy):
|
|
174
|
+
|
|
175
|
+
def __init__(self, daq_lists: List[DaqList], file_name: str, prealloc: int = 200, chunk_size: int = 1):
|
|
176
|
+
DaqProcessor.__init__(self, daq_lists)
|
|
177
|
+
_DaqRecorderPolicy.__init__(self)
|
|
178
|
+
self.file_name = file_name
|
|
179
|
+
self.prealloc = prealloc
|
|
180
|
+
self.chunk_size = chunk_size
|
|
181
|
+
|
|
182
|
+
def initialize(self):
|
|
183
|
+
metadata = self.measurement_params.dumps()
|
|
184
|
+
_DaqRecorderPolicy.create_writer(self, self.file_name, self.prealloc, self.chunk_size, metadata)
|
|
185
|
+
_DaqRecorderPolicy.initialize(self)
|
|
186
|
+
|
|
187
|
+
def finalize(self):
|
|
188
|
+
_DaqRecorderPolicy.finalize(self)
|
|
189
|
+
|
|
190
|
+
def start(self):
|
|
191
|
+
DaqProcessor.start(self)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class DaqOnlinePolicy(DaqProcessor, _DaqOnlinePolicy):
|
|
195
|
+
"""Base class for on-line measurements.
|
|
196
|
+
Handles multiple inheritence.
|
|
197
|
+
"""
|
|
198
|
+
|
|
199
|
+
def __init__(self, daq_lists: List[DaqList]):
|
|
200
|
+
DaqProcessor.__init__(self, daq_lists)
|
|
201
|
+
_DaqOnlinePolicy.__init__(self)
|
|
202
|
+
|
|
203
|
+
def start(self):
|
|
204
|
+
DaqProcessor.start(self)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class DaqToCsv(DaqOnlinePolicy):
|
|
208
|
+
"""Save a measurement as CSV files (one per DAQ-list)."""
|
|
209
|
+
|
|
210
|
+
def initialize(self):
|
|
211
|
+
self.log.debug("DaqCsv::Initialize()")
|
|
212
|
+
self.files: Dict[int, TextIO] = {}
|
|
213
|
+
for num, daq_list in enumerate(self.daq_lists):
|
|
214
|
+
if daq_list.stim:
|
|
215
|
+
continue
|
|
216
|
+
out_file = open(f"{daq_list.name}.csv", "w")
|
|
217
|
+
self.files[num] = out_file
|
|
218
|
+
hdr = ",".join(["timestamp0", "timestamp1"] + [h[0] for h in daq_list.headers])
|
|
219
|
+
out_file.write(f"{hdr}\n")
|
|
220
|
+
|
|
221
|
+
def on_daq_list(self, daq_list: int, timestamp0: int, timestamp1: int, payload: list):
|
|
222
|
+
self.files[daq_list].write(f"{timestamp0},{timestamp1},{', '.join([str(x) for x in payload])}\n")
|
|
223
|
+
|
|
224
|
+
def finalize(self):
|
|
225
|
+
self.log.debug("DaqCsv::finalize()")
|
|
226
|
+
##
|
|
227
|
+
## NOTE: `finalize` is guaranteed to be called, but `Initialize` may fail for reasons.
|
|
228
|
+
## So if you allocate resources in `Initialize` check if this really happened.
|
|
229
|
+
##
|
|
230
|
+
if hasattr(self, "files"):
|
|
231
|
+
for f in self.files.values():
|
|
232
|
+
f.close()
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Optimize data-structures like memory sections."""
|
|
3
|
+
|
|
4
|
+
from itertools import groupby
|
|
5
|
+
from operator import attrgetter
|
|
6
|
+
from typing import List
|
|
7
|
+
|
|
8
|
+
from pyxcp.cpp_ext.cpp_ext import McObject
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def make_continuous_blocks(chunks: List[McObject], upper_bound=None, upper_bound_initial=None) -> List[McObject]:
|
|
12
|
+
"""Try to make continous blocks from a list of small, unordered `chunks`.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
chunks: list of `McObject`
|
|
17
|
+
|
|
18
|
+
Returns
|
|
19
|
+
-------
|
|
20
|
+
sorted list of `McObject`
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def key_func(x):
|
|
24
|
+
return (x.ext, x.address)
|
|
25
|
+
|
|
26
|
+
values = []
|
|
27
|
+
# 1. Groupy by address.
|
|
28
|
+
for _key, value in groupby(sorted(chunks, key=key_func), key=key_func):
|
|
29
|
+
# 2. Pick the largest one.
|
|
30
|
+
values.append(max(value, key=attrgetter("length")))
|
|
31
|
+
result_sections = []
|
|
32
|
+
last_section = None
|
|
33
|
+
last_ext = None
|
|
34
|
+
first_section = True
|
|
35
|
+
if upper_bound_initial is None:
|
|
36
|
+
upper_bound_initial = upper_bound
|
|
37
|
+
while values:
|
|
38
|
+
section = values.pop(0)
|
|
39
|
+
if (last_section and section.address <= last_section.address + last_section.length) and not (section.ext != last_ext):
|
|
40
|
+
last_end = last_section.address + last_section.length - 1
|
|
41
|
+
current_end = section.address + section.length - 1
|
|
42
|
+
if last_end > section.address:
|
|
43
|
+
pass
|
|
44
|
+
else:
|
|
45
|
+
offset = current_end - last_end
|
|
46
|
+
if upper_bound:
|
|
47
|
+
if first_section:
|
|
48
|
+
upper_bound = upper_bound_initial
|
|
49
|
+
first_section = False
|
|
50
|
+
if last_section.length + offset <= upper_bound:
|
|
51
|
+
last_section.length += offset
|
|
52
|
+
last_section.add_component(section)
|
|
53
|
+
else:
|
|
54
|
+
result_sections.append(
|
|
55
|
+
McObject(name="", address=section.address, ext=section.ext, length=section.length, components=[section])
|
|
56
|
+
)
|
|
57
|
+
else:
|
|
58
|
+
last_section.length += offset
|
|
59
|
+
last_section.add_component(section)
|
|
60
|
+
else:
|
|
61
|
+
# Create a new section.
|
|
62
|
+
result_sections.append(
|
|
63
|
+
McObject(name="", address=section.address, ext=section.ext, length=section.length, components=[section])
|
|
64
|
+
)
|
|
65
|
+
last_section = result_sections[-1]
|
|
66
|
+
last_ext = last_section.ext
|
|
67
|
+
return result_sections
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Bin-packing algorithms.
|
|
3
|
+
"""
|
|
4
|
+
from typing import List, Optional
|
|
5
|
+
|
|
6
|
+
from pyxcp.cpp_ext.cpp_ext import Bin
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def first_fit_decreasing(items, bin_size: int, initial_bin_size: Optional[int] = None) -> List[Bin]:
|
|
10
|
+
"""bin-packing with first-fit-decreasing algorithm.
|
|
11
|
+
|
|
12
|
+
Parameters
|
|
13
|
+
----------
|
|
14
|
+
items: list
|
|
15
|
+
items that need to be stored/allocated.
|
|
16
|
+
|
|
17
|
+
bin_size: int
|
|
18
|
+
|
|
19
|
+
Returns
|
|
20
|
+
-------
|
|
21
|
+
list
|
|
22
|
+
Resulting bins
|
|
23
|
+
"""
|
|
24
|
+
if initial_bin_size is None:
|
|
25
|
+
initial_bin_size = bin_size
|
|
26
|
+
# bin_size = max(bin_size, initial_bin_size)
|
|
27
|
+
bins = [Bin(size=initial_bin_size)] # Initial bin
|
|
28
|
+
for item in sorted(items, key=lambda x: x.length, reverse=True):
|
|
29
|
+
if item.length > bin_size:
|
|
30
|
+
raise ValueError(f"Item {item!r} is too large to fit in a {bin_size} byte sized bin.")
|
|
31
|
+
for bin in bins:
|
|
32
|
+
if bin.residual_capacity >= item.length:
|
|
33
|
+
bin.append(item)
|
|
34
|
+
bin.residual_capacity -= item.length
|
|
35
|
+
break
|
|
36
|
+
else:
|
|
37
|
+
new_bin = Bin(size=bin_size)
|
|
38
|
+
bins.append(new_bin)
|
|
39
|
+
new_bin.append(item)
|
|
40
|
+
new_bin.residual_capacity -= item.length
|
|
41
|
+
return bins
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#include "scheduler.hpp"
|
|
2
|
+
|
|
3
|
+
#if defined(_WIN32)
|
|
4
|
+
|
|
5
|
+
#include <cstdio>
|
|
6
|
+
#include <cstdint>
|
|
7
|
+
|
|
8
|
+
VOID CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired) {
|
|
9
|
+
if (lpParam == nullptr) {
|
|
10
|
+
std::printf("TimerRoutine lpParam is NULL\n");
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const auto* param = static_cast<const int*>(lpParam);
|
|
15
|
+
std::printf("Timer routine called. Parameter is %d.\n", *param);
|
|
16
|
+
|
|
17
|
+
if (TimerOrWaitFired) {
|
|
18
|
+
std::printf("The wait timed out.\n");
|
|
19
|
+
} else {
|
|
20
|
+
std::printf("The wait event was signaled.\n");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#endif // _WIN32
|
|
25
|
+
|
|
26
|
+
// Vectorized multiply implementation with bounds checking
|
|
27
|
+
namespace {
|
|
28
|
+
constexpr size_t VECTOR_SIZE = 4;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
#if defined(_M_X64) || defined(_M_IX86) || defined(__SSE__)
|
|
32
|
+
#include <xmmintrin.h>
|
|
33
|
+
|
|
34
|
+
void mul4_vectorized(float* ptr) {
|
|
35
|
+
if (ptr == nullptr) return;
|
|
36
|
+
|
|
37
|
+
__m128 f = _mm_loadu_ps(ptr);
|
|
38
|
+
f = _mm_mul_ps(f, f);
|
|
39
|
+
_mm_storeu_ps(ptr, f);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
#elif defined(_M_ARM64) || defined(__ARM_NEON)
|
|
43
|
+
#include <arm_neon.h>
|
|
44
|
+
|
|
45
|
+
void mul4_vectorized(float* ptr) {
|
|
46
|
+
if (ptr == nullptr) return;
|
|
47
|
+
|
|
48
|
+
float32x4_t f = vld1q_f32(ptr);
|
|
49
|
+
f = vmulq_f32(f, f);
|
|
50
|
+
vst1q_f32(ptr, f);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
#else
|
|
54
|
+
// Scalar fallback
|
|
55
|
+
void mul4_vectorized(float* ptr) {
|
|
56
|
+
if (ptr == nullptr) return;
|
|
57
|
+
|
|
58
|
+
for (size_t i = 0; i < VECTOR_SIZE; ++i) {
|
|
59
|
+
ptr[i] *= ptr[i];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
#endif
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
#ifndef STIM_SCHEDULER_HPP
|
|
4
|
+
#define STIM_SCHEDULER_HPP
|
|
5
|
+
|
|
6
|
+
#if !defined(_CRT_SECURE_NO_WARNINGS)
|
|
7
|
+
#define _CRT_SECURE_NO_WARNINGS (1)
|
|
8
|
+
#endif
|
|
9
|
+
|
|
10
|
+
#include <stdio.h>
|
|
11
|
+
|
|
12
|
+
#if defined(_WIN32)
|
|
13
|
+
#include <windows.h>
|
|
14
|
+
|
|
15
|
+
#include <thread>
|
|
16
|
+
|
|
17
|
+
VOID CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired);
|
|
18
|
+
|
|
19
|
+
struct Scheduler {
|
|
20
|
+
Scheduler() = default;
|
|
21
|
+
~Scheduler() = default;
|
|
22
|
+
|
|
23
|
+
bool start_thread() noexcept {
|
|
24
|
+
if (timer_thread.joinable()) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
m_TimerQueue = CreateTimerQueue();
|
|
29
|
+
if (NULL == m_TimerQueue) {
|
|
30
|
+
printf("CreateTimerQueue failed (%d)\n", GetLastError());
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Set a timer to call the timer routine in 10 seconds.
|
|
35
|
+
if (!CreateTimerQueueTimer(&m_timer, m_TimerQueue, (WAITORTIMERCALLBACK)TimerRoutine, nullptr, 1, 500, 0)) {
|
|
36
|
+
printf("CreateTimerQueueTimer failed (%d)\n", GetLastError());
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
stop_timer_thread_flag = false;
|
|
41
|
+
timer_thread = std::jthread([this]() {
|
|
42
|
+
while (!stop_timer_thread_flag) {
|
|
43
|
+
printf("ENTER SLEEP loop!!!\n");
|
|
44
|
+
SleepEx(INFINITE, TRUE);
|
|
45
|
+
stop_timer_thread_flag = TRUE;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
bool stop_thread() noexcept {
|
|
52
|
+
if (!timer_thread.joinable()) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
stop_timer_thread_flag = true;
|
|
56
|
+
// my_queue.put(std::nullopt);
|
|
57
|
+
timer_thread.join();
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
std::jthread timer_thread{};
|
|
62
|
+
bool stop_timer_thread_flag{};
|
|
63
|
+
HANDLE m_timer{};
|
|
64
|
+
HANDLE m_TimerQueue;
|
|
65
|
+
};
|
|
66
|
+
#else
|
|
67
|
+
|
|
68
|
+
struct Scheduler {
|
|
69
|
+
Scheduler() = default;
|
|
70
|
+
~Scheduler() = default;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
#endif
|
|
74
|
+
|
|
75
|
+
#endif // STIM_SCHEDULER_HPP
|
|
Binary file
|
|
Binary file
|