pyxcp 0.23.0__cp312-cp312-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.

Files changed (131) hide show
  1. pyxcp/__init__.py +20 -0
  2. pyxcp/aml/EtasCANMonitoring.a2l +82 -0
  3. pyxcp/aml/EtasCANMonitoring.aml +67 -0
  4. pyxcp/aml/XCP_Common.aml +408 -0
  5. pyxcp/aml/XCPonCAN.aml +78 -0
  6. pyxcp/aml/XCPonEth.aml +33 -0
  7. pyxcp/aml/XCPonFlx.aml +113 -0
  8. pyxcp/aml/XCPonSxI.aml +66 -0
  9. pyxcp/aml/XCPonUSB.aml +106 -0
  10. pyxcp/aml/ifdata_CAN.a2l +20 -0
  11. pyxcp/aml/ifdata_Eth.a2l +11 -0
  12. pyxcp/aml/ifdata_Flx.a2l +94 -0
  13. pyxcp/aml/ifdata_SxI.a2l +13 -0
  14. pyxcp/aml/ifdata_USB.a2l +81 -0
  15. pyxcp/asam/__init__.py +0 -0
  16. pyxcp/asam/types.py +131 -0
  17. pyxcp/asamkeydll.c +116 -0
  18. pyxcp/asamkeydll.sh +2 -0
  19. pyxcp/checksum.py +732 -0
  20. pyxcp/cmdline.py +52 -0
  21. pyxcp/config/__init__.py +1113 -0
  22. pyxcp/config/legacy.py +120 -0
  23. pyxcp/constants.py +47 -0
  24. pyxcp/cpp_ext/__init__.py +0 -0
  25. pyxcp/cpp_ext/bin.hpp +104 -0
  26. pyxcp/cpp_ext/blockmem.hpp +58 -0
  27. pyxcp/cpp_ext/cpp_ext.cp310-win_arm64.pyd +0 -0
  28. pyxcp/cpp_ext/cpp_ext.cp311-win_arm64.pyd +0 -0
  29. pyxcp/cpp_ext/cpp_ext.cp312-win_arm64.pyd +0 -0
  30. pyxcp/cpp_ext/daqlist.hpp +206 -0
  31. pyxcp/cpp_ext/event.hpp +67 -0
  32. pyxcp/cpp_ext/extension_wrapper.cpp +100 -0
  33. pyxcp/cpp_ext/helper.hpp +280 -0
  34. pyxcp/cpp_ext/mcobject.hpp +246 -0
  35. pyxcp/cpp_ext/tsqueue.hpp +46 -0
  36. pyxcp/daq_stim/__init__.py +232 -0
  37. pyxcp/daq_stim/optimize/__init__.py +67 -0
  38. pyxcp/daq_stim/optimize/binpacking.py +41 -0
  39. pyxcp/daq_stim/scheduler.cpp +62 -0
  40. pyxcp/daq_stim/scheduler.hpp +75 -0
  41. pyxcp/daq_stim/stim.cp310-win_arm64.pyd +0 -0
  42. pyxcp/daq_stim/stim.cp311-win_arm64.pyd +0 -0
  43. pyxcp/daq_stim/stim.cp312-win_arm64.pyd +0 -0
  44. pyxcp/daq_stim/stim.cpp +13 -0
  45. pyxcp/daq_stim/stim.hpp +604 -0
  46. pyxcp/daq_stim/stim_wrapper.cpp +50 -0
  47. pyxcp/dllif.py +100 -0
  48. pyxcp/errormatrix.py +878 -0
  49. pyxcp/examples/conf_can.toml +19 -0
  50. pyxcp/examples/conf_can_user.toml +16 -0
  51. pyxcp/examples/conf_can_vector.json +11 -0
  52. pyxcp/examples/conf_can_vector.toml +11 -0
  53. pyxcp/examples/conf_eth.toml +9 -0
  54. pyxcp/examples/conf_nixnet.json +20 -0
  55. pyxcp/examples/conf_socket_can.toml +12 -0
  56. pyxcp/examples/conf_sxi.json +9 -0
  57. pyxcp/examples/conf_sxi.toml +7 -0
  58. pyxcp/examples/run_daq.py +163 -0
  59. pyxcp/examples/xcp_policy.py +60 -0
  60. pyxcp/examples/xcp_read_benchmark.py +38 -0
  61. pyxcp/examples/xcp_skel.py +49 -0
  62. pyxcp/examples/xcp_unlock.py +38 -0
  63. pyxcp/examples/xcp_user_supplied_driver.py +44 -0
  64. pyxcp/examples/xcphello.py +78 -0
  65. pyxcp/examples/xcphello_recorder.py +107 -0
  66. pyxcp/master/__init__.py +9 -0
  67. pyxcp/master/errorhandler.py +442 -0
  68. pyxcp/master/master.py +2047 -0
  69. pyxcp/py.typed +0 -0
  70. pyxcp/recorder/__init__.py +101 -0
  71. pyxcp/recorder/build_clang.cmd +1 -0
  72. pyxcp/recorder/build_clang.sh +2 -0
  73. pyxcp/recorder/build_gcc.cmd +1 -0
  74. pyxcp/recorder/build_gcc.sh +2 -0
  75. pyxcp/recorder/build_gcc_arm.sh +2 -0
  76. pyxcp/recorder/converter/__init__.py +450 -0
  77. pyxcp/recorder/lz4.c +2829 -0
  78. pyxcp/recorder/lz4.h +879 -0
  79. pyxcp/recorder/lz4hc.c +2041 -0
  80. pyxcp/recorder/lz4hc.h +413 -0
  81. pyxcp/recorder/mio.hpp +1714 -0
  82. pyxcp/recorder/reader.hpp +139 -0
  83. pyxcp/recorder/reco.py +277 -0
  84. pyxcp/recorder/recorder.rst +0 -0
  85. pyxcp/recorder/rekorder.cp310-win_arm64.pyd +0 -0
  86. pyxcp/recorder/rekorder.cp311-win_arm64.pyd +0 -0
  87. pyxcp/recorder/rekorder.cp312-win_arm64.pyd +0 -0
  88. pyxcp/recorder/rekorder.cpp +59 -0
  89. pyxcp/recorder/rekorder.hpp +274 -0
  90. pyxcp/recorder/setup.py +41 -0
  91. pyxcp/recorder/test_reko.py +34 -0
  92. pyxcp/recorder/unfolder.hpp +1332 -0
  93. pyxcp/recorder/wrap.cpp +189 -0
  94. pyxcp/recorder/writer.hpp +302 -0
  95. pyxcp/scripts/__init__.py +0 -0
  96. pyxcp/scripts/pyxcp_probe_can_drivers.py +20 -0
  97. pyxcp/scripts/xcp_examples.py +64 -0
  98. pyxcp/scripts/xcp_fetch_a2l.py +40 -0
  99. pyxcp/scripts/xcp_id_scanner.py +19 -0
  100. pyxcp/scripts/xcp_info.py +144 -0
  101. pyxcp/scripts/xcp_profile.py +27 -0
  102. pyxcp/scripts/xmraw_converter.py +31 -0
  103. pyxcp/stim/__init__.py +0 -0
  104. pyxcp/tests/test_asam_types.py +24 -0
  105. pyxcp/tests/test_binpacking.py +186 -0
  106. pyxcp/tests/test_can.py +1324 -0
  107. pyxcp/tests/test_checksum.py +95 -0
  108. pyxcp/tests/test_daq.py +193 -0
  109. pyxcp/tests/test_daq_opt.py +426 -0
  110. pyxcp/tests/test_frame_padding.py +156 -0
  111. pyxcp/tests/test_master.py +2006 -0
  112. pyxcp/tests/test_transport.py +81 -0
  113. pyxcp/tests/test_utils.py +30 -0
  114. pyxcp/timing.py +60 -0
  115. pyxcp/transport/__init__.py +10 -0
  116. pyxcp/transport/base.py +440 -0
  117. pyxcp/transport/base_transport.hpp +0 -0
  118. pyxcp/transport/can.py +556 -0
  119. pyxcp/transport/eth.py +219 -0
  120. pyxcp/transport/sxi.py +135 -0
  121. pyxcp/transport/transport_wrapper.cpp +0 -0
  122. pyxcp/transport/usb_transport.py +213 -0
  123. pyxcp/types.py +1000 -0
  124. pyxcp/utils.py +128 -0
  125. pyxcp/vector/__init__.py +0 -0
  126. pyxcp/vector/map.py +82 -0
  127. pyxcp-0.23.0.dist-info/LICENSE +165 -0
  128. pyxcp-0.23.0.dist-info/METADATA +107 -0
  129. pyxcp-0.23.0.dist-info/RECORD +131 -0
  130. pyxcp-0.23.0.dist-info/WHEEL +4 -0
  131. 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
Binary file
@@ -0,0 +1,13 @@
1
+
2
+ #if defined(_MSC_VER)
3
+ #pragma comment(lib, "Winmm.lib")
4
+ #pragma comment(lib, "Avrt.lib")
5
+ #endif
6
+
7
+ #include "stim.hpp"
8
+
9
+ void make_dto() {
10
+ }
11
+
12
+ void init() {
13
+ }