ZLayout EDA Library v1.0.0
Advanced Electronic Design Automation Layout Library with Bilingual Documentation
Loading...
Searching...
No Matches
advanced_spatial.hpp
Go to the documentation of this file.
1
14
15#pragma once
16
20#include <vector>
21#include <memory>
22#include <functional>
23#include <atomic>
24#include <thread>
25#include <mutex>
26#include <condition_variable>
27#include <future>
28#include <queue>
29#include <unordered_map>
30#include <unordered_set>
31
32#ifdef ZLAYOUT_USE_CUDA
33#include <cuda_runtime.h>
34#include <device_launch_parameters.h>
35#endif
36
37#ifdef ZLAYOUT_USE_OPENCL
38#include <CL/cl.h>
39#endif
40
41namespace zlayout {
42namespace spatial {
43
47template<typename T>
49private:
50 struct Block {
51 alignas(T) char data[sizeof(T)];
52 Block* next;
53 };
54
55 std::vector<std::unique_ptr<Block[]>> chunks;
56 Block* free_list;
57 size_t chunk_size;
58 std::mutex mutex;
59
60public:
61 explicit MemoryPool(size_t chunk_size = 1024)
62 : chunk_size(chunk_size), free_list(nullptr) {
63 allocate_chunk();
64 }
65
67 clear();
68 }
69
70 T* allocate() {
71 std::lock_guard<std::mutex> lock(mutex);
72 if (!free_list) {
73 allocate_chunk();
74 }
75
76 Block* block = free_list;
77 free_list = free_list->next;
78 return reinterpret_cast<T*>(block);
79 }
80
81 void deallocate(T* ptr) {
82 std::lock_guard<std::mutex> lock(mutex);
83 Block* block = reinterpret_cast<Block*>(ptr);
84 block->next = free_list;
85 free_list = block;
86 }
87
88private:
89 void allocate_chunk() {
90 auto chunk = std::make_unique<Block[]>(chunk_size);
91 for (size_t i = 0; i < chunk_size - 1; ++i) {
92 chunk[i].next = &chunk[i + 1];
93 }
94 chunk[chunk_size - 1].next = free_list;
95 free_list = &chunk[0];
96 chunks.push_back(std::move(chunk));
97 }
98
99 void clear() {
100 chunks.clear();
101 free_list = nullptr;
102 }
103};
104
109private:
110 std::vector<std::thread> workers;
111 mutable std::queue<std::function<void()>> tasks;
112 mutable std::mutex queue_mutex;
113 mutable std::condition_variable condition;
114 std::atomic<bool> stop;
115
116public:
117 explicit ThreadPool(size_t threads = std::thread::hardware_concurrency());
118 ~ThreadPool();
119
120 template<class F, class... Args>
121 auto enqueue(F&& f, Args&&... args) const
122 -> std::future<typename std::result_of<F(Args...)>::type>;
123
124 void wait_for_completion();
125 size_t get_thread_count() const { return workers.size(); }
126};
127
131struct IPBlock {
132 std::string name;
134 std::vector<std::unique_ptr<IPBlock>> sub_blocks;
135 std::vector<size_t> component_ids;
136 size_t level; // Hierarchy level (0 = top level)
137
138 IPBlock(const std::string& name, const geometry::Rectangle& boundary, size_t level = 0)
140
141 bool contains(const geometry::Rectangle& rect) const {
142 return boundary.contains_rectangle(rect);
143 }
144
145 bool intersects(const geometry::Rectangle& rect) const {
146 return boundary.intersects(rect);
147 }
148
149 void add_sub_block(std::unique_ptr<IPBlock> block) {
150 sub_blocks.push_back(std::move(block));
151 }
152
153 void add_component(size_t component_id) {
154 component_ids.push_back(component_id);
155 }
156};
157
162public:
163 static uint64_t encode(uint32_t x, uint32_t y) {
164 return interleave(x) | (interleave(y) << 1);
165 }
166
167 static std::pair<uint32_t, uint32_t> decode(uint64_t z) {
168 return {deinterleave(z), deinterleave(z >> 1)};
169 }
170
171 static uint64_t encode_point(const geometry::Point& point,
172 const geometry::Rectangle& bounds) {
173 uint32_t x = static_cast<uint32_t>((point.x - bounds.x) / bounds.width * 0xFFFFFFFF);
174 uint32_t y = static_cast<uint32_t>((point.y - bounds.y) / bounds.height * 0xFFFFFFFF);
175 return encode(x, y);
176 }
177
178private:
179 static uint64_t interleave(uint32_t x) {
180 uint64_t result = x;
181 result = (result | (result << 16)) & 0x0000FFFF0000FFFF;
182 result = (result | (result << 8)) & 0x00FF00FF00FF00FF;
183 result = (result | (result << 4)) & 0x0F0F0F0F0F0F0F0F;
184 result = (result | (result << 2)) & 0x3333333333333333;
185 result = (result | (result << 1)) & 0x5555555555555555;
186 return result;
187 }
188
189 static uint32_t deinterleave(uint64_t x) {
190 x = x & 0x5555555555555555;
191 x = (x | (x >> 1)) & 0x3333333333333333;
192 x = (x | (x >> 2)) & 0x0F0F0F0F0F0F0F0F;
193 x = (x | (x >> 4)) & 0x00FF00FF00FF00FF;
194 x = (x | (x >> 8)) & 0x0000FFFF0000FFFF;
195 x = (x | (x >> 16)) & 0x00000000FFFFFFFF;
196 return static_cast<uint32_t>(x);
197 }
198};
199
203template<typename T>
204struct RTreeNode {
205 geometry::Rectangle mbr; // Minimum bounding rectangle
206 std::vector<std::pair<T, geometry::Rectangle>> entries;
207 std::vector<std::unique_ptr<RTreeNode<T>>> children;
209 static const size_t MAX_ENTRIES = 16;
210 static const size_t MIN_ENTRIES = 4;
211
212 RTreeNode(bool leaf = true) : is_leaf(leaf) {}
213
214 bool is_full() const {
215 return entries.size() >= MAX_ENTRIES;
216 }
217
218 void update_mbr() {
219 if (entries.empty() && children.empty()) {
220 mbr = geometry::Rectangle(0, 0, 0, 0);
221 return;
222 }
223
224 if (is_leaf) {
225 mbr = entries[0].second;
226 for (size_t i = 1; i < entries.size(); ++i) {
227 mbr = mbr.union_with(entries[i].second);
228 }
229 } else {
230 mbr = children[0]->mbr;
231 for (size_t i = 1; i < children.size(); ++i) {
232 mbr = mbr.union_with(children[i]->mbr);
233 }
234 }
235 }
236};
237
241template<typename T>
242class RTree {
243private:
244 std::unique_ptr<RTreeNode<T>> root;
245 size_t object_count;
246
247public:
248 RTree() : object_count(0) {
249 root = std::make_unique<RTreeNode<T>>(true);
250 }
251
252 void insert(const T& object, const geometry::Rectangle& bbox);
253 std::vector<T> query_range(const geometry::Rectangle& range) const;
254 std::vector<T> query_point(const geometry::Point& point) const;
255 bool remove(const T& object, const geometry::Rectangle& bbox);
256
257 size_t size() const { return object_count; }
258 bool empty() const { return object_count == 0; }
259 void clear();
260
261private:
262 void insert_recursive(RTreeNode<T>* node, const T& object, const geometry::Rectangle& bbox);
263 std::unique_ptr<RTreeNode<T>> split_node(RTreeNode<T>* node);
264 void query_recursive(const RTreeNode<T>* node, const geometry::Rectangle& range, std::vector<T>& result) const;
265 double calculate_area_increase(const geometry::Rectangle& current, const geometry::Rectangle& new_rect) const;
266};
267
271template<typename T>
273private:
274 std::unique_ptr<IPBlock> root_block;
275 std::unordered_map<std::string, std::unique_ptr<QuadTree<T>>> block_indices;
276 std::unordered_map<std::string, std::unique_ptr<RTree<T>>> rtree_indices;
277 std::unordered_map<uint64_t, std::vector<T>> zorder_buckets;
278
279 ThreadPool thread_pool;
281
282 geometry::Rectangle world_bounds;
283 size_t max_objects_per_block;
284 size_t max_hierarchy_levels;
285
286public:
288 size_t max_objects_per_block = 1000000,
289 size_t max_hierarchy_levels = 8)
290 : world_bounds(world_bounds),
291 max_objects_per_block(max_objects_per_block),
292 max_hierarchy_levels(max_hierarchy_levels),
293 thread_pool(std::thread::hardware_concurrency()) {
294
295 root_block = std::make_unique<IPBlock>("root", world_bounds, 0);
296 }
297
298 // Batch operations for efficiency
299 void bulk_insert(const std::vector<std::pair<T, geometry::Rectangle>>& objects);
300 void parallel_bulk_insert(const std::vector<std::pair<T, geometry::Rectangle>>& objects);
301
302 std::vector<T> parallel_query_range(const geometry::Rectangle& range) const;
303 std::vector<std::pair<T, T>> parallel_find_intersections() const;
304
305 // IP block management
306 void create_ip_block(const std::string& name, const geometry::Rectangle& boundary,
307 const std::string& parent_name = "root");
308 void optimize_hierarchy();
309
310 // Statistics and optimization
319
321 void optimize_for_query_pattern(const std::vector<geometry::Rectangle>& query_patterns);
322
323private:
324 void create_block_index(const std::string& block_name, const geometry::Rectangle& boundary);
325 IPBlock* find_block(const std::string& name) const;
326 std::string find_optimal_block(const geometry::Rectangle& bbox) const;
327 void partition_objects_by_zorder(const std::vector<std::pair<T, geometry::Rectangle>>& objects);
328
329 std::vector<std::future<std::vector<T>>> dispatch_parallel_queries(
330 const geometry::Rectangle& range) const;
331};
332
337public:
345
346 template<typename T>
347 static std::unique_ptr<HierarchicalSpatialIndex<T>> create_optimized_index(
348 const geometry::Rectangle& world_bounds,
349 size_t expected_object_count,
350 IndexType preferred_type = IndexType::HYBRID) {
351
352 // Choose optimal parameters based on expected scale
353 size_t max_objects_per_block = 1000000;
354 size_t max_hierarchy_levels = 8;
355
356 if (expected_object_count > 100000000) { // > 100M objects
357 max_objects_per_block = 10000000; // 10M per block
358 max_hierarchy_levels = 12;
359 } else if (expected_object_count > 10000000) { // > 10M objects
360 max_objects_per_block = 1000000; // 1M per block
361 max_hierarchy_levels = 10;
362 }
363
364 return std::make_unique<HierarchicalSpatialIndex<T>>(
365 world_bounds, max_objects_per_block, max_hierarchy_levels);
366 }
367};
368
369// Template implementations
370
371template<typename T>
373 const std::vector<std::pair<T, geometry::Rectangle>>& objects) {
374
375 // For simplicity, just use the objects as-is without sorting for now
376 const std::vector<std::pair<T, geometry::Rectangle>>& sorted_objects = objects;
377
378 // Create blocks as needed and insert objects
379 for (const auto& [object, bbox] : sorted_objects) {
380 // Find appropriate block
381 std::string block_name = find_optimal_block(bbox);
382
383 // Create block index if needed
384 if (block_indices.find(block_name) == block_indices.end()) {
385 create_block_index(block_name, bbox);
386 }
387
388 // Insert into block
389 block_indices[block_name]->insert(object);
390 }
391}
392
393template<typename T>
395 const std::vector<std::pair<T, geometry::Rectangle>>& objects) {
396
397 const size_t num_threads = thread_pool.get_thread_count();
398 const size_t chunk_size = (objects.size() + num_threads - 1) / num_threads;
399
400 std::vector<std::future<void>> futures;
401
402 for (size_t i = 0; i < num_threads; ++i) {
403 size_t start = i * chunk_size;
404 size_t end = std::min(start + chunk_size, objects.size());
405
406 if (start >= objects.size()) break;
407
408 auto future = thread_pool.enqueue([this, &objects, start, end]() {
409 std::vector<std::pair<T, geometry::Rectangle>> chunk(
410 objects.begin() + start, objects.begin() + end);
411 this->bulk_insert(chunk);
412 });
413
414 futures.push_back(std::move(future));
415 }
416
417 // Wait for all insertions to complete
418 for (auto& future : futures) {
419 future.wait();
420 }
421}
422
423template<typename T>
425 const geometry::Rectangle& range) const {
426
427 auto futures = dispatch_parallel_queries(range);
428
429 std::vector<T> result;
430 for (auto& future : futures) {
431 auto partial_result = future.get();
432 result.insert(result.end(), partial_result.begin(), partial_result.end());
433 }
434
435 // Note: In a full implementation, you'd want to remove duplicates here
436 // For now, keeping it simple without sorting
437
438 return result;
439}
440
441} // namespace spatial
442} // namespace zlayout
2D point with high-precision coordinates and utility methods
Definition point.hpp:23
double x
X coordinate.
Definition point.hpp:25
double y
Y coordinate.
Definition point.hpp:26
Axis-aligned rectangle for bounding boxes and simple EDA components.
Definition rectangle.hpp:26
double y
Y coordinate of bottom-left corner.
Definition rectangle.hpp:29
double height
Height of rectangle.
Definition rectangle.hpp:31
double x
X coordinate of bottom-left corner.
Definition rectangle.hpp:28
double width
Width of rectangle.
Definition rectangle.hpp:30
void create_ip_block(const std::string &name, const geometry::Rectangle &boundary, const std::string &parent_name="root")
void optimize_for_query_pattern(const std::vector< geometry::Rectangle > &query_patterns)
std::vector< std::pair< T, T > > parallel_find_intersections() const
HierarchicalSpatialIndex(const geometry::Rectangle &world_bounds, size_t max_objects_per_block=1000000, size_t max_hierarchy_levels=8)
void parallel_bulk_insert(const std::vector< std::pair< T, geometry::Rectangle > > &objects)
void bulk_insert(const std::vector< std::pair< T, geometry::Rectangle > > &objects)
std::vector< T > parallel_query_range(const geometry::Rectangle &range) const
Memory pool for efficient object allocation.
MemoryPool(size_t chunk_size=1024)
void insert(const T &object, const geometry::Rectangle &bbox)
std::vector< T > query_point(const geometry::Point &point) const
bool remove(const T &object, const geometry::Rectangle &bbox)
std::vector< T > query_range(const geometry::Rectangle &range) const
Ultra-high performance spatial index factory.
static std::unique_ptr< HierarchicalSpatialIndex< T > > create_optimized_index(const geometry::Rectangle &world_bounds, size_t expected_object_count, IndexType preferred_type=IndexType::HYBRID)
Thread pool for parallel processing.
auto enqueue(F &&f, Args &&... args) const -> std::future< typename std::result_of< F(Args...)>::type >
ThreadPool(size_t threads=std::thread::hardware_concurrency())
Z-order curve (Morton code) for spatial hashing.
static std::pair< uint32_t, uint32_t > decode(uint64_t z)
static uint64_t encode(uint32_t x, uint32_t y)
static uint64_t encode_point(const geometry::Point &point, const geometry::Rectangle &bounds)
Main namespace for ZLayout library.
Definition component.hpp:20
2D Point class for geometric calculations
QuadTree spatial indexing for efficient geometric queries.
Axis-aligned rectangle class for bounding boxes and simple components.
IP Block represents a hierarchical design block.
bool contains(const geometry::Rectangle &rect) const
std::vector< size_t > component_ids
bool intersects(const geometry::Rectangle &rect) const
void add_sub_block(std::unique_ptr< IPBlock > block)
std::vector< std::unique_ptr< IPBlock > > sub_blocks
IPBlock(const std::string &name, const geometry::Rectangle &boundary, size_t level=0)
void add_component(size_t component_id)
R-tree node for efficient rectangle indexing.
std::vector< std::pair< T, geometry::Rectangle > > entries
std::vector< std::unique_ptr< RTreeNode< T > > > children