20#include <boost/test/unit_test.hpp>
59#include <wx/filename.h>
74static void appendLe32( std::vector<uint8_t>& aBytes, uint32_t aValue )
76 for(
int shift = 0; shift < 32; shift += 8 )
77 aBytes.push_back(
static_cast<uint8_t
>( aValue >> shift ) );
81static void appendLe16( std::vector<uint8_t>& aBytes, uint16_t aValue )
83 aBytes.push_back(
static_cast<uint8_t
>( aValue ) );
84 aBytes.push_back(
static_cast<uint8_t
>( aValue >> 8 ) );
88static void appendLzt( std::vector<uint8_t>& aBytes,
const std::string& aValue )
90 appendLe16( aBytes,
static_cast<uint16_t
>( aValue.size() ) );
91 aBytes.insert( aBytes.end(), aValue.begin(), aValue.end() );
92 aBytes.push_back( 0 );
97static void appendFramedHeader( std::vector<uint8_t>& aBytes, uint8_t aType,
size_t aLongPrefixCount )
99 size_t start = aBytes.size();
100 size_t end = start + 9 * aLongPrefixCount + 3 + 8;
102 for(
size_t i = 0; i < aLongPrefixCount; ++i )
104 aBytes.push_back( aType );
105 appendLe32( aBytes,
static_cast<uint32_t
>(
end - ( start + 9 * i + 9 ) ) );
106 appendLe32( aBytes, 0 );
109 aBytes.push_back( aType );
110 appendLe16( aBytes, 0 );
111 aBytes.insert( aBytes.end(), { 0xFF, 0xE4, 0x5C, 0x39 } );
112 appendLe32( aBytes, 0 );
118static std::vector<char> makeLibraryStream( uint16_t aVersionMajor,
const std::vector<std::string>& aStrings )
120 std::vector<uint8_t> bytes( 32, 0 );
121 const std::string introduction =
"OrCAD Windows Design";
122 std::copy( introduction.begin(), introduction.end(), bytes.begin() );
124 appendLe16( bytes, aVersionMajor );
125 appendLe16( bytes, 0 );
126 bytes.resize( bytes.size() + 12, 0 );
127 appendLe16( bytes, 1 );
129 appendLe16( bytes, 1 );
130 appendLe16( bytes, 0 );
131 bytes.resize( bytes.size() + 8, 0 );
133 for(
int i = 0; i < 8; ++i )
134 appendLzt( bytes,
"" );
136 bytes.resize( bytes.size() + 156, 0 );
138 if( aVersionMajor < 3 )
139 appendLe16( bytes,
static_cast<uint16_t
>( aStrings.size() ) );
141 appendLe32( bytes,
static_cast<uint32_t
>( aStrings.size() ) );
143 for(
const std::string&
text : aStrings )
144 appendLzt( bytes,
text );
146 appendLe16( bytes, 0 );
147 bytes.resize( bytes.size() + 8, 0 );
148 appendLzt( bytes,
"SCHEMATIC1" );
150 return std::vector<char>( bytes.begin(), bytes.end() );
154static std::vector<char> cisFramed(
const std::vector<uint8_t>& aPayload )
156 std::vector<char> bytes;
157 uint32_t length =
static_cast<uint32_t
>( aPayload.size() );
159 for(
int shift = 0; shift < 32; shift += 8 )
160 bytes.push_back(
static_cast<char>( length >> shift ) );
162 bytes.insert( bytes.end(), aPayload.begin(), aPayload.end() );
167static void writeLe16( std::vector<uint8_t>& aBytes,
size_t aOffset, uint16_t aValue )
169 aBytes[aOffset] =
static_cast<uint8_t
>( aValue );
170 aBytes[aOffset + 1] =
static_cast<uint8_t
>( aValue >> 8 );
174static void writeLe32( std::vector<uint8_t>& aBytes,
size_t aOffset, uint32_t aValue )
176 for(
int shift = 0; shift < 32; shift += 8 )
177 aBytes[aOffset++] =
static_cast<uint8_t
>( aValue >> shift );
181static std::vector<uint8_t> makeGlyphIndexWmf()
183 std::vector<uint8_t> bytes;
184 appendLe16( bytes, 1 );
185 appendLe16( bytes, 9 );
186 appendLe16( bytes, 0x0300 );
187 appendLe32( bytes, 0 );
188 appendLe16( bytes, 1 );
189 appendLe32( bytes, 10 );
190 appendLe16( bytes, 0 );
192 auto record = [&]( uint16_t aFunction, std::initializer_list<uint16_t> aParams )
194 appendLe32( bytes,
static_cast<uint32_t
>( aParams.size() + 3 ) );
195 appendLe16( bytes, aFunction );
197 for( uint16_t param : aParams )
198 appendLe16( bytes, param );
201 record( 0x0103, { 8 } );
202 record( 0x020B, { 0, 0 } );
203 record( 0x020C, { 100, 100 } );
204 record( 0x012E, { 0 } );
205 record( 0x0102, { 1 } );
206 record( 0x041B, { 90, 90, 10, 10 } );
207 record( 0x0A32, { 50, 50, 2, 0x0010, 0x4241, 8, 8 } );
208 record( 0x02FC, { 0, 0xFFFF, 0x00FF, 0 } );
209 record( 0x012D, { 0 } );
210 record( 0x0940, { 0x0029, 0x00AA, 0, 0, 0, 100, 100, 0, 0 } );
212 writeLe32( bytes, 6,
static_cast<uint32_t
>( bytes.size() / 2 ) );
217static std::vector<uint8_t> makeFlippedDibWmf()
219 std::vector<uint8_t> bytes;
220 appendLe16( bytes, 1 );
221 appendLe16( bytes, 9 );
222 appendLe16( bytes, 0x0300 );
223 appendLe32( bytes, 0 );
224 appendLe16( bytes, 0 );
225 appendLe32( bytes, 0 );
226 appendLe16( bytes, 0 );
228 auto record = [&]( uint16_t aFunction, std::initializer_list<uint16_t> aParams )
230 appendLe32( bytes,
static_cast<uint32_t
>( aParams.size() + 3 ) );
231 appendLe16( bytes, aFunction );
233 for( uint16_t param : aParams )
234 appendLe16( bytes, param );
237 record( 0x0103, { 8 } );
238 record( 0x020B, { 0, 0 } );
239 record( 0x020C, { 100, 100 } );
241 const size_t dibRecord = bytes.size();
242 appendLe32( bytes, 0 );
243 appendLe16( bytes, 0x0B41 );
244 appendLe16( bytes, 0x0020 );
245 appendLe16( bytes, 0x00CC );
246 appendLe16( bytes, 2 );
247 appendLe16( bytes, 2 );
248 appendLe16( bytes, 0 );
249 appendLe16( bytes, 0 );
250 appendLe16( bytes,
static_cast<uint16_t
>( -80 ) );
251 appendLe16( bytes, 80 );
252 appendLe16( bytes, 90 );
253 appendLe16( bytes, 10 );
255 appendLe32( bytes, 40 );
256 appendLe32( bytes, 2 );
257 appendLe32( bytes, 2 );
258 appendLe16( bytes, 1 );
259 appendLe16( bytes, 24 );
260 appendLe32( bytes, 0 );
261 appendLe32( bytes, 16 );
262 appendLe32( bytes, 0 );
263 appendLe32( bytes, 0 );
264 appendLe32( bytes, 0 );
265 appendLe32( bytes, 0 );
267 bytes.insert( bytes.end(), { 0, 0, 255, 0, 255, 0, 0, 0 } );
268 bytes.insert( bytes.end(), { 255, 0, 0, 255, 255, 255, 0, 0 } );
269 writeLe32( bytes, dibRecord,
static_cast<uint32_t
>( ( bytes.size() - dibRecord ) / 2 ) );
272 writeLe32( bytes, 6,
static_cast<uint32_t
>( bytes.size() / 2 ) );
273 writeLe32( bytes, 12,
static_cast<uint32_t
>( ( bytes.size() - dibRecord ) / 2 ) );
278static std::vector<uint8_t> makeEmbeddedEmfWmf(
const std::vector<uint8_t>& aEmf = {} )
280 std::vector<uint8_t> emf = aEmf;
284 emf.resize( 100, 0 );
285 writeLe32( emf, 0, 1 );
286 writeLe32( emf, 4, 88 );
287 writeLe32( emf, 40, 0x464D4520 );
288 writeLe32( emf, 48, emf.size() );
291 std::vector<uint8_t> wmf;
292 appendLe16( wmf, 1 );
293 appendLe16( wmf, 9 );
294 appendLe16( wmf, 0x0300 );
295 appendLe32( wmf, 0 );
296 appendLe16( wmf, 0 );
297 appendLe32( wmf, 0 );
298 appendLe16( wmf, 0 );
300 size_t sourceOffset = 0;
301 const size_t chunkSizes[] = { emf.size() / 2, emf.size() - emf.size() / 2 };
303 for(
size_t chunkSize : chunkSizes )
305 size_t recordStart = wmf.size();
306 appendLe32( wmf, 0 );
307 appendLe16( wmf, 0x0626 );
308 appendLe16( wmf, 0x000F );
309 appendLe16( wmf,
static_cast<uint16_t
>( 34 + chunkSize ) );
310 appendLe32( wmf, 0x43464D57 );
311 appendLe32( wmf, 1 );
312 appendLe32( wmf, 0x00010000 );
313 appendLe16( wmf, 0 );
314 appendLe32( wmf, 0 );
315 appendLe32( wmf, std::size( chunkSizes ) );
316 appendLe32( wmf, chunkSize );
317 appendLe32( wmf, emf.size() - sourceOffset - chunkSize );
318 appendLe32( wmf, emf.size() );
319 wmf.insert( wmf.end(), emf.begin() + sourceOffset, emf.begin() + sourceOffset + chunkSize );
324 writeLe32( wmf, recordStart, ( wmf.size() - recordStart ) / 2 );
325 sourceOffset += chunkSize;
328 appendLe32( wmf, 3 );
329 appendLe16( wmf, 0 );
330 writeLe32( wmf, 6, wmf.size() / 2 );
335static std::vector<uint8_t> makeRenderableEmf()
337 std::vector<uint8_t> emf( 108, 0 );
338 writeLe32( emf, 0, 1 );
339 writeLe32( emf, 4, 108 );
340 writeLe32( emf, 16, 100 );
341 writeLe32( emf, 20, 100 );
342 writeLe32( emf, 32, 2646 );
343 writeLe32( emf, 36, 2646 );
344 writeLe32( emf, 40, 0x464D4520 );
345 writeLe32( emf, 44, 0x00010000 );
346 writeLe32( emf, 52, 23 );
347 writeLe16( emf, 56, 4 );
348 writeLe32( emf, 72, 100 );
349 writeLe32( emf, 76, 100 );
350 writeLe32( emf, 80, 26 );
351 writeLe32( emf, 84, 26 );
352 writeLe32( emf, 100, 26000 );
353 writeLe32( emf, 104, 26000 );
355 auto pointRecord = [&]( uint32_t aType, int32_t aX, int32_t aY )
357 appendLe32( emf, aType );
358 appendLe32( emf, 16 );
359 appendLe32( emf,
static_cast<uint32_t
>( aX ) );
360 appendLe32( emf,
static_cast<uint32_t
>( aY ) );
363 pointRecord( 27, 10, 10 );
364 pointRecord( 54, 90, 10 );
366 appendLe32( emf, 82 );
367 appendLe32( emf, 104 );
368 appendLe32( emf, 1 );
369 appendLe32( emf,
static_cast<uint32_t
>( -20 ) );
370 appendLe32( emf, 0 );
371 appendLe32( emf, 900 );
372 appendLe32( emf, 900 );
373 appendLe32( emf, 400 );
374 emf.insert( emf.end(), 8, 0 );
375 const std::u16string face = u
"Source Sans Pro";
377 for(
size_t i = 0; i < 32; ++i )
378 appendLe16( emf, i < face.size() ? face[i] : 0 );
380 appendLe32( emf, 37 );
381 appendLe32( emf, 12 );
382 appendLe32( emf, 1 );
383 appendLe32( emf, 24 );
384 appendLe32( emf, 12 );
385 appendLe32( emf, 0x00CC0000 );
386 appendLe32( emf, 22 );
387 appendLe32( emf, 12 );
388 appendLe32( emf, 0x18 );
390 appendLe32( emf, 84 );
391 appendLe32( emf, 88 );
392 emf.insert( emf.end(), 16, 0 );
393 appendLe32( emf, 1 );
394 appendLe32( emf, 0x3F800000 );
395 appendLe32( emf, 0x3F800000 );
396 appendLe32( emf, 40 );
397 appendLe32( emf, 70 );
398 appendLe32( emf, 2 );
399 appendLe32( emf, 76 );
400 appendLe32( emf, 0 );
401 emf.insert( emf.end(), 16, 0 );
402 appendLe32( emf, 80 );
403 appendLe16( emf,
'H' );
404 appendLe16( emf,
'i' );
405 appendLe32( emf, 12 );
406 appendLe32( emf, 12 );
408 appendLe32( emf, 82 );
409 appendLe32( emf, 104 );
410 appendLe32( emf, 2 );
411 appendLe32( emf,
static_cast<uint32_t
>( -20 ) );
412 appendLe32( emf, 0 );
413 appendLe32( emf, 0 );
414 appendLe32( emf, 0 );
415 appendLe32( emf, 400 );
416 emf.insert( emf.end(), 8, 0 );
418 for(
size_t i = 0; i < 32; ++i )
419 appendLe16( emf, i < face.size() ? face[i] : 0 );
421 appendLe32( emf, 37 );
422 appendLe32( emf, 12 );
423 appendLe32( emf, 2 );
425 appendLe32( emf, 84 );
426 appendLe32( emf, 88 );
427 emf.insert( emf.end(), 16, 0 );
428 appendLe32( emf, 1 );
429 appendLe32( emf, 0x3F800000 );
430 appendLe32( emf, 0x3F800000 );
431 appendLe32( emf, 70 );
432 appendLe32( emf, 30 );
433 appendLe32( emf, 2 );
434 appendLe32( emf, 76 );
435 appendLe32( emf, 0x10 );
436 emf.insert( emf.end(), 16, 0 );
437 appendLe32( emf, 80 );
438 appendLe16( emf, 1211 );
439 appendLe16( emf, 3 );
440 appendLe32( emf, 20 );
441 appendLe32( emf, 5 );
443 appendLe32( emf, 82 );
444 appendLe32( emf, 104 );
445 appendLe32( emf, 3 );
446 appendLe32( emf,
static_cast<uint32_t
>( -20 ) );
447 appendLe32( emf, 0 );
448 appendLe32( emf, 0 );
449 appendLe32( emf, 0 );
450 appendLe32( emf, 400 );
451 emf.insert( emf.end(), 8, 0 );
452 const std::u16string calibri = u
"Calibri";
454 for(
size_t i = 0; i < 32; ++i )
455 appendLe16( emf, i < calibri.size() ? calibri[i] : 0 );
457 appendLe32( emf, 37 );
458 appendLe32( emf, 12 );
459 appendLe32( emf, 3 );
460 appendLe32( emf, 84 );
461 appendLe32( emf, 84 );
462 emf.insert( emf.end(), 16, 0 );
463 appendLe32( emf, 1 );
464 appendLe32( emf, 0x3F800000 );
465 appendLe32( emf, 0x3F800000 );
466 appendLe32( emf, 5 );
467 appendLe32( emf, 95 );
468 appendLe32( emf, 1 );
469 appendLe32( emf, 76 );
470 appendLe32( emf, 0x10 );
471 emf.insert( emf.end(), 16, 0 );
472 appendLe32( emf, 80 );
473 appendLe16( emf, 3 );
474 appendLe16( emf, 0 );
475 appendLe32( emf, 10 );
477 appendLe32( emf, 85 );
478 appendLe32( emf, 44 );
479 emf.insert( emf.end(), 16, 0 );
480 appendLe32( emf, 4 );
482 for(
const std::pair<uint16_t, uint16_t>& point :
483 { std::pair<uint16_t, uint16_t>{ 10, 40 }, { 20, 20 }, { 30, 60 }, { 40, 40 } } )
485 appendLe16( emf, point.first );
486 appendLe16( emf, point.second );
489 appendLe32( emf, 59 );
490 appendLe32( emf, 8 );
491 pointRecord( 27, 10, 90 );
492 pointRecord( 54, 90, 90 );
493 appendLe32( emf, 60 );
494 appendLe32( emf, 8 );
495 appendLe32( emf, 64 );
496 appendLe32( emf, 24 );
497 emf.insert( emf.end(), 16, 0 );
499 appendLe32( emf, 91 );
500 appendLe32( emf, 52 );
501 emf.insert( emf.end(), 16, 0 );
502 appendLe32( emf, 1 );
503 appendLe32( emf, 4 );
504 appendLe32( emf, 4 );
506 for(
const std::pair<uint16_t, uint16_t>& point :
507 { std::pair<uint16_t, uint16_t>{ 60, 60 }, { 70, 50 }, { 80, 60 }, { 70, 70 } } )
509 appendLe16( emf, point.first );
510 appendLe16( emf, point.second );
513 appendLe32( emf, 58 );
514 appendLe32( emf, 12 );
515 appendLe32( emf, 0x40400000 );
517 appendLe32( emf, 14 );
518 appendLe32( emf, 20 );
519 emf.insert( emf.end(), 12, 0 );
520 writeLe32( emf, 48, emf.size() );
525static std::vector<uint8_t> makeCalibriMetricEmf(
const std::u16string& aText = u
"UMC" )
527 std::vector<uint8_t> emf( 108, 0 );
528 writeLe32( emf, 0, 1 );
529 writeLe32( emf, 4, 108 );
530 writeLe32( emf, 16, 100 );
531 writeLe32( emf, 20, 50 );
532 writeLe32( emf, 32, 2646 );
533 writeLe32( emf, 36, 1323 );
534 writeLe32( emf, 40, 0x464D4520 );
535 writeLe32( emf, 44, 0x00010000 );
536 writeLe32( emf, 52, 6 );
537 writeLe16( emf, 56, 2 );
538 writeLe32( emf, 72, 100 );
539 writeLe32( emf, 76, 50 );
540 writeLe32( emf, 80, 26 );
541 writeLe32( emf, 84, 13 );
542 writeLe32( emf, 100, 26000 );
543 writeLe32( emf, 104, 13000 );
545 appendLe32( emf, 82 );
546 appendLe32( emf, 104 );
547 appendLe32( emf, 1 );
548 appendLe32( emf,
static_cast<uint32_t
>( -20 ) );
549 appendLe32( emf, 0 );
550 appendLe32( emf, 0 );
551 appendLe32( emf, 0 );
552 appendLe32( emf, 400 );
553 emf.insert( emf.end(), 8, 0 );
554 const std::u16string calibri = u
"Calibri";
556 for(
size_t i = 0; i < 32; ++i )
557 appendLe16( emf, i < calibri.size() ? calibri[i] : 0 );
559 appendLe32( emf, 37 );
560 appendLe32( emf, 12 );
561 appendLe32( emf, 1 );
562 appendLe32( emf, 22 );
563 appendLe32( emf, 12 );
564 appendLe32( emf, 0x18 );
566 size_t stringBytes = ( aText.size() * 2 + 3 ) & ~size_t( 3 );
567 appendLe32( emf, 84 );
568 appendLe32( emf, 76 + stringBytes + aText.size() * 4 );
569 emf.insert( emf.end(), 16, 0 );
570 appendLe32( emf, 1 );
571 appendLe32( emf, 0x3F800000 );
572 appendLe32( emf, 0x3F800000 );
573 appendLe32( emf, 5 );
574 appendLe32( emf, 5 );
575 appendLe32( emf, aText.size() );
576 appendLe32( emf, 76 );
577 appendLe32( emf, 0 );
578 emf.insert( emf.end(), 16, 0 );
579 appendLe32( emf, 76 + stringBytes );
581 for(
char16_t c : aText )
582 appendLe16( emf, c );
584 emf.insert( emf.end(), stringBytes - aText.size() * 2, 0 );
586 for(
size_t i = 0; i < aText.size(); ++i )
587 appendLe32( emf, i == 1 ? 16 : i == 2 ? 10 : 12 );
589 appendLe32( emf, 14 );
590 appendLe32( emf, 20 );
591 emf.insert( emf.end(), 12, 0 );
592 writeLe32( emf, 48, emf.size() );
599static std::vector<uint8_t> makeOlePayload(
const std::vector<uint8_t>& aCfb, uint32_t aDeclaredLength )
601 std::vector<uint8_t> payload( 26, 0 );
602 writeLe32( payload, 0, aDeclaredLength + 22 );
603 writeLe32( payload, 22, aDeclaredLength );
604 payload.insert( payload.end(), aCfb.begin(), aCfb.end() );
610static std::vector<uint8_t> makeOlePreviewCfb(
const std::vector<uint16_t>& aName,
const std::vector<uint8_t>& aStream )
612 constexpr uint32_t FREE_SECTOR = 0xFFFFFFFF;
613 constexpr uint32_t END_OF_CHAIN = 0xFFFFFFFE;
614 constexpr uint32_t FAT_SECTOR = 0xFFFFFFFD;
615 constexpr size_t SECTOR_SIZE = 512;
616 constexpr size_t STREAM_SECTORS = 8;
618 std::vector<uint8_t> cfb( SECTOR_SIZE * ( 3 + STREAM_SECTORS ), 0 );
619 const uint8_t magic[] = { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 };
620 std::copy( std::begin( magic ), std::end( magic ), cfb.begin() );
621 writeLe16( cfb, 24, 0x003E );
622 writeLe16( cfb, 26, 3 );
623 writeLe16( cfb, 28, 0xFFFE );
624 writeLe16( cfb, 30, 9 );
625 writeLe16( cfb, 32, 6 );
626 writeLe32( cfb, 44, 1 );
627 writeLe32( cfb, 48, 1 );
628 writeLe32( cfb, 56, 4096 );
629 writeLe32( cfb, 60, END_OF_CHAIN );
630 writeLe32( cfb, 68, END_OF_CHAIN );
632 for(
size_t i = 0; i < 109; ++i )
633 writeLe32( cfb, 76 + 4 * i, i == 0 ? 0 : FREE_SECTOR );
635 size_t fat = SECTOR_SIZE;
636 writeLe32( cfb, fat, FAT_SECTOR );
637 writeLe32( cfb, fat + 4, END_OF_CHAIN );
639 for(
size_t i = 0; i < STREAM_SECTORS; ++i )
640 writeLe32( cfb, fat + 4 * ( 2 + i ), i + 1 == STREAM_SECTORS ? END_OF_CHAIN : 3 + i );
642 for(
size_t i = 2 + STREAM_SECTORS; i < SECTOR_SIZE / 4; ++i )
643 writeLe32( cfb, fat + 4 * i, FREE_SECTOR );
645 size_t root = 2 * SECTOR_SIZE;
646 writeLe16( cfb, root,
'R' );
647 writeLe16( cfb, root + 2, 0 );
648 writeLe16( cfb, root + 64, 4 );
650 writeLe32( cfb, root + 68, FREE_SECTOR );
651 writeLe32( cfb, root + 72, FREE_SECTOR );
652 writeLe32( cfb, root + 76, 1 );
653 writeLe32( cfb, root + 116, END_OF_CHAIN );
655 size_t entry = root + 128;
657 for(
size_t i = 0; i < aName.size(); ++i )
658 writeLe16( cfb, entry + 2 * i, aName[i] );
660 writeLe16( cfb, entry + 64,
static_cast<uint16_t
>( 2 * aName.size() ) );
662 writeLe32( cfb, entry + 68, FREE_SECTOR );
663 writeLe32( cfb, entry + 72, FREE_SECTOR );
664 writeLe32( cfb, entry + 76, FREE_SECTOR );
665 writeLe32( cfb, entry + 116, 2 );
666 writeLe32( cfb, entry + 120, STREAM_SECTORS * SECTOR_SIZE );
668 std::copy_n( aStream.begin(), std::min( aStream.size(), STREAM_SECTORS * SECTOR_SIZE ),
669 cfb.begin() + 3 * SECTOR_SIZE );
674static std::vector<uint8_t> makeOleWmfPreview(
const std::vector<uint8_t>& aWmf )
676 std::vector<uint8_t> presentation( 40, 0 );
677 writeLe32( presentation, 4, 14 );
678 presentation.insert( presentation.end(), aWmf.begin(), aWmf.end() );
680 const std::vector<uint16_t>
name = { 2,
'O',
'l',
'e',
'P',
'r',
'e',
's',
'0',
'0',
'0', 0 };
681 std::vector<uint8_t> cfb = makeOlePreviewCfb(
name, presentation );
682 return makeOlePayload( cfb, cfb.size() );
688 TEMP_TEST_FILE(
const wxString& aFileName,
const wxString& aContents ) :
689 m_path( wxFileName( wxFileName::GetTempDir(), aFileName ).GetFullPath() )
691 wxFFile file( m_path, wxS(
"w" ) );
693 if( file.IsOpened() )
694 file.Write( aContents );
697 ~TEMP_TEST_FILE() { wxRemoveFile( m_path ); }
718 std::string
dataPath(
const std::string& aRelPath )
const
739 std::vector<uint8_t> payload = {
'2', 0xF9,
'5',
'V', 0xF9,
'1',
'2',
'V' };
742 BOOST_REQUIRE_EQUAL( names.size(), 2u );
753 BOOST_CHECK( names.empty() );
761 std::vector<uint8_t> payload;
763 auto appendText = [&](
const std::string& aText ) { payload.insert( payload.end(), aText.begin(), aText.end() ); };
764 auto separator = [&]( uint8_t aByte ) { payload.push_back( aByte ); };
766 appendText(
"2835" );
768 appendText(
"SiLabsPN^Value^Voltage" );
770 appendText(
"NVMFS5C680NLT1G^NVMFS5C680NLT1G^60V~2829" );
772 appendText(
"Part Number^Value" );
774 appendText(
"PDS5100H-13^PDS5100~" );
778 BOOST_REQUIRE_EQUAL( updates.size(), 2u );
787 std::vector<uint8_t> payload = {
'1', 0xB0,
'2',
'8',
'3',
'5',
'~',
788 '0', 0xB0,
'2',
'2',
'1',
'2',
'~' };
791 BOOST_REQUIRE_EQUAL( memberships.size(), 2u );
792 BOOST_CHECK( memberships.at( 2835 ) );
793 BOOST_CHECK( !memberships.at( 2212 ) );
799 std::vector<uint8_t> bytes;
800 appendLe32( bytes, 1 );
801 appendLe32( bytes, 1656123 );
802 appendLe32( bytes, 2 );
803 appendLzt( bytes,
"Output Voltage-12V" );
804 appendLzt( bytes,
"Output Voltage-5V" );
805 appendLe32( bytes, 2 );
806 appendLzt( bytes,
"1" );
807 appendLzt( bytes,
"1" );
808 appendLe32( bytes, 2 );
810 for(
const auto& [value, voltage] :
811 { std::pair<std::string, std::string>(
"NVMFS5C680NLT1G",
"60V" ),
812 std::pair<std::string, std::string>(
"SiR422DP-T1",
"40V" ) } )
814 appendLe32( bytes, 2 );
815 appendLzt( bytes,
"Value" );
816 appendLzt( bytes,
"Voltage" );
817 appendLe32( bytes, 2 );
818 appendLzt( bytes, value );
819 appendLzt( bytes, voltage );
822 appendLe32( bytes, 1 );
823 std::vector<char> data( bytes.begin(), bytes.end() );
826 BOOST_CHECK_EQUAL( groups.at(
"Output Voltage-12V" ).at( 1656123 ).at(
"Value" ),
828 BOOST_CHECK_EQUAL( groups.at(
"Output Voltage-5V" ).at( 1656123 ).at(
"Voltage" ),
"40V" );
834 const std::map<int, int>
expected = { { 9, 1 }, { 10, 2 }, { 2, 3 }, { 13, 4 }, { 24, 5 },
835 { 66, 1 }, { 16, 2 }, { 12, 3 }, { 64, 4 } };
837 for(
const auto& [type, depth] :
expected )
840 BOOST_REQUIRE_MESSAGE(
actual,
"type " << type );
852 std::vector<uint8_t> bytes;
853 std::vector<size_t> lengthOffsets;
855 for(
int i = 0; i < 5; ++i )
858 lengthOffsets.push_back( bytes.size() );
859 appendLe32( bytes, 0 );
860 appendLe32( bytes, 0 );
864 appendLe16( bytes, 41 );
866 for(
int i = 0; i < 41; ++i )
868 appendLe32( bytes, 0 );
869 appendLe32( bytes, 0 );
872 bytes.insert( bytes.end(), { 0xFF, 0xE4, 0x5C, 0x39 } );
873 appendLe32( bytes, 0 );
875 for(
size_t offset : lengthOffsets )
876 writeLe32( bytes, offset,
static_cast<uint32_t
>( bytes.size() - offset - 8 ) );
887 std::vector<uint8_t> tooDeep;
889 ORCAD_STREAM tooDeepStream( tooDeep.data(), tooDeep.size() );
894 std::vector<uint8_t> correct;
896 ORCAD_STREAM correctStream( correct.data(), correct.size() );
905 const uint8_t bytes[] = { 1, 2, 3, 4 };
921 std::vector<char> data( 10, 0 );
922 std::map<std::string, ORCAD_SYMBOL_DEF> symbols;
923 std::map<std::string, ORCAD_PACKAGE> packages;
924 std::vector<wxString> warnings;
928 warnings.push_back( aMsg );
931 BOOST_CHECK_NO_THROW(
OrcadParseCache( data, {}, warn, symbols, packages ) );
932 BOOST_CHECK( warnings.empty() );
933 BOOST_CHECK( symbols.empty() );
934 BOOST_CHECK( packages.empty() );
942 std::vector<char> data( 11, 0 );
943 std::map<std::string, ORCAD_SYMBOL_DEF> symbols;
944 std::map<std::string, ORCAD_PACKAGE> packages;
945 std::vector<wxString> warnings;
949 warnings.push_back( aMsg );
952 BOOST_CHECK_NO_THROW(
OrcadParseCache( data, {}, warn, symbols, packages ) );
954 BOOST_CHECK( symbols.empty() );
962 std::vector<uint8_t> bytes;
963 appendLe16( bytes, 0 );
964 appendLe16( bytes, 1 );
965 appendLzt( bytes,
"GROUP" );
966 appendLe16( bytes, 1 );
967 appendLzt( bytes,
"SOURCE.OLB" );
968 appendLe32( bytes, 0 );
969 appendLe32( bytes, 0 );
971 bytes.push_back( 0 );
973 std::vector<char> data( bytes.begin(), bytes.end() );
974 std::map<std::string, ORCAD_SYMBOL_DEF> symbols;
975 std::map<std::string, ORCAD_PACKAGE> packages;
976 std::vector<wxString> warnings;
980 warnings.push_back( aMsg );
983 BOOST_CHECK_NO_THROW(
OrcadParseCache( data, {}, warn, symbols, packages ) );
985 BOOST_CHECK( symbols.empty() );
986 BOOST_CHECK( packages.empty() );
993 BOOST_REQUIRE_EQUAL( legacy.
strings.size(), 2u );
997 BOOST_REQUIRE_EQUAL( modern.
strings.size(), 2u );
1001 std::vector<char> mislabelled = makeLibraryStream( 2, {
"SIZE",
"N/A" } );
1002 mislabelled[32] = 3;
1012 appendLe32( legacy, 24 );
1013 appendLe32( legacy, 0 );
1015 for( uint32_t value : { 10u, 20u, 30u, 40u, 1u, 7u } )
1016 appendLe32( legacy, value );
1018 ORCAD_STREAM legacyStream( legacy.data(), legacy.size() );
1026 std::vector<uint8_t> mismatched = legacy;
1027 mismatched.resize( mismatched.size() + 8, 0 );
1028 writeLe32( mismatched, 2, 25 );
1030 ORCAD_STREAM mismatchedStream( mismatched.data(), mismatched.size() );
1039 size_t lengthOffset = bytes.size();
1040 appendLe32( bytes, 0 );
1041 appendLe32( bytes, 0 );
1043 for( uint32_t value : { 10u, 20u, 30u, 40u, 10u, 20u } )
1044 appendLe32( bytes, value );
1046 appendLe16( bytes, 1 );
1047 appendLe16( bytes, 0 );
1048 appendLzt( bytes,
"NOTE" );
1050 bytes.resize( bytes.size() + 20, 0 );
1051 writeLe32( bytes, lengthOffset,
static_cast<uint32_t
>( bytes.size() - 2 - 8 ) );
1066 appendLe32( bytes, 32 );
1067 appendLe32( bytes, 0 );
1068 appendLe32( bytes, 10 );
1069 appendLe32( bytes, 20 );
1070 appendLe32( bytes, 30 );
1071 appendLe32( bytes, 40 );
1072 appendLe32( bytes, 1 );
1073 appendLe32( bytes, 2 );
1086 std::vector<uint8_t> bytes;
1087 appendLzt( bytes,
"JMB582QH.Normal" );
1088 appendLzt( bytes,
"IC.OLB" );
1089 appendLe32( bytes, 48 );
1090 appendLe16( bytes, 0 );
1092 for(
int coordinate : { 0, 0, 100, 100 } )
1093 appendLe16( bytes,
static_cast<uint16_t
>( coordinate ) );
1095 size_t bboxEnd = bytes.size();
1096 appendLe16( bytes, 0 );
1097 appendLe16( bytes, 0 );
1100 size_t tailStart = bytes.size();
1101 appendLzt( bytes,
"JMB582" );
1102 appendLzt( bytes,
"" );
1103 appendLzt( bytes,
"U" );
1104 appendLzt( bytes,
"JMB582QH" );
1105 appendLe16( bytes, 3 );
1111 prefixes.
stops = { bytes.size(), tailStart, bboxEnd };
1112 prefixes.
end = bytes.size();
1123 auto framed = []( uint8_t aType,
const std::vector<uint8_t>& aBody )
1125 std::vector<uint8_t> bytes;
1126 std::vector<size_t> lengthOffsets;
1128 for(
int i = 0; i < 2; ++i )
1130 bytes.push_back( aType );
1131 lengthOffsets.push_back( bytes.size() );
1132 appendLe32( bytes, 0 );
1133 appendLe32( bytes, 0 );
1136 bytes.push_back( aType );
1137 appendLe16( bytes, 0xFFFF );
1138 bytes.insert( bytes.end(), { 0xFF, 0xE4, 0x5C, 0x39 } );
1139 appendLe32( bytes, 0 );
1140 bytes.insert( bytes.end(), aBody.begin(), aBody.end() );
1142 for(
size_t offset : lengthOffsets )
1143 writeLe32( bytes, offset,
static_cast<uint32_t
>( bytes.size() - offset - 8 ) );
1148 std::vector<uint8_t> displayBody;
1149 appendLe32( displayBody, 0 );
1150 appendLe16( displayBody, 20 );
1151 appendLe16( displayBody, 0 );
1152 appendLe16( displayBody, 0 );
1153 displayBody.push_back( 48 );
1154 appendLe16( displayBody, 0x01E9 );
1155 displayBody.push_back( 0 );
1158 std::vector<uint8_t> pinBody;
1159 appendLzt( pinBody,
"F1" );
1161 for(
int coordinate : { 20, 0, 20, -10 } )
1162 appendLe32( pinBody,
static_cast<uint32_t
>( coordinate ) );
1164 appendLe16( pinBody, 0x21 );
1165 appendLe16( pinBody, 0 );
1168 pinBody.insert( pinBody.end(), 3, 0 );
1169 appendLe16( pinBody, 1 );
1170 pinBody.insert( pinBody.end(), display.begin(), display.end() );
1172 std::vector<std::string> strings = {
"Pin Name" };
1178 BOOST_REQUIRE_EQUAL(
pin->displayProps.size(), 1u );
1187 std::vector<uint8_t> bytes;
1188 appendLe32( bytes, 6 );
1189 appendLe32( bytes, 10 );
1190 appendLe32( bytes, 20 );
1191 appendLe32( bytes, 30 );
1192 appendLe32( bytes, 40 );
1193 appendLe32( bytes, 0 );
1194 appendLe32( bytes, 0 );
1211 std::vector<uint8_t> cache;
1212 appendLe16( cache, 0 );
1213 appendLe16( cache, 0 );
1214 appendLe16( cache, 1 );
1215 appendLzt( cache,
"THERMISTOR_2.Normal" );
1216 appendLe16( cache, 2 );
1217 appendLzt( cache,
"SOURCE.OLB" );
1218 appendLe32( cache, 0 );
1219 appendLe32( cache, 0 );
1221 cache.push_back( 0 );
1223 appendLe16( cache, 0 );
1224 appendLzt( cache,
"THERMISTOR_2.Normal" );
1225 appendLzt( cache,
"SOURCE.OLB" );
1226 appendLe32( cache, 48 );
1227 appendLe16( cache, 1 );
1230 for(
int coordinate : { 12, -8, 30, 7, 12, -8 } )
1231 appendLe32( cache,
static_cast<uint32_t
>( coordinate ) );
1233 appendLe16( cache, 27 );
1234 appendLe16( cache, 0 );
1235 appendLzt( cache,
"t" );
1237 for(
int coordinate : { 0, 0, 20, 30 } )
1238 appendLe16( cache,
static_cast<uint16_t
>( coordinate ) );
1240 appendLe16( cache, 0 );
1241 appendLe16( cache, 0 );
1242 appendLzt( cache,
"" );
1243 appendLzt( cache,
"" );
1244 appendLzt( cache,
"Q" );
1245 appendLzt( cache,
"" );
1246 appendLe16( cache, 6 );
1250 appendLzt( cache,
"SOURCE.OLB" );
1251 appendLe32( cache, 0 );
1252 appendLe32( cache, 0 );
1254 cache.push_back( 0 );
1256 appendLe16( cache, 0 );
1257 appendLzt( cache,
"THERMISTOR_2.Normal" );
1258 appendLzt( cache,
"SOURCE.OLB" );
1259 appendLe32( cache, 48 );
1260 appendLe16( cache, 0 );
1262 for(
int coordinate : { 0, 0, 30, 30 } )
1263 appendLe16( cache,
static_cast<uint16_t
>( coordinate ) );
1265 appendLe16( cache, 0 );
1266 appendLe16( cache, 0 );
1267 appendLzt( cache,
"" );
1268 appendLzt( cache,
"" );
1269 appendLzt( cache,
"Q" );
1270 appendLzt( cache,
"" );
1271 appendLe16( cache, 6 );
1273 appendLe16( cache, 0 );
1274 appendLe16( cache, 0 );
1276 std::map<std::string, ORCAD_SYMBOL_DEF> symbols;
1277 std::map<std::string, ORCAD_PACKAGE> packages;
1279 std::vector<char>( cache.begin(), cache.end() ), {},
1280 [](
const wxString& )
1283 symbols, packages );
1285 BOOST_REQUIRE_EQUAL( symbols.size(), 1u );
1286 BOOST_REQUIRE_EQUAL( symbols.begin()->second.primitives.size(), 1u );
1293 BOOST_REQUIRE_EQUAL( symbols.begin()->second.variants.size(), 1u );
1316 BOOST_CHECK( !
pin.IsNoConnect() );
1319 BOOST_CHECK(
pin.IsNoConnect() );
1327 "Sch 2: PCI Connector" );
1355 constexpr uint32_t legacyModified = 0x56A2631C;
1356 constexpr uint32_t currentModified = 0x652CEBA8;
1367 BOOST_CHECK_GT( reverseDiagonal.size(), 40u );
1368 BOOST_CHECK_LT( reverseDiagonal.size(), 48u );
1369 BOOST_CHECK( std::all_of( reverseDiagonal.begin(), reverseDiagonal.end(),
1370 [](
const SEG& aLine )
1372 return static_cast<int64_t>( aLine.B.x - aLine.A.x )
1373 * ( aLine.B.y - aLine.A.y )
1378 BOOST_CHECK_GT( diagonalCross.size(), 80u );
1379 BOOST_CHECK_LT( diagonalCross.size(), 96u );
1382 BOOST_CHECK_GT( orthogonalCross.size(), 40u );
1383 BOOST_CHECK_LT( orthogonalCross.size(), 48u );
1384 BOOST_CHECK( std::any_of( orthogonalCross.begin(), orthogonalCross.end(),
1385 [](
const SEG& aLine ) { return aLine.A.x == aLine.B.x; } ) );
1386 BOOST_CHECK( std::any_of( orthogonalCross.begin(), orthogonalCross.end(),
1387 [](
const SEG& aLine ) { return aLine.A.y == aLine.B.y; } ) );
1390 BOOST_CHECK_GT( currentCross.size(), 20u );
1391 BOOST_CHECK_LT( currentCross.size(), 40u );
1397 wxString dashed = wxS(
"03 - CAN" );
1398 wxString dotted = wxS(
"02.uC" );
1399 wxString colon = wxS(
"13:IMU" );
1400 wxString folder = wxS(
"Sch 7: CAN Drivers" );
1401 wxString pager = wxS(
"PAGER 8" );
1402 wxString underscored = wxS(
"PAGE_03_HSMC CONNECTOR" );
1403 wxString compact = wxS(
"PAGE01 OVERALL BLOCK DIAGRAM" );
1404 wxString plain = wxS(
"Overview" );
1427 std::vector<uint8_t> bytes;
1429 appendLzt( bytes,
"SCHEMATIC1" );
1430 appendLe32( bytes, 0 );
1431 appendLe16( bytes, 3 );
1432 appendLzt( bytes,
"Block Diagram" );
1433 appendLzt( bytes,
"I2C-USB" );
1434 appendLzt( bytes,
"Street Fighter" );
1436 std::vector<char> stream( bytes.begin(), bytes.end() );
1439 BOOST_REQUIRE_EQUAL( pages.size(), 3u );
1449 appendLzt( bytes,
"Low Power" );
1450 appendLe32( bytes, 0 );
1451 appendLe16( bytes, 3 );
1452 appendLzt( bytes,
"Pre Regulator 100V" );
1453 appendLzt( bytes,
"ZVS Flyback" );
1454 appendLzt( bytes,
"Pre Regulator 12V" );
1456 std::vector<char> stream( bytes.begin(), bytes.end() );
1459 BOOST_REQUIRE_EQUAL( pages.size(), 3u );
1468 auto appendPrefix = []( std::vector<uint8_t>& aBytes, uint8_t aType )
1470 aBytes.push_back( aType );
1471 appendLe16( aBytes, 0 );
1473 auto appendEmptyScope = []( std::vector<uint8_t>& aBytes )
1475 appendLe16( aBytes, 0 );
1476 appendLe16( aBytes, 0 );
1477 appendLe16( aBytes, 0 );
1480 std::vector<uint8_t> bytes;
1481 appendLzt( bytes,
"SCHEMATIC1" );
1482 bytes.insert( bytes.end(), 5, 0 );
1483 appendLe16( bytes, 0 );
1484 appendLe16( bytes, 0 );
1485 appendLe16( bytes, 0 );
1486 appendLe16( bytes, 2 );
1488 appendPrefix( bytes, 0x42 );
1489 appendLe32( bytes, 0x12345678 );
1490 appendLe32( bytes, 0x00001234 );
1491 appendLzt( bytes,
"" );
1492 appendLzt( bytes,
"C1" );
1493 appendLe16( bytes, 0xFFFF );
1494 appendLe16( bytes, 0 );
1495 appendEmptyScope( bytes );
1497 appendPrefix( bytes, 0x42 );
1498 appendLe32( bytes, 0x87654321 );
1499 appendLe32( bytes, 0x00004321 );
1500 appendLzt( bytes,
"CHILD" );
1501 appendLzt( bytes,
"" );
1502 appendLe16( bytes, 0xFFFF );
1503 appendLe16( bytes, 0 );
1504 appendLe16( bytes, 0 );
1505 appendLe16( bytes, 0 );
1506 appendLe16( bytes, 1 );
1507 appendPrefix( bytes, 0x42 );
1508 appendLe32( bytes, 0xABCDEF01 );
1509 appendLe32( bytes, 0x00005678 );
1510 appendLzt( bytes,
"" );
1511 appendLzt( bytes,
"R1" );
1512 appendLe16( bytes, 0xFFFF );
1513 appendLe16( bytes, 0 );
1514 appendEmptyScope( bytes );
1516 std::vector<char> stream( bytes.begin(), bytes.end() );
1519 BOOST_REQUIRE_EQUAL( root.
partRefs.size(), 1u );
1521 BOOST_REQUIRE_EQUAL( root.
blocks.size(), 1u );
1523 BOOST_REQUIRE_EQUAL( root.
blocks[0].scope.partRefs.size(), 1u );
1530 auto appendPrefix = []( std::vector<uint8_t>& aBytes, uint8_t aType,
1531 const std::vector<std::pair<uint16_t, uint16_t>>& aProperties )
1533 aBytes.push_back( aType );
1534 appendLe16( aBytes,
static_cast<uint16_t
>( aProperties.size() ) );
1536 for(
const auto& [
name, value] : aProperties )
1538 appendLe16( aBytes,
name );
1539 appendLe16( aBytes, value );
1543 std::vector<uint8_t> bytes;
1544 appendLzt( bytes,
"SCHEMATIC1" );
1545 bytes.insert( bytes.end(), 5, 0 );
1546 appendLe16( bytes, 0 );
1547 appendLe16( bytes, 0 );
1548 appendLe16( bytes, 0 );
1549 appendLe16( bytes, 1 );
1551 appendPrefix( bytes, 0x42, { { 0, 1 }, { 2, 3 }, { 4, 0xFFFF } } );
1552 appendLe32( bytes, 0x12345678 );
1553 appendLe32( bytes, 0x00001234 );
1554 appendLzt( bytes,
"" );
1555 appendLzt( bytes,
"" );
1556 appendLe16( bytes, 0xFFFF );
1557 appendLe16( bytes, 0 );
1558 appendLe16( bytes, 0 );
1559 appendLe16( bytes, 0 );
1560 appendLe16( bytes, 0 );
1562 std::vector<std::string> strings = {
"Value",
"434 123 050 816",
"Manufacturer",
1563 "Wurth Electronics Inc",
"Clear Me" };
1564 std::vector<char> stream( bytes.begin(), bytes.end() );
1567 BOOST_CHECK( root.
partRefs.empty() );
1568 BOOST_REQUIRE_EQUAL( root.
partProps.size(), 1u );
1577 std::vector<uint8_t> bytes;
1578 bytes.push_back( 0x42 );
1579 size_t rootLengthOffset = bytes.size();
1580 appendLe32( bytes, 0 );
1581 appendLe32( bytes, 0 );
1582 appendLzt( bytes,
"SCHEMATIC1" );
1583 bytes.insert( bytes.end(), 7, 0 );
1584 appendLe16( bytes, 0 );
1585 appendLe16( bytes, 0 );
1586 appendLe16( bytes, 0 );
1587 appendLe32( bytes, 0 );
1588 appendLe16( bytes, 1 );
1590 size_t occurrenceStart = bytes.size();
1591 bytes.push_back( 0x42 );
1592 size_t occurrenceLengthOffset = bytes.size();
1593 appendLe32( bytes, 0 );
1594 appendLe32( bytes, 0 );
1595 bytes.push_back( 0x42 );
1596 appendLe16( bytes, 3 );
1597 appendLe32( bytes, 0 );
1598 appendLe32( bytes, 1 );
1599 appendLe32( bytes, 2 );
1600 appendLe32( bytes, 3 );
1601 appendLe32( bytes, 4 );
1602 appendLe32( bytes, 0xFFFFFFFF );
1603 bytes.insert( bytes.end(), { 0xFF, 0xE4, 0x5C, 0x39 } );
1604 appendLe32( bytes, 0 );
1605 appendLe32( bytes, 0x12345678 );
1606 appendLe32( bytes, 0x00001234 );
1607 bytes.push_back( 0x42 );
1608 appendLe32( bytes, 0 );
1609 appendLe32( bytes, 0 );
1610 appendLzt( bytes,
"" );
1611 appendLzt( bytes,
"" );
1612 appendLe32( bytes, 0xFFFFFFFF );
1613 appendLe16( bytes, 0 );
1614 appendLe16( bytes, 0 );
1615 appendLe16( bytes, 0 );
1616 appendLe32( bytes, 0 );
1617 appendLe16( bytes, 0 );
1619 writeLe32( bytes, occurrenceLengthOffset,
1620 static_cast<uint32_t
>( bytes.size() - occurrenceStart - 9 ) );
1621 writeLe32( bytes, rootLengthOffset,
static_cast<uint32_t
>( bytes.size() - 9 ) );
1623 std::vector<std::string> strings = {
"Value",
"434 123 050 816",
"Manufacturer",
1624 "Wurth Electronics Inc",
"Clear Me" };
1625 std::vector<char> stream( bytes.begin(), bytes.end() );
1628 BOOST_CHECK( root.
partRefs.empty() );
1629 BOOST_REQUIRE_EQUAL( root.
partProps.size(), 1u );
1638 std::vector<uint8_t> bytes;
1639 bytes.push_back( 0x42 );
1640 size_t rootLengthOffset = bytes.size();
1641 appendLe32( bytes, 0 );
1642 appendLe32( bytes, 0 );
1643 appendLzt( bytes,
"SCHEMATIC1" );
1644 bytes.insert( bytes.end(), 7, 0 );
1645 appendLe16( bytes, 0 );
1646 appendLe16( bytes, 0 );
1647 appendLe16( bytes, 0 );
1648 appendLe32( bytes, 0 );
1649 appendLe16( bytes, 1 );
1651 size_t occurrenceStart = bytes.size();
1652 bytes.push_back( 0x42 );
1653 size_t occurrenceLengthOffset = bytes.size();
1654 appendLe32( bytes, 0 );
1655 appendLe32( bytes, 0 );
1656 bytes.push_back( 0x42 );
1657 appendLe16( bytes, 0 );
1658 bytes.insert( bytes.end(), { 0xFF, 0xE4, 0x5C, 0x39 } );
1659 appendLe32( bytes, 0 );
1660 appendLe32( bytes, 0x12345678 );
1661 appendLe32( bytes, 0x0000BEEF );
1662 bytes.push_back( 0x42 );
1663 appendLe32( bytes, 0 );
1664 appendLe32( bytes, 0 );
1665 appendLzt( bytes,
"PAG_2" );
1666 appendLzt( bytes,
"" );
1667 appendLe32( bytes, 0xFFFFFFFF );
1668 appendLe16( bytes, 0 );
1669 appendLe16( bytes, 0 );
1670 appendLe16( bytes, 0 );
1671 appendLe32( bytes, 0 );
1672 appendLe16( bytes, 0 );
1674 writeLe32( bytes, occurrenceLengthOffset,
static_cast<uint32_t
>( bytes.size() - occurrenceStart - 9 ) );
1675 writeLe32( bytes, rootLengthOffset,
static_cast<uint32_t
>( bytes.size() - 9 ) );
1677 std::vector<char> stream( bytes.begin(), bytes.end() );
1680 BOOST_REQUIRE_EQUAL( root.
blocks.size(), 1u );
1688 std::vector<uint8_t> bytes;
1690 appendLe16( bytes, 1 );
1691 appendLe16( bytes, 0 );
1692 appendLe16( bytes, 1 );
1693 appendLzt( bytes,
"TITLEBLK" );
1694 appendLzt( bytes,
"" );
1695 appendLe32( bytes, 0 );
1696 appendLe16( bytes, 0 );
1697 appendLe16( bytes, 0 );
1698 appendLe16( bytes, 0 );
1699 appendLe16( bytes, 100 );
1700 appendLe16( bytes, 50 );
1701 appendLe16( bytes, 0 );
1702 appendLe16( bytes, 0 );
1704 std::map<std::string, ORCAD_SYMBOL_DEF> symbols;
1707 BOOST_REQUIRE_EQUAL( symbols.size(), 1u );
1714 std::vector<uint8_t> bytes;
1715 appendLe32( bytes, 0x5351BBF2 );
1716 appendLe16( bytes, 2 );
1718 for(
const std::string&
name : {
"DC1987A",
"SCHEMATIC1" } )
1720 appendLzt( bytes,
name );
1721 appendLe16( bytes, 9 );
1722 bytes.insert( bytes.end(), 20, 0 );
1725 std::vector<char> stream( bytes.begin(), bytes.end() );
1728 BOOST_REQUIRE_EQUAL( folders.size(), 2u );
1737 appendLe32( bytes, 40 );
1738 appendLe32( bytes, 0 );
1739 appendLe32( bytes, 10 );
1740 appendLe32( bytes, 20 );
1741 appendLe32( bytes, 30 );
1742 appendLe32( bytes, 40 );
1743 appendLe32( bytes, 2 );
1744 appendLe32( bytes, 3 );
1745 appendLe32( bytes, 2 );
1746 appendLe32( bytes, 5 );
1761 std::vector<uint8_t> bytes( 32, 0 );
1762 const std::string introduction =
"OrCAD Windows Design";
1763 std::copy( introduction.begin(), introduction.end(), bytes.begin() );
1764 appendLe16( bytes, 3 );
1765 appendLe16( bytes, 2 );
1766 bytes.resize( bytes.size() + 12, 0 );
1767 appendLe16( bytes, 3 );
1769 for(
int height : { -9, -12 } )
1771 size_t offset = bytes.size();
1772 bytes.resize( offset + 60, 0 );
1773 writeLe32( bytes, offset,
static_cast<uint32_t
>( height ) );
1774 writeLe32( bytes, offset + 8, height == -9 ? 900 : 0 );
1775 writeLe32( bytes, offset + 12, height == -9 ? 0 : 1800 );
1776 std::copy_n(
"Arial", 5, bytes.begin() + offset + 28 );
1779 appendLe16( bytes, 24 );
1781 for(
int i = 0; i < 24; ++i )
1782 appendLe16( bytes, i == 10 ? 1 : i == 11 ? 2 : 0 );
1784 bytes.resize( bytes.size() + 8, 0 );
1786 for(
int i = 0; i < 8; ++i )
1787 appendLzt( bytes,
"" );
1789 bytes.resize( bytes.size() + 156, 0 );
1790 appendLe32( bytes, 0 );
1791 appendLe16( bytes, 0 );
1793 writeLe32( bytes, 36, 0x53A88A14 );
1794 writeLe32( bytes, 40, 0x56A2631C );
1797 BOOST_REQUIRE_EQUAL(
library.templateFonts.size(), 24u );
1802 BOOST_REQUIRE_EQUAL(
library.fonts.size(), 2u );
1814 std::vector<uint8_t> bytes( 156, 0 );
1815 writeLe32( bytes, 24, 9700 );
1816 writeLe32( bytes, 28, 7200 );
1817 writeLe32( bytes, 32, 100 );
1818 writeLe16( bytes, 38, 5 );
1819 writeLe16( bytes, 40, 4 );
1820 writeLe32( bytes, 44, 100 );
1821 writeLe32( bytes, 48, 100 );
1822 writeLe32( bytes, 112, 1 );
1824 for(
size_t offset = 128; offset < 156; offset += 4 )
1825 writeLe32( bytes, offset, 1 );
1848 appendLe32( bytes, 34 );
1849 appendLe32( bytes, 0 );
1850 appendLe32( bytes, 1 );
1851 appendLe32( bytes, 2 );
1852 appendLe32( bytes, 2 );
1853 appendLe32( bytes, 4 );
1854 appendLe16( bytes, 2 );
1855 appendLe16( bytes, 20 );
1856 appendLe16( bytes, 10 );
1857 appendLe16( bytes, 40 );
1858 appendLe16( bytes, 30 );
1868 BOOST_REQUIRE_EQUAL( primitive->points.size(), 2u );
1869 BOOST_CHECK( ( primitive->points[0] ==
ORCAD_POINT{ 10, 20 } ) );
1870 BOOST_CHECK( ( primitive->points[1] ==
ORCAD_POINT{ 30, 40 } ) );
1877 appendLe32( bytes, 63 );
1878 appendLe32( bytes, 0 );
1880 appendLe16( bytes, 0 );
1882 appendLe32( bytes, 0 );
1883 appendLe16( bytes, 12 );
1884 appendLe16( bytes, 26 );
1885 appendLe16( bytes, 1 );
1886 bytes.insert( bytes.end(), { ORCAD_PRIM_POLYLINE, 0, ORCAD_PRIM_POLYLINE } );
1887 appendLe32( bytes, 30 );
1888 appendLe32( bytes, 0 );
1889 appendLe32( bytes, 0 );
1890 appendLe32( bytes, 0 );
1891 appendLe16( bytes, 3 );
1892 appendLe16( bytes, 8 );
1893 appendLe16( bytes, 4 );
1894 appendLe16( bytes, 0 );
1895 appendLe16( bytes, 4 );
1896 appendLe16( bytes, 0 );
1897 appendLe16( bytes, 16 );
1898 appendLe16( bytes, 10 );
1899 bytes.insert( bytes.end(), {
'H',
'y',
's',
't',
'e',
'r',
'e',
's',
'i',
's', 0 } );
1908 BOOST_REQUIRE_EQUAL( primitive->children.size(), 1u );
1910 BOOST_REQUIRE_EQUAL( primitive->children[0].points.size(), 3u );
1911 BOOST_CHECK( ( primitive->children[0].points[2] ==
ORCAD_POINT{ 16, 0 } ) );
1917 std::vector<uint8_t> presentation( 4096, 0 );
1918 writeLe32( presentation, 4, 14 );
1919 presentation[40] = 1;
1920 presentation[41] = 0;
1921 presentation[42] = 9;
1922 presentation[43] = 0;
1924 std::vector<uint16_t>
name = { 2,
'O',
'l',
'e',
'P',
'r',
'e',
's',
'0',
'0',
'0', 0 };
1925 std::vector<uint8_t> cfb = makeOlePreviewCfb(
name, presentation );
1929 BOOST_REQUIRE_EQUAL( preview.
data.size(), presentation.size() - 40 );
1937 std::vector<uint8_t> presentation( 4096, 0 );
1938 writeLe32( presentation, 4, 14 );
1939 presentation[40] = 1;
1940 presentation[42] = 9;
1942 std::vector<uint16_t>
name = { 2,
'O',
'l',
'e',
'P',
'r',
'e',
's',
'0',
'0',
'0', 0 };
1943 std::vector<uint8_t> cfb = makeOlePreviewCfb(
name, presentation );
1944 uint32_t declared =
static_cast<uint32_t
>( cfb.size() );
1945 cfb.resize( cfb.size() - 200 );
1950 BOOST_REQUIRE_EQUAL( preview.
data.size(), presentation.size() - 40 );
1960 std::vector<uint8_t> native( 4096, 0 );
1961 writeLe32( native, 0,
static_cast<uint32_t
>( native.size() - 4 ) );
1964 writeLe32( native, 6, 58 );
1966 std::vector<uint16_t>
name = { 1,
'O',
'l',
'e',
'1',
'0',
'N',
'a',
't',
'i',
'v',
'e', 0 };
1967 std::vector<uint8_t> cfb = makeOlePreviewCfb(
name, native );
1971 BOOST_REQUIRE_EQUAL( preview.
data.size(), native.size() - 4 );
1975 for(
const std::vector<uint8_t>& signature :
1976 { std::vector<uint8_t>{ 0x89,
'P',
'N',
'G' }, std::vector<uint8_t>{ 0xFF, 0xD8, 0xFF } } )
1978 std::copy( signature.begin(), signature.end(), native.begin() + 4 );
1979 cfb = makeOlePreviewCfb(
name, native );
1990 std::vector<uint8_t> contents( 4096, 0 );
1993 writeLe32( contents, 2, 58 );
1995 std::vector<uint16_t>
name = {
'C',
'O',
'N',
'T',
'E',
'N',
'T',
'S', 0 };
2000 BOOST_REQUIRE_EQUAL(
image.data.size(), contents.size() );
2009 constexpr size_t SECTOR_SIZE = 512;
2010 constexpr size_t RIGHT_SIBLING_OFFSET = 72;
2012 std::vector<uint16_t>
name = {
'C',
'O',
'N',
'T',
'E',
'N',
'T',
'S', 0 };
2013 std::vector<uint8_t> contents( 64, 0 );
2018 std::vector<uint8_t> cfb = makeOlePreviewCfb(
name, contents );
2021 const size_t streamEntry = 2 * SECTOR_SIZE + 128;
2023 writeLe32( cfb, streamEntry + RIGHT_SIBLING_OFFSET, 1 );
2036 std::vector<uint16_t>
name = {
'C',
'O',
'N',
'T',
'E',
'N',
'T',
'S', 0 };
2037 std::vector<uint8_t> contents( 64, 0 );
2039 writeLe32( contents, 0, 40 );
2040 writeLe32( contents, 4, 16 );
2041 writeLe32( contents, 8, 16 );
2042 writeLe16( contents, 12, 7 );
2043 writeLe16( contents, 14, 24 );
2055 std::vector<uint8_t> payload( 40 + 2 * 4 + 8 * 15, 0 );
2056 writeLe32( payload, 0, 40 );
2057 writeLe32( payload, 4, 55 );
2058 writeLe32( payload, 8, 15 );
2059 writeLe16( payload, 12, 1 );
2060 writeLe16( payload, 14, 1 );
2062 const std::string marker =
"~~CI_IMAGE~~";
2063 payload.insert( payload.end(), marker.begin(), marker.end() );
2064 payload.insert( payload.end(), { 0, 2,
'1',
'1' } );
2066 const std::vector<uint8_t> png = { 0x89,
'P',
'N',
'G', 0x0D, 0x0A, 0x1A, 0x0A, 1, 2, 3 };
2067 payload.insert( payload.end(), png.begin(), png.end() );
2071 payload.resize( 40 );
2074 writeLe32( payload, 4, 0x7FFFFFFF );
2075 writeLe32( payload, 8, 0x80000000 );
2076 writeLe16( payload, 14, 32 );
2083 std::vector<uint8_t> payload;
2084 constexpr char marker[] =
"~~CI_IMAGE~~";
2085 payload.insert( payload.end(), marker, marker +
sizeof( marker ) - 1 );
2086 payload.insert( payload.end(), { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 } );
2087 payload.insert( payload.end(), { 0x89,
'P',
'N',
'G', 0x0D, 0x0A, 0x1A, 0x0A } );
2115 const unsigned char* pixels =
image.GetData();
2116 size_t nonWhite = 0;
2118 for(
size_t i = 0; i < static_cast<size_t>(
image.GetWidth() ) *
image.GetHeight(); ++i )
2120 if( pixels[3 * i] != 255 || pixels[3 * i + 1] != 255 || pixels[3 * i + 2] != 255 )
2124 BOOST_CHECK_GT( nonWhite, 0u );
2133 BOOST_CHECK_LE(
image.GetWidth(), 200 );
2134 BOOST_CHECK_LE(
image.GetHeight(), 200 );
2135 BOOST_CHECK_GE(
image.GetWidth(), 50 );
2136 BOOST_CHECK_GE(
image.GetHeight(), 50 );
2139 const int top =
image.GetHeight() / 4;
2140 const int bottom =
image.GetHeight() * 3 / 4;
2143 const int bottomRed =
image.GetRed(
left, bottom );
2144 const int bottomBlue =
image.GetBlue(
left, bottom );
2146 BOOST_CHECK_GT( topRed, topBlue + 50 );
2147 BOOST_CHECK_GT( bottomBlue, bottomRed + 50 );
2155 BOOST_REQUIRE_EQUAL( emf.size(), 100u );
2168 std::vector<uint8_t> emf = makeRenderableEmf();
2172 BOOST_REQUIRE_EQUAL( first.GetWidth(), 100 );
2173 BOOST_REQUIRE_EQUAL( first.GetHeight(), 100 );
2174 BOOST_REQUIRE_EQUAL( second.GetWidth(), first.GetWidth() );
2175 BOOST_REQUIRE_EQUAL( second.GetHeight(), first.GetHeight() );
2177 size_t nonWhite = 0;
2179 size_t byteCount =
static_cast<size_t>( first.GetWidth() ) * first.GetHeight() * 3;
2181 for(
size_t i = 0; i < byteCount; i += 3 )
2183 const unsigned char* pixel = first.GetData() + i;
2185 if( pixel[0] != 255 || pixel[1] != 255 || pixel[2] != 255 )
2188 if( pixel[2] > pixel[0] + 64 && pixel[2] > pixel[1] + 64 )
2192 BOOST_CHECK_GT( nonWhite, 50u );
2193 BOOST_CHECK_GT(
blue, 10u );
2195 second.GetData() + byteCount );
2197 for(
int y = 30; y < 36; ++y )
2199 for(
int x = 70; x < 84; ++x )
2201 BOOST_CHECK_MESSAGE( first.GetBlue( x, y ) < 160 || first.GetRed( x, y ) > 160,
2202 "glyph-index trademark descends below its baseline at " << x <<
',' << y );
2206 size_t wideGlyphPixels = 0;
2208 for(
int y = 15; y < 26; ++y )
2210 for(
int x = 77; x < 84; ++x )
2212 if( first.GetBlue( x, y ) > first.GetRed( x, y ) + 64 )
2217 BOOST_CHECK_GT( wideGlyphPixels, 2u );
2219 size_t substitutedSpacePixels = 0;
2221 for(
int y = 70; y < 100; ++y )
2223 for(
int x = 0; x < 25; ++x )
2225 if( first.GetBlue( x, y ) > first.GetRed( x, y ) + 64 )
2226 ++substitutedSpacePixels;
2236 std::vector<uint8_t> emf = makeRenderableEmf();
2238 writeLe32( emf, 48, emf.size() );
2239 writeLe32( emf, 52, 3 );
2240 writeLe32( emf, 108, 35 );
2241 writeLe32( emf, 112, 8 );
2242 writeLe32( emf, 116, 14 );
2243 writeLe32( emf, 120, 20 );
2244 std::fill( emf.begin() + 124, emf.end(), 0 );
2249 writeLe32( emf, 108, 27 );
2252 writeLe32( emf, 112, 256 );
2263 size_t nonWhite = 0;
2265 for(
int y = 0; y <
image.GetHeight(); ++y )
2267 for(
int x = 0; x <
image.GetWidth(); ++x )
2269 if(
image.GetRed( x, y ) != 255 ||
image.GetGreen( x, y ) != 255 ||
image.GetBlue( x, y ) != 255 )
2274 BOOST_CHECK_GE( nonWhite, 110u );
2283 BOOST_CHECK(
image.IsOk() );
2289 wxImage directEmfImage;
2292 std::vector<uint8_t> emf = makeRenderableEmf();
2299 size_t byteCount =
static_cast<size_t>( emfImage.GetWidth() ) * emfImage.GetHeight() * 3;
2301 directEmfImage.GetData() + byteCount );
2302 BOOST_CHECK( wmfImage.IsOk() );
2308 const char* emfPath = std::getenv(
"KICAD_ORCAD_EMF" );
2310 if( !emfPath || !*emfPath )
2312 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_EMF not set; skipping external embedded-EMF check." );
2316 std::ifstream input( emfPath, std::ios::binary );
2318 std::vector<uint8_t> emf( std::istreambuf_iterator<char>( input ), {} );
2322 BOOST_CHECK_GT(
image.GetWidth(), 0 );
2323 BOOST_CHECK_GT(
image.GetHeight(), 0 );
2325 if(
const char* outputPath = std::getenv(
"KICAD_ORCAD_EMF_OUTPUT" ) )
2326 BOOST_REQUIRE(
image.SaveFile( wxString::FromUTF8( outputPath ), wxBITMAP_TYPE_PNG ) );
2332 const char* wmfPath = std::getenv(
"KICAD_ORCAD_WMF" );
2334 if( !wmfPath || !*wmfPath )
2340 std::ifstream input( wmfPath, std::ios::binary );
2342 std::vector<uint8_t> wmf( std::istreambuf_iterator<char>( input ), {} );
2345 wxImage directImage;
2350 BOOST_REQUIRE_EQUAL(
image.GetWidth(), directImage.GetWidth() );
2351 BOOST_REQUIRE_EQUAL(
image.GetHeight(), directImage.GetHeight() );
2352 size_t byteCount =
static_cast<size_t>(
image.GetWidth() ) *
image.GetHeight() * 3;
2354 directImage.GetData() + byteCount );
2356 if(
const char* outputPath = std::getenv(
"KICAD_ORCAD_WMF_OUTPUT" ) )
2357 BOOST_REQUIRE(
image.SaveFile( wxString::FromUTF8( outputPath ), wxBITMAP_TYPE_PNG ) );
2363 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
2365 if( !corpusEnv || !*corpusEnv )
2367 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping multi-preview OLE check." );
2371 std::filesystem::path dsn;
2373 for(
const std::filesystem::directory_entry& entry : std::filesystem::recursive_directory_iterator( corpusEnv ) )
2375 if( entry.is_regular_file() && entry.path().filename() ==
"reServer industrial J401 Carrier Board v11.DSN" )
2384 BOOST_TEST_MESSAGE(
"reServer industrial J401 design not present; skipping multi-preview OLE check." );
2388 std::ifstream stream( dsn, std::ios::binary );
2389 std::vector<uint8_t> bytes( std::istreambuf_iterator<char>( stream ), {} );
2390 const std::array<std::array<uint8_t, 8>, 2> markers = {
2391 std::array<uint8_t, 8>{ 0x6A, 0x31, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00 },
2392 std::array<uint8_t, 8>{ 0x16, 0x94, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00 }
2395 for(
size_t markerIndex = 0; markerIndex < markers.size(); ++markerIndex )
2397 const auto& marker = markers[markerIndex];
2398 auto markerPos = std::search( bytes.begin(), bytes.end(), marker.begin(), marker.end() );
2401 size_t offset =
static_cast<size_t>( std::distance( bytes.begin(), markerPos ) );
2402 size_t size =
static_cast<size_t>( bytes[offset] ) | (
static_cast<size_t>( bytes[offset + 1] ) << 8 )
2403 | (
static_cast<size_t>( bytes[offset + 2] ) << 16 )
2404 | (
static_cast<size_t>( bytes[offset + 3] ) << 24 );
2405 BOOST_REQUIRE_LE( offset + size + 4, bytes.size() );
2410 BOOST_CHECK_GT( preview.
data.size(), 200000u );
2414 "marker " << markerIndex <<
", preview bytes " << preview.
data.size() <<
", "
2416 BOOST_CHECK_GT(
image.GetWidth(), 1000 );
2417 BOOST_CHECK_GT(
image.GetHeight(), 500 );
2425 appendLzt( bytes,
"PAGE" );
2426 appendLzt( bytes,
"C" );
2427 bytes.resize( bytes.size() + 156 );
2428 appendLe16( bytes, 0 );
2429 appendLe16( bytes, 0 );
2430 appendLe16( bytes, 1 );
2431 appendLe32( bytes, 0x12345678 );
2432 appendLzt( bytes,
"BUS[1:0]" );
2433 appendLe16( bytes, 2 );
2434 appendLe32( bytes, 0x11111111 );
2435 appendLe32( bytes, 0x22222222 );
2437 for(
int i = 0; i < 10; ++i )
2438 appendLe16( bytes, 0 );
2440 std::vector<char> data( bytes.begin(), bytes.end() );
2442 [](
const wxString& )
2446 BOOST_REQUIRE_EQUAL( page.
netGroups.size(), 1u );
2449 BOOST_REQUIRE_EQUAL( page.
netGroups[0].members.size(), 2u );
2454static std::string
terminalToken(
const std::string& aRef,
const std::string& aPin );
2456 std::vector<std::set<std::string>>* aInconsistent =
nullptr );
2469 converter.
Convert( rootSheet );
2477 page.
name =
"CONNECTED CROSSING";
2485 page.
wires.push_back( horizontal );
2492 page.
wires.push_back( vertical );
2493 page.
netmap.emplace( 1,
"GND_SIGNAL" );
2496 design.
sourceId =
"same-net-interior-crossing";
2497 design.
pages.push_back( std::move( page ) );
2501 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
2502 schematic->SetProject( &manager.
Prj() );
2504 size_t junctionCount = 0;
2516 page.
name =
"OVERSIZED B";
2526 page.
wires.push_back( wire );
2529 design.
sourceId =
"inconsistent-named-page-size";
2530 design.
pages.push_back( std::move( page ) );
2534 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
2535 schematic->SetProject( &manager.
Prj() );
2540 BOOST_CHECK_CLOSE( paper.
GetWidthMils(), 20000.0, 0.001 );
2549 page.
name =
"OUTER BORDER";
2563 design.
pages.push_back( std::move( page ) );
2567 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
2568 schematic->SetProject( &manager.
Prj() );
2583 const std::vector<VECTOR2I> points = border->
GetPolyPoints();
2584 BOOST_REQUIRE_EQUAL( points.size(), 5u );
2589 BOOST_CHECK( points[4] == points[0] );
2592 std::set<wxString> labels;
2595 labels.insert(
static_cast<const SCH_TEXT*
>( item )->GetText() );
2597 for(
const wxString&
expected : { wxS(
"5" ), wxS(
"4" ), wxS(
"3" ), wxS(
"2" ), wxS(
"1" ),
2598 wxS(
"D" ), wxS(
"C" ), wxS(
"B" ), wxS(
"A" ) } )
2600 BOOST_CHECK( labels.count(
expected ) );
2608 definition.
name =
"TITLE";
2610 definition.
props[
"SIZE"] =
"N/A";
2617 titleBlock.
props[
"Title"] =
"Amplifier";
2618 titleBlock.
props[
"Page Number"] =
"7";
2619 titleBlock.
props[
"Page Count"] =
"9";
2620 titleBlock.
props[
"Page Modify Date"] =
"Wednesday, January 25, 2023";
2623 displayedTitle.
name =
"Title";
2624 displayedTitle.
x = 10;
2625 displayedTitle.
y = 20;
2628 displayedTitle.
color = 5;
2632 displayedPageSize.
name =
"SIZE";
2633 displayedPageSize.
x = 30;
2634 displayedPageSize.
y = 40;
2635 displayedPageSize.
dispMode = 0x100;
2636 titleBlock.
displayProps.push_back( displayedPageSize );
2639 displayedDate.
name =
"Page Modify Date";
2640 displayedDate.
x = 40;
2641 displayedDate.
y = 45;
2646 displayedPageNumber.
name =
"Page Number";
2647 displayedPageNumber.
x = 50;
2648 displayedPageNumber.
y = 50;
2649 displayedPageNumber.
dispMode = 0x100;
2650 titleBlock.
displayProps.push_back( displayedPageNumber );
2653 displayedPageCount.
name =
"Page Count";
2654 displayedPageCount.
x = 60;
2655 displayedPageCount.
y = 55;
2656 displayedPageCount.
dispMode = 0x100;
2657 titleBlock.
displayProps.push_back( displayedPageCount );
2660 page.
name =
"SHEET";
2667 page.
titleBlocks.push_back( std::move( titleBlock ) );
2670 design.
sourceId =
"title-block-properties";
2671 design.
symbols.emplace( definition.
name, std::move( definition ) );
2672 design.
pages.push_back( std::move( page ) );
2676 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
2677 schematic->SetProject( &manager.
Prj() );
2681 const SCH_TEXT* pageSize =
nullptr;
2687 title =
static_cast<const SCH_TEXT*
>( item );
2689 pageSize =
static_cast<const SCH_TEXT*
>( item );
2691 &&
static_cast<const SCH_TEXT*
>( item )->
GetText() == wxS(
"Tuesday, January 24, 2023" ) )
2692 date =
static_cast<const SCH_TEXT*
>( item );
2703 std::set<wxString> renderedText;
2708 renderedText.insert(
static_cast<const SCH_TEXT*
>( item )->GetText() );
2711 BOOST_CHECK( renderedText.count( wxS(
"2" ) ) );
2712 BOOST_CHECK( renderedText.count( wxS(
"3" ) ) );
2713 BOOST_CHECK( !renderedText.count( wxS(
"7" ) ) );
2714 BOOST_CHECK( !renderedText.count( wxS(
"9" ) ) );
2715 BOOST_CHECK( !renderedText.count( wxS(
"<Title>" ) ) );
2722 definition.
name =
"TITLE";
2723 definition.
props[
"Title"] =
"<Title>";
2727 titleBlock.
props[
"Title"] =
"";
2730 displayedTitle.
name =
"Title";
2735 page.
name =
"SHEET";
2738 page.
titleBlocks.push_back( std::move( titleBlock ) );
2741 design.
sourceId =
"title-block-placeholder";
2742 design.
symbols.emplace( definition.
name, std::move( definition ) );
2743 design.
pages.push_back( std::move( page ) );
2747 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
2748 schematic->SetProject( &manager.
Prj() );
2754 found |=
static_cast<const SCH_TEXT*
>( item )->GetText() == wxS(
"<Title>" );
2756 BOOST_CHECK( found );
2763 definition.
name =
"TITLE";
2769 displayedDate.
name =
"Schematic Modify Date";
2774 page.
name =
"SHEET";
2778 page.
titleBlocks.push_back( std::move( titleBlock ) );
2781 design.
sourceId =
"schematic-modify-date";
2782 design.
symbols.emplace( definition.
name, std::move( definition ) );
2783 design.
pages.push_back( std::move( page ) );
2787 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
2788 schematic->SetProject( &manager.
Prj() );
2791 std::set<wxString> renderedText;
2794 renderedText.insert(
static_cast<const SCH_TEXT*
>( item )->GetText() );
2796 BOOST_CHECK( renderedText.count( wxS(
"Thursday, February 16, 2023" ) ) );
2797 BOOST_CHECK( !renderedText.count( wxS(
"<Schematic Modify Date>" ) ) );
2804 definition.
name =
"TITLEBLK/Rudy";
2810 displayedDate.
name =
"Page Modify Date";
2815 page.
name =
"SHEET";
2819 page.
titleBlocks.push_back( std::move( titleBlock ) );
2822 design.
sourceId =
"rudy-title-block-date";
2823 design.
symbols.emplace( definition.
name, std::move( definition ) );
2824 design.
pages.push_back( std::move( page ) );
2828 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
2829 schematic->SetProject( &manager.
Prj() );
2832 std::set<wxString> renderedText;
2835 renderedText.insert(
static_cast<const SCH_TEXT*
>( item )->GetText() );
2837 BOOST_CHECK( renderedText.count( wxS(
"Feb 16, 2023" ) ) );
2838 BOOST_CHECK( !renderedText.count( wxS(
"Thursday, February 16, 2023" ) ) );
2845 definition.
name =
"TITLE";
2849 titleBlock.
props[
"Title"] =
"";
2850 titleBlock.
props[
"Doc"] =
"";
2851 titleBlock.
props[
"RevCode"] =
"?";
2853 for(
const std::string&
name : {
"Title",
"Doc",
"RevCode" } )
2862 page.
name =
"SHEET";
2865 page.
titleBlocks.push_back( std::move( titleBlock ) );
2868 design.
sourceId =
"empty-title-block-placeholders";
2869 design.
symbols.emplace( definition.
name, std::move( definition ) );
2870 design.
pages.push_back( std::move( page ) );
2874 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
2875 schematic->SetProject( &manager.
Prj() );
2878 std::set<wxString> renderedText;
2881 renderedText.insert(
static_cast<const SCH_TEXT*
>( item )->GetText() );
2883 BOOST_CHECK( renderedText.count( wxS(
"<Title>" ) ) );
2884 BOOST_CHECK( renderedText.count( wxS(
"<Doc>" ) ) );
2885 BOOST_CHECK( renderedText.count( wxS(
"<RevCode>" ) ) );
2893 revision.
name =
"REVISION";
2895 .text =
"REVISION HISTORY" } );
2900 .text =
"CUSTOMER NOTICE" } );
2903 revisionBlock.
name = revision.
name;
2904 revisionBlock.
props[
"RevCode"] =
"2";
2908 mainBlock.
props[
"Title"] =
"Power Supply";
2911 page.
name =
"SHEET";
2914 page.
titleBlocks.push_back( std::move( revisionBlock ) );
2915 page.
titleBlocks.push_back( std::move( mainBlock ) );
2918 design.
sourceId =
"multiple-title-blocks";
2919 design.
symbols.emplace( revision.
name, std::move( revision ) );
2921 design.
pages.push_back( std::move( page ) );
2925 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
2926 schematic->SetProject( &manager.
Prj() );
2929 std::set<wxString> renderedText;
2932 renderedText.insert(
static_cast<const SCH_TEXT*
>( item )->GetText() );
2934 BOOST_CHECK( renderedText.count( wxS(
"REVISION HISTORY" ) ) );
2935 BOOST_CHECK( renderedText.count( wxS(
"CUSTOMER NOTICE" ) ) );
2942 primary.
name =
"TITLE";
2945 .text =
"PRIMARY" } );
2951 .text =
"MATCHED" } );
2952 primary.
variants.push_back( std::move( matching ) );
2959 page.
name =
"SHEET";
2960 page.
titleBlocks.push_back( std::move( titleBlock ) );
2963 design.
sourceId =
"title-block-variant-bounds";
2964 design.
symbols.emplace( primary.
name, std::move( primary ) );
2965 design.
pages.push_back( std::move( page ) );
2969 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
2970 schematic->SetProject( &manager.
Prj() );
2973 std::set<wxString> renderedText;
2976 renderedText.insert(
static_cast<const SCH_TEXT*
>( item )->GetText() );
2978 BOOST_CHECK( renderedText.count( wxS(
"MATCHED" ) ) );
2979 BOOST_CHECK( !renderedText.count( wxS(
"PRIMARY" ) ) );
2986 definition.
name =
"TITLE";
2999 .text =
"CUSTOMER NOTICE",
3008 page.
name =
"SHEET";
3009 page.
titleBlocks.push_back( std::move( titleBlock ) );
3012 design.
sourceId =
"title-block-vector-text";
3014 design.
symbols.emplace( definition.
name, std::move( definition ) );
3015 design.
pages.push_back( std::move( page ) );
3019 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3020 schematic->SetProject( &manager.
Prj() );
3025 const SCH_TEXT* vectorText =
nullptr;
3028 vectorText =
static_cast<const SCH_TEXT*
>( item );
3043 vectorLine =
static_cast<const SCH_SHAPE*
>( item );
3053 design.
sourceId =
"rotated-page-order";
3055 for(
const std::string&
name : {
"PAGE_02_CONTENT",
"PAGE_03_CONTENT",
"PAGE_01_INDEX" } )
3064 design.
pages.push_back( std::move( page ) );
3069 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3070 schematic->SetProject( &manager.
Prj() );
3073 std::vector<SCH_SHEET*> sheets = schematic->GetTopLevelSheets();
3074 BOOST_REQUIRE_EQUAL( sheets.size(), 3u );
3079 std::map<std::string, size_t> pageNumbers;
3093 design.
sourceId =
"title-block-page-order";
3095 for(
const auto& [
name, pageNumber] : { std::pair{
"SECOND",
"2" }, std::pair{
"FIRST",
"1" } } )
3105 titleBlock.
props[
"Page Number"] = pageNumber;
3106 page.
titleBlocks.push_back( std::move( titleBlock ) );
3107 design.
pages.push_back( std::move( page ) );
3112 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3113 schematic->SetProject( &manager.
Prj() );
3116 std::vector<SCH_SHEET*> sheets = schematic->GetTopLevelSheets();
3117 BOOST_REQUIRE_EQUAL( sheets.size(), 2u );
3129 if( symbol->
GetRef( &aPath,
false ) == aReference )
3141 comment.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3148 page.
name =
"PAGE GRAPHIC ORDER";
3149 page.
graphics.push_back( std::move( comment ) );
3152 design.
sourceId =
"page-graphic-order";
3153 design.
pages.push_back( std::move( page ) );
3157 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3158 schematic->SetProject( &manager.
Prj() );
3161 std::map<wxString, KIID> textUuids;
3166 textUuids.emplace(
text->GetText(),
text->m_Uuid );
3169 BOOST_REQUIRE_EQUAL( textUuids.size(), 2u );
3170 std::string role =
"orcad-import:page-graphic-order:page:0:item:"
3171 + std::to_string(
static_cast<int>(
SCH_TEXT_T ) );
3172 BOOST_CHECK( textUuids.at( wxS(
"SOURCE FIRST" ) ) ==
KIID::FromName( role +
":0" ) );
3173 BOOST_CHECK( textUuids.at( wxS(
"SOURCE SECOND" ) ) ==
KIID::FromName( role +
":1" ) );
3181 comment.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3187 .text =
"PCA ADDITIONAL PARTS",
3192 page.
name =
"BOXED COMMENT";
3193 page.
graphics.push_back( std::move( comment ) );
3198 design.
pages.push_back( std::move( page ) );
3202 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3203 schematic->SetProject( &manager.
Prj() );
3208 const SCH_TEXT* sheetText =
nullptr;
3211 sheetText =
static_cast<const SCH_TEXT*
>( item );
3227 comment.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3233 .text =
"DC590 SPI INTERFACE",
3238 page.
name =
"BOLD NARROW STORED WIDTH";
3239 page.
graphics.push_back( std::move( comment ) );
3242 design.
sourceId =
"bold-narrow-small-overflow";
3244 ORCAD_FONT{ .height = -28, .face =
"Arial Narrow", .bold =
true }
3246 design.
pages.push_back( std::move( page ) );
3250 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3251 schematic->SetProject( &manager.
Prj() );
3254 const SCH_TEXT* sheetText =
nullptr;
3257 sheetText =
static_cast<const SCH_TEXT*
>( item );
3268 comment.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3274 .text =
"1. ALL RESISTORS ARE IN OHMS, 0402",
3279 page.
name =
"BOLD NARROW NOTE";
3280 page.
graphics.push_back( std::move( comment ) );
3283 design.
sourceId =
"bold-narrow-note-small-overflow";
3285 ORCAD_FONT{ .height = -16, .face =
"Arial Narrow", .bold =
true }
3287 design.
pages.push_back( std::move( page ) );
3291 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3292 schematic->SetProject( &manager.
Prj() );
3295 const SCH_TEXT* sheetText =
nullptr;
3298 sheetText =
static_cast<const SCH_TEXT*
>( item );
3309 comment.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3320 page.
name =
"SOURCE-ANCHORED COMMENT";
3323 page.
graphics.push_back( std::move( comment ) );
3326 design.
sourceId =
"source-anchored-comment";
3328 design.
pages.push_back( std::move( page ) );
3332 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3333 schematic->SetProject( &manager.
Prj() );
3336 const SCH_TEXT* sheetText =
nullptr;
3339 sheetText =
static_cast<const SCH_TEXT*
>( item );
3353 comment.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3360 .text =
"*All Test Points are No Load",
3365 page.
name =
"ELEPHANT COMMENT";
3366 page.
graphics.push_back( std::move( comment ) );
3369 design.
sourceId =
"elephant-comment";
3371 design.
pages.push_back( std::move( page ) );
3375 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3376 schematic->SetProject( &manager.
Prj() );
3379 const SCH_TEXT* sheetText =
nullptr;
3382 sheetText =
static_cast<const SCH_TEXT*
>( item );
3399 comment.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3405 .text =
"OPTIONAL COMPONENTS",
3409 page.
name =
"NARROW WRAPPED COMMENT";
3410 page.
graphics.push_back( std::move( comment ) );
3413 design.
sourceId =
"narrow-wrapped-comment";
3415 design.
pages.push_back( std::move( page ) );
3419 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3420 schematic->SetProject( &manager.
Prj() );
3423 const SCH_TEXT* sheetText =
nullptr;
3426 sheetText =
static_cast<const SCH_TEXT*
>( item );
3437 comment.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3443 .text =
"FOR USE WITH DC2321A DUST DEMOBOARD",
3447 page.
name =
"BOLD NARROW SINGLE LINE COMMENT";
3448 page.
graphics.push_back( std::move( comment ) );
3451 design.
sourceId =
"bold-narrow-single-line-comment";
3453 design.
pages.push_back( std::move( page ) );
3457 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3458 schematic->SetProject( &manager.
Prj() );
3461 const SCH_TEXT* sheetText =
nullptr;
3464 sheetText =
static_cast<const SCH_TEXT*
>( item );
3475 comment.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3481 .text =
"NOTE: UNLESS OTHERWISE SPECIFIED",
3485 page.
name =
"WRAPPED COMMENT";
3486 page.
graphics.push_back( std::move( comment ) );
3489 design.
sourceId =
"wrapped-comment";
3491 design.
pages.push_back( std::move( page ) );
3495 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3496 schematic->SetProject( &manager.
Prj() );
3499 const SCH_TEXT* sheetText =
nullptr;
3502 sheetText =
static_cast<const SCH_TEXT*
>( item );
3513 comment.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3523 page.
name =
"SMALL METRIC OVERFLOW";
3524 page.
graphics.push_back( std::move( comment ) );
3527 design.
sourceId =
"small-metric-overflow";
3529 design.
pages.push_back( std::move( page ) );
3533 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3534 schematic->SetProject( &manager.
Prj() );
3537 const SCH_TEXT* sheetText =
nullptr;
3540 sheetText =
static_cast<const SCH_TEXT*
>( item );
3551 comment.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3558 page.
name =
"LEGACY SYMBOL FONTS";
3559 page.
graphics.push_back( std::move( comment ) );
3562 design.
sourceId =
"legacy-symbol-fonts";
3564 ORCAD_FONT{ .height = -13, .face =
"CommercialPi BT" } };
3565 design.
pages.push_back( std::move( page ) );
3569 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3570 schematic->SetProject( &manager.
Prj() );
3573 std::set<wxString> texts;
3576 texts.insert(
static_cast<const SCH_TEXT*
>( item )->GetText() );
3578 BOOST_CHECK( texts.count( wxString::FromUTF8(
"µ" ) ) );
3579 BOOST_CHECK( texts.count( wxString::FromUTF8(
"®" ) ) );
3587 comment.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3594 .text =
"SENZA resistenza di terminazione",
3598 page.
name =
"SINGLE-LINE COMMENT";
3602 page.
graphics.push_back( std::move( comment ) );
3605 design.
sourceId =
"single-line-comment";
3607 design.
pages.push_back( std::move( page ) );
3611 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3612 schematic->SetProject( &manager.
Prj() );
3617 const SCH_TEXT* sheetText =
nullptr;
3620 sheetText =
static_cast<const SCH_TEXT*
>( item );
3633 comment.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3637 .text =
"LARGE TITLE",
3641 page.
name =
"LARGE PAGE TEXT";
3645 page.
graphics.push_back( std::move( comment ) );
3648 design.
sourceId =
"large-page-text";
3650 design.
pages.push_back( std::move( page ) );
3654 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3655 schematic->SetProject( &manager.
Prj() );
3663 title =
static_cast<const SCH_TEXT*
>( item );
3677 comment.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3683 .text =
"POWER SUPPLY REGULATOR",
3687 page.
name =
"FIXED PITCH PAGE TEXT";
3688 page.
graphics.push_back( std::move( comment ) );
3691 design.
sourceId =
"fixed-pitch-page-text";
3693 ORCAD_FONT{ .height = -32, .pitchAndFamily = 0x31, .face =
"Courier New" }
3695 design.
pages.push_back( std::move( page ) );
3699 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3700 schematic->SetProject( &manager.
Prj() );
3708 title =
static_cast<const SCH_TEXT*
>( item );
3720 graphic.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3725 page.
name =
"DEFAULT GRAPHIC COLOR";
3726 page.
graphics.push_back( std::move( graphic ) );
3729 design.
sourceId =
"default-page-graphic-color";
3730 design.
pages.push_back( std::move( page ) );
3734 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3735 schematic->SetProject( &manager.
Prj() );
3738 std::vector<SCH_SHAPE*> shapes;
3741 shapes.push_back(
static_cast<SCH_SHAPE*
>( item ) );
3743 BOOST_REQUIRE_EQUAL( shapes.size(), 1u );
3744 BOOST_CHECK( shapes.front()->GetStroke().GetColor() ==
KIGFX::COLOR4D( 0.0, 0.0, 0.0, 1.0 ) );
3753 graphic.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3759 .data = makeOleWmfPreview(
3760 makeEmbeddedEmfWmf( makeRenderableEmf() ) ) } );
3763 page.
name =
"DEFAULT OLE FRAME COLOR";
3764 page.
graphics.push_back( std::move( graphic ) );
3767 design.
sourceId =
"default-ole-frame-color";
3768 design.
pages.push_back( std::move( page ) );
3772 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3773 schematic->SetProject( &manager.
Prj() );
3777 BOOST_REQUIRE_EQUAL( std::distance( bitmaps.begin(), bitmaps.end() ), 1 );
3779 std::vector<SCH_SHAPE*> shapes;
3782 shapes.push_back(
static_cast<SCH_SHAPE*
>( item ) );
3784 BOOST_REQUIRE_EQUAL( shapes.size(), 1u );
3785 BOOST_CHECK( shapes.front()->GetStroke().GetColor() ==
OrcadColor( 8 ) );
3794 graphic.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3800 .data = makeOleWmfPreview( makeGlyphIndexWmf() ) } );
3803 page.
name =
"DEFAULT OLE FRAME COLOR";
3804 page.
graphics.push_back( std::move( graphic ) );
3807 design.
sourceId =
"default-ole-frame-color";
3808 design.
pages.push_back( std::move( page ) );
3812 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3813 schematic->SetProject( &manager.
Prj() );
3817 BOOST_REQUIRE_EQUAL( std::distance( bitmaps.begin(), bitmaps.end() ), 1 );
3819 std::vector<SCH_SHAPE*> shapes;
3822 shapes.push_back(
static_cast<SCH_SHAPE*
>( item ) );
3824 BOOST_REQUIRE_EQUAL( shapes.size(), 1u );
3825 BOOST_CHECK( shapes.front()->GetStroke().GetColor() ==
KIGFX::COLOR4D( 0.0, 0.0, 0.0, 1.0 ) );
3834 graphic.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3843 page.
name =
"WHITE FILLED GRAPHIC";
3844 page.
graphics.push_back( std::move( graphic ) );
3847 design.
sourceId =
"white-filled-page-graphic";
3848 design.
pages.push_back( std::move( page ) );
3852 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3853 schematic->SetProject( &manager.
Prj() );
3856 std::vector<SCH_SHAPE*> shapes;
3859 shapes.push_back(
static_cast<SCH_SHAPE*
>( item ) );
3861 BOOST_REQUIRE_EQUAL( shapes.size(), 1u );
3863 BOOST_CHECK( shapes.front()->GetStroke().GetColor() ==
KIGFX::COLOR4D( 0.0, 0.0, 0.0, 1.0 ) );
3871 graphic.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3881 page.
name =
"DEGENERATE PAGE ARC";
3882 page.
graphics.push_back( std::move( graphic ) );
3885 design.
sourceId =
"degenerate-page-arc";
3886 design.
pages.push_back( std::move( page ) );
3890 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3891 schematic->SetProject( &manager.
Prj() );
3902 definition.
name =
"MAPPED_FONT.Normal";
3908 placed.
value =
"10nF";
3917 page.
name =
"MAPPED FONT";
3918 page.
instances.push_back( std::move( placed ) );
3919 ORCAD_WIRE wire{ .id = 1, .x1 = 50, .y1 = 50, .x2 = 150, .y2 = 50 };
3920 wire.
aliases.push_back(
ORCAD_ALIAS{ .name =
"FONT_NET", .x = 50, .y = 50, .fontIdx = 0x20650200 } );
3921 page.
netmap[wire.id] =
"FONT_NET";
3922 page.
wires.push_back( std::move( wire ) );
3925 comment.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
3928 page.
graphics.push_back( std::move( comment ) );
3931 design.
sourceId =
"design-template-font-map";
3933 ORCAD_FONT{ .height = -9, .face =
"Courier New" },
3934 ORCAD_FONT{ .height = -12, .face =
"Arial Narrow", .bold =
true } };
3939 design.
symbols.emplace( definition.
name, std::move( definition ) );
3940 design.
pages.push_back( std::move( page ) );
3944 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
3945 schematic->SetProject( &manager.
Prj() );
3948 path.push_back( root );
3955 BOOST_CHECK( reference->
IsBold() );
3975 BOOST_CHECK( netLabel->
IsBold() );
3983 rawText =
static_cast<const SCH_TEXT*
>( item );
3989 BOOST_CHECK( !rawText->
IsBold() );
3997 definition.
name =
"EXPLICIT_FONT.Normal";
4003 placed.
value =
"LARGE";
4012 page.
name =
"EXPLICIT FONT";
4013 page.
instances.push_back( std::move( placed ) );
4016 design.
sourceId =
"explicit-display-font";
4018 ORCAD_FONT{ .height = -20, .face =
"Arial Narrow", .bold =
true } };
4020 design.
symbols.emplace( definition.
name, std::move( definition ) );
4021 design.
pages.push_back( std::move( page ) );
4025 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4026 schematic->SetProject( &manager.
Prj() );
4029 path.push_back( root );
4037 BOOST_CHECK( field->IsBold() );
4046 definition.
name =
"BOXED_TEXT.Normal";
4068 page.
name =
"BOXED TEXT";
4069 page.
instances.push_back( std::move( placed ) );
4072 design.
sourceId =
"boxed-symbol-text";
4074 ORCAD_FONT{ .height = -20, .width = 11, .pitchAndFamily = 0x31, .face =
"Courier New" }
4076 design.
symbols.emplace( definition.
name, std::move( definition ) );
4077 design.
pages.push_back( std::move( page ) );
4081 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4082 schematic->SetProject( &manager.
Prj() );
4085 path.push_back( root );
4095 rectangle =
static_cast<const SCH_SHAPE*
>( &item );
4103 BOX2I glyphBox =
text->GetEffectiveTextShape(
false )->BBox();
4115 definition.
name =
"MULTILINE_TEXT.Normal";
4122 .text =
"DEVICE\nVERSION : 1\nPAGE : 1 of 1\nDATE : TODAY\n",
4132 page.
name =
"MULTILINE TEXT";
4133 page.
instances.push_back( std::move( placed ) );
4136 design.
sourceId =
"multiline-symbol-text";
4138 design.
symbols.emplace( definition.
name, std::move( definition ) );
4139 design.
pages.push_back( std::move( page ) );
4143 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4144 schematic->SetProject( &manager.
Prj() );
4147 path.push_back( root );
4171 definition.
name =
"OCCLUDED_UNDERSCORES.Normal";
4178 .text =
"ISO_EVB_LABEL",
4192 page.
name =
"OCCLUDED UNDERSCORES";
4193 page.
instances.push_back( std::move( placed ) );
4196 design.
sourceId =
"occluded-symbol-text-underscores";
4198 ORCAD_FONT{ .height = -20, .width = 11, .pitchAndFamily = 0x31, .face =
"Courier New" }
4200 design.
symbols.emplace( definition.
name, std::move( definition ) );
4201 design.
pages.push_back( std::move( page ) );
4205 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4206 schematic->SetProject( &manager.
Prj() );
4209 path.push_back( root );
4213 const SCH_TEXT* primitiveText =
nullptr;
4218 primitiveText =
static_cast<const SCH_TEXT*
>( &item );
4230 definition.
name =
"VERTICAL_TEXT.Normal";
4246 page.
name =
"ROTATED SYMBOL TEXT";
4247 page.
instances.push_back( std::move( placed ) );
4250 design.
sourceId =
"rotated-symbol-text";
4252 design.
symbols.emplace( definition.
name, std::move( definition ) );
4253 design.
pages.push_back( std::move( page ) );
4257 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4258 schematic->SetProject( &manager.
Prj() );
4261 path.push_back( root );
4265 const SCH_TEXT* primitiveText =
nullptr;
4270 primitiveText =
static_cast<const SCH_TEXT*
>( &item );
4282 definition.
name =
"VERTICAL_BOXED_TEXT.Normal";
4289 .text =
"ISOLATION BARRIER",
4299 page.
name =
"VERTICAL BOXED TEXT";
4300 page.
instances.push_back( std::move( placed ) );
4303 design.
sourceId =
"vertical-boxed-symbol-text";
4305 design.
symbols.emplace( definition.
name, std::move( definition ) );
4306 design.
pages.push_back( std::move( page ) );
4310 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4311 schematic->SetProject( &manager.
Prj() );
4314 path.push_back( root );
4318 const SCH_TEXT* primitiveText =
nullptr;
4323 &&
static_cast<const SCH_TEXT&
>( item ).
GetText() == wxS(
"ISOLATION BARRIER" ) )
4325 primitiveText =
static_cast<const SCH_TEXT*
>( &item );
4344 definition.
name =
"SWITCH_CONTACT_TEXT.Normal";
4371 page.
name =
"SWITCH CONTACT TEXT";
4372 page.
instances.push_back( std::move( placed ) );
4375 design.
sourceId =
"switch-contact-text";
4377 design.
symbols.emplace( definition.
name, std::move( definition ) );
4378 design.
pages.push_back( std::move( page ) );
4382 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4383 schematic->SetProject( &manager.
Prj() );
4386 path.push_back( root );
4395 contact =
static_cast<const SCH_SHAPE*
>( &item );
4408 definition.
name =
"DEGENERATE_ARC.Normal";
4425 page.
name =
"DEGENERATE ARC";
4426 page.
instances.push_back( std::move( placed ) );
4429 design.
sourceId =
"degenerate-symbol-arc";
4430 design.
symbols.emplace( definition.
name, std::move( definition ) );
4431 design.
pages.push_back( std::move( page ) );
4435 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4436 schematic->SetProject( &manager.
Prj() );
4439 path.push_back( root );
4452 definition.
name =
"HIDDEN_PIN.Normal";
4483 page.
name =
"HIDDEN PIN";
4484 page.
instances.push_back( std::move( placed ) );
4487 design.
sourceId =
"zero-length-pin-text";
4488 design.
symbols.emplace( definition.
name, std::move( definition ) );
4489 design.
pages.push_back( std::move( page ) );
4493 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4494 schematic->SetProject( &manager.
Prj() );
4497 path.push_back( root );
4500 BOOST_REQUIRE_EQUAL( converted->
GetPins().size(), 2u );
4502 std::map<wxString, wxString> pinNames;
4506 BOOST_CHECK(
pin->IsVisible() );
4508 BOOST_CHECK_GT(
pin->GetNameTextSize(), 0 );
4509 BOOST_CHECK_GT(
pin->GetNumberTextSize(), 0 );
4510 pinNames.emplace(
pin->GetNumber(),
pin->GetName() );
4520 const wxString&
text =
static_cast<const SCH_TEXT&
>( item ).GetText();
4521 BOOST_CHECK(
text != wxS(
"LABEL" ) &&
text != wxS(
"RIGHT" )
4522 &&
text != wxS(
"1" ) &&
text != wxS(
"2" ) );
4532 definition.
name =
"POWER_STYLE_PIN.Normal";
4542 .shapeBits = 0x81 } );
4552 page.
name =
"POWER STYLE PIN";
4553 page.
instances.push_back( std::move( placed ) );
4556 design.
sourceId =
"power-style-pin";
4557 design.
symbols.emplace( definition.
name, std::move( definition ) );
4558 design.
pages.push_back( std::move( page ) );
4562 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4563 schematic->SetProject( &manager.
Prj() );
4566 path.push_back( root );
4569 BOOST_REQUIRE_EQUAL( converted->
GetPins().size(), 1u );
4571 BOOST_CHECK(
pin->IsVisible() );
4574 BOOST_CHECK_GT(
pin->GetNameTextSize(), 0 );
4575 BOOST_CHECK_GT(
pin->GetNumberTextSize(), 0 );
4580 BOOST_ERROR(
"Pin data duplicated as SCH_TEXT" );
4589 definition.
name =
"ZERO_LENGTH_POWER_STYLE_PIN.Normal";
4599 .shapeBits = 0x81 } );
4609 page.
name =
"ZERO LENGTH POWER STYLE PIN";
4610 page.
instances.push_back( std::move( placed ) );
4613 design.
sourceId =
"zero-length-power-style-pin";
4614 design.
symbols.emplace( definition.
name, std::move( definition ) );
4615 design.
pages.push_back( std::move( page ) );
4619 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4620 schematic->SetProject( &manager.
Prj() );
4623 path.push_back( root );
4626 BOOST_REQUIRE_EQUAL( converted->
GetPins().size(), 1u );
4627 BOOST_CHECK( !converted->
GetPins().front()->IsVisible() );
4638 definition.
name =
"INPUT_WEDGE.Normal";
4643 .shapeBits = 0x21 },
4644 ORCAD_SYMBOL_PIN{ .name =
"OUT", .position = 1, .startX = 40, .startY = 10,
4646 .shapeBits = 0x21 },
4658 page.
name =
"INPUT WEDGE";
4659 page.
instances.push_back( std::move( placed ) );
4663 design.
symbols.emplace( definition.
name, std::move( definition ) );
4664 design.
pages.push_back( std::move( page ) );
4668 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4669 schematic->SetProject( &manager.
Prj() );
4672 path.push_back( root );
4676 std::vector<const SCH_SHAPE*> filledPolygons;
4686 filledPolygons.push_back( &shape );
4689 BOOST_REQUIRE_EQUAL( filledPolygons.size(), 1u );
4690 const std::vector<VECTOR2I>& points = filledPolygons.front()->GetPolyPoints();
4691 BOOST_REQUIRE_EQUAL( points.size(), 4u );
4692 BOOST_CHECK( points.front() ==
OrcadDbuToIu( 0, 10 ) );
4693 BOOST_CHECK( points.back() == points.front() );
4701 definition.
name =
"HORIZONTAL_PIN_NUMBER.Normal";
4721 page.
name =
"HORIZONTAL PIN NUMBER";
4722 page.
instances.push_back( std::move( placed ) );
4725 design.
sourceId =
"horizontal-pin-number";
4726 design.
symbols.emplace( definition.
name, std::move( definition ) );
4727 design.
pages.push_back( std::move( page ) );
4731 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4732 schematic->SetProject( &manager.
Prj() );
4735 path.push_back( root );
4739 BOOST_REQUIRE_EQUAL( converted->
GetPins().size(), 1u );
4743 BOOST_CHECK_GT(
pin->GetNameTextSize(), 0 );
4744 BOOST_CHECK_GT(
pin->GetNumberTextSize(), 0 );
4749 BOOST_ERROR(
"Pin number duplicated as SCH_TEXT" );
4758 definition.
name =
"PSPICE_TRANSISTOR.Normal";
4764 placed.
value =
"MMBT3904";
4769 ORCAD_DISPLAY_PROP{ .name =
"Implementation", .x = -10, .y = -30, .dispMode = 0x101 },
4773 page.
name =
"DISPLAYED IMPLEMENTATION";
4774 page.
instances.push_back( std::move( placed ) );
4777 design.
sourceId =
"displayed-implementation";
4779 design.
symbols.emplace( definition.
name, std::move( definition ) );
4780 design.
pages.push_back( std::move( page ) );
4784 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4785 schematic->SetProject( &manager.
Prj() );
4788 path.push_back( root );
4794 BOOST_CHECK( implementation->
IsVisible() );
4806 definition.
name =
"VPULSE.Normal";
4814 placed.
props[
"V1"] =
"0";
4821 page.
name =
"DISPLAYED PROPERTY NAME";
4822 page.
instances.push_back( std::move( placed ) );
4825 design.
sourceId =
"displayed-property-name";
4826 design.
symbols.emplace( definition.
name, std::move( definition ) );
4827 design.
pages.push_back( std::move( page ) );
4831 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4832 schematic->SetProject( &manager.
Prj() );
4835 path.push_back( root );
4849 if(
text->GetText() == wxS(
"V1 = 0" ) )
4861 definition.
name =
"RES_27.Normal";
4867 placed.
value =
"27";
4876 page.
name =
"DISPLAYED VALUE NAME";
4877 page.
instances.push_back( std::move( placed ) );
4880 design.
sourceId =
"displayed-value-name";
4881 design.
symbols.emplace( definition.
name, std::move( definition ) );
4882 design.
pages.push_back( std::move( page ) );
4886 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4887 schematic->SetProject( &manager.
Prj() );
4890 path.push_back( root );
4904 if(
text->GetText() == wxS(
"Value = 27" ) )
4916 definition.
name =
"IMPLEMENTATION_PATH.Normal";
4918 definition.
props[
"Implementation Path"] =
"LIBRARY/PART";
4921 package.
name =
"IMPLEMENTATION_PATH";
4922 package.
props[
"Implementation Path"] =
"";
4932 page.
name =
"HIDDEN IMPLEMENTATION PATH";
4933 page.
instances.push_back( std::move( placed ) );
4936 design.
sourceId =
"hidden-implementation-path";
4937 design.
symbols.emplace( definition.
name, std::move( definition ) );
4938 design.
packages.emplace( package.
name, std::move( package ) );
4939 design.
pages.push_back( std::move( page ) );
4943 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
4944 schematic->SetProject( &manager.
Prj() );
4947 path.push_back( root );
4950 SCH_FIELD* implementationPath = converted->
GetField( wxS(
"Implementation Path" ) );
4953 BOOST_CHECK( !implementationPath->
IsVisible() );
4961 definition.
name =
"SWITCH.Normal";
4963 definition.
props[
"Manufacturer"] =
"Panasonic Electronic Components";
4966 package.
name =
"SWITCH";
4975 replaced.
value =
"EVQ-PE105K";
4991 page.
name =
"OCCURRENCE PROPERTIES";
4995 design.
sourceId =
"occurrence-properties";
4996 design.
symbols.emplace( definition.
name, std::move( definition ) );
4997 design.
packages.emplace( package.
name, std::move( package ) );
4998 design.
pages.push_back( std::move( page ) );
5000 {
"Value",
"434 123 050 816" },
5001 {
"Manufacturer",
"Wurth Electronics Inc" },
5002 {
"PCB Footprint",
"434 123 050 816" },
5006 {
"Manufacturer",
"" },
5007 {
"PCB Footprint",
"" },
5012 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
5013 schematic->SetProject( &manager.
Prj() );
5016 path.push_back( root );
5023 wxS(
"Wurth Electronics Inc" ) );
5026 wxS(
"434 123 050 816" ) );
5031 BOOST_CHECK( !clearedSymbol->
GetField( wxS(
"Manufacturer" ) ) );
5032 BOOST_CHECK( !clearedSymbol->
GetField( wxS(
"OrCAD Footprint" ) ) );
5039 page.
name =
"OCCURRENCE NETS";
5040 page.
netmap[11643] =
"LED1_R";
5046 page.
wires.push_back( named );
5049 generated.
dbId = 6941990;
5050 generated.
id = 20000;
5054 page.
wires.push_back( generated );
5057 design.
sourceId =
"occurrence-net-names";
5058 design.
pages.push_back( std::move( page ) );
5062 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
5065 schematic->SetProject( &manager.
Prj() );
5067 std::set<wxString> labels;
5070 labels.insert(
static_cast<SCH_LABEL*
>( item )->GetText() );
5072 BOOST_CHECK( !labels.contains( wxS(
"LED1_R_G13" ) ) );
5073 BOOST_CHECK( !labels.contains( wxS(
"N6941990_DSP_UL,_LL,_UR,_LR_ATDSP0" ) ) );
5080 page.
name =
"INTERFACE NETS";
5081 page.
netmap[1] =
"WL_REG_ON";
5086 page.
wires.push_back( wire );
5090 page.
offpage.push_back( std::move( offpage ) );
5093 peerPage.
name =
"PEER";
5096 peerPage.
offpage.push_back( std::move( peerOffpage ) );
5099 design.
sourceId =
"occurrence-interface-prefix";
5100 design.
pages.push_back( std::move( page ) );
5101 design.
pages.push_back( std::move( peerPage ) );
5105 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
5108 schematic->SetProject( &manager.
Prj() );
5110 std::set<wxString> labels;
5115 BOOST_CHECK( labels.contains( wxS(
"WL_REG_ON" ) ) );
5116 BOOST_CHECK( !labels.contains( wxS(
"WL_REG_ON_M2" ) ) );
5123 page.
name =
"INTERFACE ALIAS";
5124 page.
netmap[1] =
"UART0_CTS";
5125 page.
netAliases[1] = {
"TWRPI_GPIO4",
"EBI_AD1/PTD5/FTM0_CH5",
"UART0_CTS" };
5132 connectorAlias.
name =
"TWRPI_GPIO4";
5133 connectorAlias.
x = 10;
5134 wire.
aliases.push_back( std::move( connectorAlias ) );
5136 interfaceAlias.
name =
"EBI_AD1/PTD5/FTM0_CH5";
5137 interfaceAlias.
x = 15;
5138 wire.
aliases.push_back( std::move( interfaceAlias ) );
5140 secondaryAlias.
name =
"UART0_CTS";
5141 secondaryAlias.
x = 50;
5142 wire.
aliases.push_back( std::move( secondaryAlias ) );
5143 page.
wires.push_back( wire );
5149 connector.
pins.push_back(
pin );
5150 page.
instances.push_back( std::move( connector ) );
5156 displayedName.
name =
"Name";
5157 displayedName.
x = -85;
5158 offpage.
displayProps.push_back( std::move( displayedName ) );
5159 page.
offpage.push_back( std::move( offpage ) );
5162 design.
sourceId =
"occurrence-interface-alias";
5163 design.
pages.push_back( std::move( page ) );
5166 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
5169 schematic->SetProject( &manager.
Prj() );
5171 std::set<wxString> labels;
5176 BOOST_CHECK( labels.contains( wxS(
"TWRPI_GPIO4" ) ) );
5183 page.
name =
"VERTICAL OFFPAGE";
5184 page.
netmap[1] =
"VBUS_P_CTRL0_CON";
5192 page.
wires.push_back( wire );
5195 offpage.
name =
"OFFPAGELEFT-L";
5201 .name =
"Name", .x = 4, .y = 10, .rotation = 1, .fontIdx = 1, .dispMode = 0x101 } );
5202 page.
offpage.push_back( std::move( offpage ) );
5205 design.
sourceId =
"vertical-offpage-display-name";
5208 design.
pages.push_back( std::move( page ) );
5210 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
5213 schematic->SetProject( &manager.
Prj() );
5222 if( label->
GetText() == wxS(
"VBUS_P_CTRL0_CON" )
5232 BOOST_CHECK(
static_cast<const SCH_TEXT*
>( item )->GetText() != wxS(
"VBUS_P_CTRL0_CON" ) );
5239 page.
name =
"INTERSHEET REFERENCE";
5240 page.
netmap[1] =
"PWR_LED_CTRL";
5248 page.
wires.push_back( wire );
5251 offpage.
name =
"OFFPAGELEFT-L";
5256 offpage.
props[
"IREF"] =
"[5,20]";
5258 .name =
"Name", .x = 4, .y = 5, .fontIdx = 1, .dispMode = 0x101 } );
5260 .name =
"IREF", .x = 83, .y = 5, .fontIdx = 1, .dispMode = 0x101 } );
5261 page.
offpage.push_back( std::move( offpage ) );
5264 design.
sourceId =
"offpage-intersheet-reference";
5267 design.
pages.push_back( std::move( page ) );
5269 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
5272 schematic->SetProject( &manager.
Prj() );
5275 const SCH_TEXT* intersheetRef =
nullptr;
5281 if(
text->GetText() == wxS(
"[5,20]" ) )
5282 intersheetRef =
text;
5286 BOOST_CHECK( intersheetRef->
IsVisible() );
5290 int baseX = std::min( design.
pages[0].offpage[0].bbox.x1, design.
pages[0].offpage[0].bbox.x2 );
5291 int baseY = std::min( design.
pages[0].offpage[0].bbox.y1, design.
pages[0].offpage[0].bbox.y2 );
5302 page.
name =
"HIDDEN INTERSHEET REFERENCE";
5303 page.
netmap[1] =
"SWDIO";
5307 offpage.
name =
"OFFPAGELEFT-L";
5312 offpage.
props[
"IREF"] =
"0";
5314 .name =
"Name", .x = 4, .y = 5, .fontIdx = 1, .dispMode = 0x101 } );
5316 .name =
"IREF", .x = 20, .y = 30, .fontIdx = 1, .dispMode = 0x001 } );
5317 page.
offpage.push_back( std::move( offpage ) );
5320 design.
sourceId =
"hidden-offpage-intersheet-reference";
5323 design.
pages.push_back( std::move( page ) );
5325 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
5328 schematic->SetProject( &manager.
Prj() );
5332 BOOST_CHECK_NE(
static_cast<const SCH_TEXT*
>( item )->GetText(), wxS(
"0" ) );
5340 definition.
name =
"Rudy-PortRight";
5356 ORCAD_DISPLAY_PROP{ .name =
"Name", .x = 16, .y = 3, .fontIdx = 1, .dispMode = 0x101 } );
5359 page.
name =
"SOURCE PORT GRAPHICS";
5362 page.
ports.push_back( std::move( port ) );
5363 page.
wires.push_back(
ORCAD_WIRE{ .id = 1, .x1 = 170, .y1 = 110, .x2 = 220, .y2 = 110 } );
5364 page.
netmap[1] =
"*SHORT";
5367 design.
sourceId =
"source-port-graphics";
5369 design.
symbols.emplace( definition.
name, std::move( definition ) );
5370 design.
pages.push_back( std::move( page ) );
5374 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
5375 schematic->SetProject( &manager.
Prj() );
5383 if( label->
GetText() == wxS(
"*SHORT" ) )
5396 BOOST_CHECK_NE(
static_cast<const SCH_TEXT*
>( item )->GetText(), wxString(
"*SHORT" ) );
5404 sensePage.
name =
"SENSE";
5405 sensePage.
netmap[1] =
"SENSE-";
5406 sensePage.
netAliases[1] = {
"SENSE-",
"VOUT" };
5410 sensePage.
wires.push_back( senseWire );
5413 sensePage.
offpage.push_back( std::move( senseOffpage ) );
5416 isnPage.
name =
"ISN";
5417 isnPage.
netmap[2] =
"ISN1_DCR";
5418 isnPage.
netAliases[2] = {
"ISN1_DCR",
"VOUT" };
5422 isnPage.
wires.push_back( isnWire );
5425 isnPage.
offpage.push_back( std::move( isnOffpage ) );
5428 design.
sourceId =
"occurrence-cross-page-interface-alias";
5429 design.
pages.push_back( std::move( sensePage ) );
5430 design.
pages.push_back( std::move( isnPage ) );
5433 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
5436 schematic->SetProject( &manager.
Prj() );
5438 std::set<wxString> labels;
5446 BOOST_CHECK( labels.contains( wxS(
"SENSE-" ) ) );
5447 BOOST_CHECK( !labels.contains( wxS(
"ISN1_DCR" ) ) );
5454 page.
name =
"DISTINCT INTERFACES";
5455 page.
netmap[1] =
"PCIE_USIM_DATA";
5456 page.
netAliases[1] = {
"PCIE_USIM_DATA",
"USIM_DATA" };
5460 page.
wires.push_back( wire );
5464 page.
offpage.push_back( std::move( pcieOffpage ) );
5467 page.
offpage.push_back( std::move( usimOffpage ) );
5470 design.
sourceId =
"distinct-occurrence-interface-names";
5471 design.
pages.push_back( std::move( page ) );
5475 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
5478 schematic->SetProject( &manager.
Prj() );
5480 std::set<wxString> labels;
5485 BOOST_CHECK( labels.contains( wxS(
"PCIE_USIM_DATA" ) ) );
5486 BOOST_CHECK( labels.contains( wxS(
"USIM_DATA" ) ) );
5493 page.
name =
"OCCURRENCE OFFPAGE";
5497 wire.
dbId = 22608001;
5500 page.
wires.push_back( wire );
5504 page.
offpage.push_back( std::move( offpage ) );
5507 design.
sourceId =
"occurrence-wire-offpage-name";
5508 design.
pages.push_back( std::move( page ) );
5511 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
5514 schematic->SetProject( &manager.
Prj() );
5516 std::set<wxString> labels;
5521 BOOST_CHECK( labels.contains( wxS(
"VOUT_22608001" ) ) );
5522 BOOST_CHECK( !labels.contains( wxS(
"VOUT" ) ) );
5530 power.
name =
"VCC_BAR";
5540 wirePage.
name =
"OCCURRENCE POWER WIRE";
5541 wirePage.
netmap[1] =
"VDD";
5545 wirePage.
wires.push_back( wire );
5548 globalPage.
name =
"OCCURRENCE POWER SYMBOL";
5549 globalPage.
globals.push_back( std::move( global ) );
5552 design.
sourceId =
"occurrence-power-global-wire";
5553 design.
symbols.emplace( power.
name, std::move( power ) );
5554 design.
pages.push_back( std::move( wirePage ) );
5555 design.
pages.push_back( std::move( globalPage ) );
5558 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
5561 schematic->SetProject( &manager.
Prj() );
5573 wireNet = item->Connection( &
path )->Name();
5578 BOOST_REQUIRE_EQUAL( symbol->
GetPins( &
path ).size(), 1 );
5579 powerNet = symbol->
GetPins( &
path ).front()->Connection( &
path )->Name();
5586 BOOST_CHECK_NE( wireNet, powerNet );
5594 power.
name =
"VCC_CIRCLE";
5598 power.
pins.push_back( powerPin );
5604 global.
props[
"Name"] =
"DISPLAY_ONLY";
5614 aliasedGlobal.
x = 1090;
5615 aliasedGlobal.
y = 320;
5619 page.
name =
"POWER";
5626 page.
wires.push_back( wire );
5627 page.
netmap.emplace( wire.
id,
"0" );
5630 aliasedWire.
x1 = 1110;
5631 aliasedWire.
y1 = 320;
5632 aliasedWire.
x2 = 1110;
5633 aliasedWire.
y2 = 300;
5634 page.
wires.push_back( aliasedWire );
5635 page.
netmap.emplace( aliasedWire.
id,
"0" );
5637 page.
globals.push_back( std::move( global ) );
5638 page.
globals.push_back( std::move( aliasedGlobal ) );
5641 design.
sourceId =
"power-display-name";
5642 design.
symbols.emplace( power.
name, std::move( power ) );
5643 design.
pages.push_back( std::move( page ) );
5647 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
5648 schematic->SetProject( &manager.
Prj() );
5651 path.push_back( root );
5656 BOOST_REQUIRE_EQUAL( symbol->
GetPins().size(), 1u );
5665 BOOST_CHECK( displayName->
IsVisible() );
5678 aliased = candidate;
5684 BOOST_REQUIRE_EQUAL( aliased->
GetPins().size(), 1u );
5688 schematic->ConnectionGraph()->Recalculate( schematic->BuildSheetListSortedByPageNumbers(),
true );
5692 BOOST_CHECK_NE( symbol->
GetPins().front()->Connection( &
path )->Name(),
5693 aliased->
GetPins().front()->Connection( &
path )->Name() );
5699 for(
int pinLength : { 10, 0 } )
5703 part.
name =
"LOCAL_POWER.Normal";
5707 .startX = pinLength,
5710 .shapeBits = 0x80 } );
5720 .wordA = std::numeric_limits<uint32_t>::max(),
5724 page.
name =
"EXPLICIT HIDDEN POWER PIN";
5726 page.
instances.push_back( std::move( placed ) );
5729 design.
sourceId =
"explicit-power-style-pin";
5730 design.
symbols.emplace( part.
name, std::move( part ) );
5731 design.
pages.push_back( std::move( page ) );
5735 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
5736 schematic->SetProject( &manager.
Prj() );
5739 path.push_back( root );
5743 BOOST_REQUIRE_EQUAL( symbol->
GetPins().size(), 1u );
5745 BOOST_CHECK( !symbol->
GetPins().front()->IsGlobalPower() );
5747 BOOST_CHECK( symbol->
GetPins().front()->GetType()
5750 schematic->ConnectionGraph()->Recalculate( schematic->BuildSheetListSortedByPageNumbers(),
true );
5759 for(
int scenario : { 0, 1, 2, 3 } )
5761 bool powerUnitFirst = ( scenario & 1 ) == 0;
5762 bool separatePages = ( scenario & 2 ) != 0;
5765 power.
name =
"DUALA.Normal";
5770 .shapeBits = 0x80 } );
5773 signal.
name =
"DUALB.Normal";
5774 signal.
pins.front().name =
"SIGNAL";
5775 signal.
pins.front().startX = 10;
5777 signal.
pins.front().shapeBits = 0;
5780 package.
name =
"DUAL";
5785 page.
name =
"HIDDEN POWER MULTIUNIT";
5787 page.
netmap[2] =
"OVERRIDE";
5789 for(
int part : { 1, 2, 3 } )
5791 for(
int unit : { 0, 1 } )
5793 if( part == 3 && unit == 1 )
5799 instance.
reference =
"U" + std::to_string( part );
5801 instance.
x = part * 100;
5802 instance.
y = ( unit + 1 ) * 100;
5806 .wordB = unit ? 0u :
static_cast<uint32_t
>( part == 2 ? 2 : 1 ) } );
5807 page.
instances.push_back( std::move( instance ) );
5811 if( !powerUnitFirst )
5815 design.
sourceId =
"native-hidden-power-multiunit";
5816 design.
symbols.emplace( power.
name, std::move( power ) );
5817 design.
symbols.emplace( signal.
name, std::move( signal ) );
5818 design.
packages.emplace( package.
name, std::move( package ) );
5819 design.
pages.push_back( std::move( page ) );
5824 second.
name =
"SIGNAL UNITS";
5825 auto& first = design.
pages.front().instances;
5827 for(
auto& instance : first )
5829 if( instance.unitIndex == 1 )
5830 second.
instances.push_back( std::move( instance ) );
5833 std::erase_if( first, [](
const auto& aInstance ) {
return aInstance.unitIndex == 1; } );
5834 design.
pages.push_back( std::move( second ) );
5839 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
5840 schematic->SetProject( &manager.
Prj() );
5842 auto checkUnits = [&]()
5844 SCH_SHEET_LIST paths = schematic->BuildSheetListSortedByPageNumbers();
5845 schematic->ConnectionGraph()->Recalculate( paths,
true );
5846 std::map<wxString, std::vector<SCH_SYMBOL*>> parts;
5847 std::map<SCH_SYMBOL*, SCH_SHEET_PATH> symbolPaths;
5854 parts[symbol->
GetRef( &
path,
false )].push_back( symbol );
5855 symbolPaths.emplace( symbol,
path );
5859 BOOST_REQUIRE_EQUAL( parts.size(), 3u );
5861 for(
const auto& [reference, units] : parts )
5863 BOOST_REQUIRE_EQUAL( units.size(), reference == wxS(
"U3" ) ? 1u : 2u );
5865 if( units.size() == 2 )
5867 BOOST_CHECK( units[0]->GetLibId() == units[1]->GetLibId() );
5868 BOOST_CHECK( units[0]->GetUnit() != units[1]->GetUnit() );
5879 if(
pin->GetNumber() == wxS(
"1" ) )
5881 BOOST_CHECK( !
pin->IsVisible() );
5885 reference != wxS(
"U2" ) ? wxString(
"$$$1" )
5886 : wxString(
"OVERRIDE" ) );
5895 std::vector<wxString> files;
5896 std::vector<std::pair<KIID, wxString>> sheetIdentities;
5898 for(
SCH_SHEET* sheet : schematic->GetTopLevelSheets() )
5900 wxString file = wxFileName::CreateTempFileName( wxS(
"orcad_native_power_" ) );
5902 files.push_back( file );
5903 sheetIdentities.emplace_back( sheet->m_Uuid, sheet->GetName() );
5907 std::vector<SCH_SHEET*> reloaded;
5909 for(
const wxString& file : files )
5913 const auto& [uuid,
name] = sheetIdentities[reloaded.size()];
5916 reloaded.push_back( root );
5919 schematic->SetTopLevelSheets( reloaded );
5920 schematic->RefreshHierarchy();
5923 path.LastScreen()->UpdateLocalLibSymbolLinks();
5927 for(
const wxString& file : files )
5928 wxRemoveFile( file );
5937 ground.
name =
"GND_POWER";
5941 ground.
pins.push_back( groundPin );
5944 supply.
name =
"VCC_CIRCLE";
5959 page.
name =
"POWER GRAPHICS";
5962 groundWire.
x1 = 960;
5963 groundWire.
y1 = 270;
5964 groundWire.
x2 = 960;
5965 groundWire.
y2 = 250;
5966 page.
wires.push_back( groundWire );
5969 supplyWire.
x1 = 1110;
5970 supplyWire.
y1 = 320;
5971 supplyWire.
x2 = 1110;
5972 supplyWire.
y2 = 300;
5973 page.
wires.push_back( supplyWire );
5974 page.
netmap.emplace( 1,
"0" );
5975 page.
netmap.emplace( 2,
"0" );
5977 page.
globals.push_back( std::move( groundGlobal ) );
5978 page.
globals.push_back( std::move( supplyGlobal ) );
5981 design.
sourceId =
"power-graphic-identity";
5982 design.
symbols.emplace( ground.
name, std::move( ground ) );
5983 design.
symbols.emplace( supply.
name, std::move( supply ) );
5984 design.
pages.push_back( std::move( page ) );
5989 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
5990 schematic->SetProject( &manager.
Prj() );
5993 path.push_back( root );
6000 BOOST_REQUIRE_EQUAL( groundSymbol->
GetPins().size(), 1u );
6001 BOOST_REQUIRE_EQUAL( supplySymbol->
GetPins().size(), 1u );
6008static std::filesystem::path
findCorpusDesign(
const std::filesystem::path& aRoot,
const std::string& aFileName );
6013 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
6015 if( !corpusEnv || !*corpusEnv )
6018 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC2331A-4.DSN" );
6023 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
6026 schematic->SetProject( &manager.
Prj() );
6027 schematic->CurrentSheet().clear();
6028 schematic->CurrentSheet().push_back( &schematic->Root() );
6033 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
6034 schematic->ConnectionGraph()->Recalculate( sheets,
true );
6037 for(
const auto& [key, subgraphs] : schematic->ConnectionGraph()->GetNetMap() )
6041 for(
SCH_ITEM* item : subgraph->GetItems() )
6049 if( symbol && symbol->
GetRef( &subgraph->GetSheet(),
false ) == wxS(
"C1" )
6050 &&
pin->GetNumber() == wxS(
"1" ) )
6052 c1Pin1Net = key.Name;
6064 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
6066 if( !corpusEnv || !*corpusEnv )
6074 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
6077 schematic->SetProject( &manager.
Prj() );
6078 schematic->CurrentSheet().clear();
6079 schematic->CurrentSheet().push_back( &schematic->Root() );
6084 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
6085 schematic->ConnectionGraph()->Recalculate( sheets,
true );
6088 for(
const auto& [key, subgraphs] : schematic->ConnectionGraph()->GetNetMap() )
6092 if( !subgraph->GetSheet().LastScreen()->GetFileName().Contains( wxS(
"_PSU" ) ) )
6095 for(
SCH_ITEM* item : subgraph->GetItems() )
6104 pinNets[{ symbol->
GetRef( &subgraph->GetSheet(),
false ),
pin->GetNumber() }] = subgraph;
6109 BOOST_REQUIRE( pinNets.count( { wxS(
"C126" ), wxS(
"1" ) } ) );
6110 BOOST_REQUIRE( pinNets.count( { wxS(
"U15" ), wxS(
"3" ) } ) );
6111 BOOST_REQUIRE( pinNets.count( { wxS(
"U15" ), wxS(
"8" ) } ) );
6113 pinNets.at( { wxS(
"U15" ), wxS(
"3" ) } ) );
6115 pinNets.at( { wxS(
"U15" ), wxS(
"3" ) } ) );
6123 power.
name =
"VCC_BAR";
6128 power.
pins.push_back( powerPin );
6139 page.
name =
"LEGACY POWER";
6146 page.
wires.push_back( wire );
6147 page.
netmap.emplace( wire.
id,
"12V" );
6148 page.
globals.push_back( std::move( global ) );
6151 design.
sourceId =
"legacy-power-bbox";
6152 design.
symbols.emplace( power.
name, std::move( power ) );
6153 design.
pages.push_back( std::move( page ) );
6157 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
6158 schematic->SetProject( &manager.
Prj() );
6161 path.push_back( root );
6165 BOOST_REQUIRE_EQUAL( symbol->
GetPins().size(), 1u );
6176 power.
name =
"GND_POWER";
6180 power.
pins.push_back( powerPin );
6190 page.
name =
"POWER ALIAS";
6197 page.
wires.push_back( wire );
6198 page.
netmap.emplace( wire.
id,
"GND" );
6200 page.
globals.push_back( std::move( global ) );
6203 design.
sourceId =
"power-page-net";
6204 design.
symbols.emplace( power.
name, std::move( power ) );
6205 design.
pages.push_back( std::move( page ) );
6210 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
6211 schematic->SetProject( &manager.
Prj() );
6214 path.push_back( root );
6218 BOOST_REQUIRE_EQUAL( symbol->
GetPins().size(), 1u );
6227 power.
name =
"VDD_POWER";
6231 power.
pins.push_back( powerPin );
6243 duplicateGlobal.
dbId = 2;
6244 duplicateGlobal.
name = global.
name;
6246 duplicateGlobal.
x = global.
x;
6247 duplicateGlobal.
y = global.
y;
6248 duplicateGlobal.
bbox = global.
bbox;
6251 page.
name =
"GLOBAL ALIAS";
6260 wire.
aliases.push_back( alias );
6261 page.
wires.push_back( wire );
6262 page.
netmap.emplace( wire.
id,
"AUX" );
6264 page.
globals.push_back( std::move( global ) );
6265 page.
globals.push_back( std::move( duplicateGlobal ) );
6268 design.
sourceId =
"canonical-global-alias";
6269 design.
symbols.emplace( power.
name, std::move( power ) );
6270 design.
pages.push_back( std::move( page ) );
6274 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
6275 schematic->SetProject( &manager.
Prj() );
6278 std::set<wxString> globalLabels;
6279 std::set<wxString> localLabels;
6282 globalLabels.insert(
static_cast<SCH_GLOBALLABEL*
>( item )->GetText() );
6285 localLabels.insert(
static_cast<SCH_LABEL*
>( item )->GetText() );
6287 BOOST_CHECK( !globalLabels.contains( wxS(
"AUX" ) ) );
6288 BOOST_CHECK( localLabels.contains( wxS(
"AUX" ) ) );
6295 page.
name =
"DISTINCT INTERFACE NET";
6296 page.
netmap[1] =
"USIM_DATA";
6297 page.
netAliases[1] = {
"USIM_DATA",
"PCIE_USIM_DATA" };
6299 page.
netmap[2] =
"PCIE_USIM_DATA";
6301 page.
wires.push_back(
ORCAD_WIRE{ .id = 2, .x1 = 1000, .x2 = 1100 } );
6312 page.
offpage.push_back( std::move( aliased ) );
6313 page.
offpage.push_back( std::move( distinct ) );
6316 design.
sourceId =
"distinct-interface-net";
6317 design.
pages.push_back( std::move( page ) );
6322 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
6323 schematic->SetProject( &manager.
Prj() );
6325 std::set<wxString> labels;
6330 BOOST_CHECK( labels.contains( wxS(
"PCIE_USIM_DATA" ) ) );
6337 page.
name =
"ACTIVE LOW NET";
6338 page.
netmap[1] =
"STATUS";
6344 page.
wires.push_back( std::move( high ) );
6345 page.
netmap[2] =
"/STATUS";
6352 page.
wires.push_back( std::move( low ) );
6355 design.
sourceId =
"active-low-net";
6356 design.
pages.push_back( std::move( page ) );
6360 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
6361 schematic->SetProject( &manager.
Prj() );
6363 std::set<wxString> labels;
6366 labels.insert(
static_cast<SCH_LABEL*
>( item )->GetText() );
6368 BOOST_CHECK( labels.contains( wxS(
"STATUS" ) ) );
6369 BOOST_CHECK( labels.contains( wxS(
"{slash}STATUS" ) ) );
6376 rootPage.
name =
"ROOT";
6382 rootPage.
blocks.push_back( drawn );
6385 childPage.
name =
"CHILD";
6386 childPage.
netmap[1] =
"LED1_R";
6392 alias.
name =
"LED1_R";
6393 wire.
aliases.push_back( alias );
6394 childPage.
wires.push_back( wire );
6396 childPage.
netmap[2] =
"LOCAL_PORT_NAME";
6402 childPage.
wires.push_back( portWire );
6405 port.
name =
"PORTBOTH-R";
6412 ORCAD_DISPLAY_PROP{ .name =
"Name", .x = 10, .y = 3, .fontIdx = 1, .dispMode = 0x101 } );
6413 childPage.
ports.push_back( std::move( port ) );
6415 childPage.
netmap[4] =
"N6941990";
6417 generatedWire.
dbId = 6941990;
6418 generatedWire.
id = 4;
6419 generatedWire.
y1 = 300;
6420 generatedWire.
x2 = 100;
6421 generatedWire.
y2 = 300;
6422 childPage.
wires.push_back( generatedWire );
6433 design.
sourceId =
"hierarchical-flat-net-name";
6437 portDefinition.
name =
"PORTBOTH-R";
6442 design.
symbols.emplace( portDefinition.
name, std::move( portDefinition ) );
6443 design.
pages.push_back( std::move( rootPage ) );
6447 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
6450 schematic->SetProject( &manager.
Prj() );
6455 child =
static_cast<SCH_SHEET*
>( item );
6460 std::set<wxString> labels;
6463 labels.insert(
static_cast<SCH_LABEL*
>( item )->GetText() );
6468 BOOST_CHECK( labels.contains( wxS(
"LED1_R" ) ) );
6469 BOOST_CHECK( !labels.contains( wxS(
"LED1_R_G13" ) ) );
6470 BOOST_CHECK( !labels.contains( wxS(
"LOCAL_PORT_NAME_G13" ) ) );
6471 BOOST_CHECK( !labels.contains( wxS(
"N6941990_G13" ) ) );
6473 int exactPortLabels = 0;
6479 if( label->
GetText() == wxS(
"LOCAL_PORT_NAME" ) )
6493 rootPage.
name =
"ROOT";
6503 ORCAD_DISPLAY_PROP{ .name =
"Reference", .y = -10, .fontIdx = 2, .dispMode = 0x101 },
6504 ORCAD_DISPLAY_PROP{ .name =
"Value", .x = 85, .y = -10, .fontIdx = 9, .dispMode = 0x101 },
6507 .x = 100, .y = 230 } );
6508 rootPage.
blocks.push_back( std::move( drawn ) );
6511 childPage.
name =
"Channel_BoM";
6518 design.
sourceId =
"hierarchical-display-fields";
6519 design.
pages.push_back( std::move( rootPage ) );
6520 design.
childFolderPages[
"channel_bom"].push_back( std::move( childPage ) );
6523 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
6526 schematic->SetProject( &manager.
Prj() );
6531 child =
static_cast<SCH_SHEET*
>( item );
6548 pinFill =
static_cast<SCH_SHAPE*
>( item );
6559 titlePage.
name =
"0-TITLE";
6562 mainPage.
name =
"1-MAIN";
6565 gateBlock.
dbId = 600;
6570 .x = 0, .y = 50 } );
6571 mainPage.
blocks.push_back( gateBlock );
6574 microBlock.
dbId = 200;
6576 microBlock.
x1 = 200;
6580 .x = 300, .y = 50 } );
6581 mainPage.
blocks.push_back( microBlock );
6592 gatePage.
name =
"6-GATE";
6594 microPage.
name =
"2-MICRO";
6597 design.
sourceId =
"multi-page-hierarchy-order";
6598 design.
pages.push_back( std::move( titlePage ) );
6599 design.
pages.push_back( std::move( mainPage ) );
6605 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
6608 schematic->SetProject( &manager.
Prj() );
6611 std::vector<SCH_SHEET*> topLevelSheets = schematic->GetTopLevelSheets();
6612 BOOST_REQUIRE_EQUAL( topLevelSheets.size(), 2u );
6616 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
6617 BOOST_REQUIRE_EQUAL( sheets.size(), 4u );
6619 for(
size_t i = 0; i < sheets.size(); ++i )
6620 BOOST_CHECK_EQUAL( sheets[i].GetPageNumber(), wxString::Format( wxS(
"%zu" ), i + 1 ) );
6633 std::vector<wxString> childNames;
6637 if(
path.Last()->GetName() == wxS(
"MICRO" ) ||
path.Last()->GetName() == wxS(
"GATE" ) )
6638 childNames.push_back(
path.Last()->GetName() );
6641 BOOST_REQUIRE_EQUAL( childNames.size(), 2u );
6647 if(
path.Last()->GetName() == wxS(
"GATE" ) )
6649 BOOST_REQUIRE_EQUAL(
path.Last()->GetPins().size(), 1u );
6652 else if(
path.Last()->GetName() == wxS(
"MICRO" ) )
6654 BOOST_REQUIRE_EQUAL(
path.Last()->GetPins().size(), 1u );
6664 rootPage.
name =
"ROOT";
6665 rootPage.
netmap[1] =
"N12345";
6669 parentWire.
x2 = 100;
6670 rootPage.
wires.push_back( parentWire );
6678 rootPage.
blocks.push_back( std::move( drawn ) );
6681 childPage.
name =
"CHILD";
6688 design.
sourceId =
"hierarchical-parent-net-name";
6689 design.
pages.push_back( std::move( rootPage ) );
6693 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
6696 schematic->SetProject( &manager.
Prj() );
6698 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
6699 schematic->ConnectionGraph()->Recalculate( sheets,
true );
6706 wire =
static_cast<SCH_LINE*
>( item );
6708 child =
static_cast<SCH_SHEET*
>( item );
6710 BOOST_CHECK_NE(
static_cast<SCH_LABEL_BASE*
>( item )->GetText(), wxString(
"N12345" ) );
6719 BOOST_REQUIRE_GT( connection->
NetCode(), 0 );
6720 std::set<wxString> pinNames;
6724 pinNames.insert(
pin->GetText() );
6729 BOOST_CHECK( pinNames.contains( wxS(
"SIGNAL" ) ) );
6732 auto mapped = std::find_if( map->
entries.begin(), map->
entries.end(),
6735 return entry.sourceNetId == 1 && entry.originalName == wxS(
"N12345" );
6740 BOOST_CHECK_NE( mapped->nameAtImport, wxString(
"N12345" ) );
6747 rootPage.
name =
"ROOT";
6748 rootPage.
netmap[1] =
"N12345";
6752 parentWire.
x2 = 100;
6753 rootPage.
wires.push_back( parentWire );
6762 rootPage.
blocks.push_back( std::move( drawn ) );
6765 childPage.
name =
"CHILD";
6772 design.
sourceId =
"hierarchical-parent-shared-net-name";
6773 design.
pages.push_back( std::move( rootPage ) );
6777 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
6780 schematic->SetProject( &manager.
Prj() );
6782 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
6783 schematic->ConnectionGraph()->Recalculate( sheets,
true );
6790 wire =
static_cast<SCH_LINE*
>( item );
6792 child =
static_cast<SCH_SHEET*
>( item );
6794 BOOST_CHECK_NE(
static_cast<SCH_LABEL_BASE*
>( item )->GetText(), wxString(
"N12345" ) );
6803 BOOST_REQUIRE_GT( connection->
NetCode(), 0 );
6804 std::set<wxString> pinNames;
6808 pinNames.insert(
pin->GetText() );
6813 BOOST_CHECK( pinNames.contains( wxS(
"G1" ) ) );
6814 BOOST_CHECK( pinNames.contains( wxS(
"G5" ) ) );
6817 auto mapped = std::find_if( map->
entries.begin(), map->
entries.end(),
6820 return entry.sourceNetId == 1 && entry.originalName == wxS(
"N12345" );
6825 BOOST_CHECK_NE( mapped->nameAtImport, wxString(
"N12345" ) );
6832 cached.
name =
"THERMISTOR.Normal";
6835 cached.
pins.resize( 4 );
6836 for(
size_t i = 0; i < cached.
pins.size(); ++i )
6838 cached.
pins[i].hotptX =
static_cast<int>( i ) * 10;
6839 cached.
pins[i].hotptY = 10;
6840 cached.
pins[i].startX = cached.
pins[i].hotptX;
6841 cached.
pins[i].startY = 10;
6848 placed.
pins.resize( 2 );
6849 placed.
pins[0].pinIndex = 2;
6850 placed.
pins[0].x = 70;
6851 placed.
pins[0].y = 1060;
6852 placed.
pins[1].pinIndex = -4;
6853 placed.
pins[1].x = 70;
6854 placed.
pins[1].y = 1080;
6863 load.
name =
"LOAD.Normal";
6865 load.
pins.resize( 1 );
6866 load.
pins[0].hotptX = 0;
6867 load.
pins[0].hotptY = 0;
6868 load.
pins[0].startX = 0;
6869 load.
pins[0].startY = 0;
6875 loadPlaced.
dbId = 2;
6877 loadPlaced.
y = 1060;
6881 page.
name =
"PIN GEOMETRY";
6887 design.
sourceId =
"s593487-stale-pin-geometry";
6890 design.
pages.push_back( std::move( page ) );
6892 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
6895 schematic->SetProject( &manager.
Prj() );
6900 schematic->SetTopLevelSheets( { rootSheet } );
6901 schematic->CurrentSheet().clear();
6902 schematic->CurrentSheet().push_back( rootSheet );
6905 converter.
Convert( rootSheet );
6907 auto [consistent, checkable] =
6923 if( symbol->
GetRef( &rootPath,
false ) == wxS(
"U1" ) )
6934 std::set<std::pair<int, int>> convertedHotpoints;
6935 SCH_PIN* noConnectPin =
nullptr;
6939 convertedHotpoints.emplace(
pin->GetPosition().x,
pin->GetPosition().y );
6941 if(
pin->GetNumber() == wxS(
"4" ) )
6955 cached.
name =
"TESTPOINT.Normal";
6957 cached.
pins.resize( 1 );
6958 cached.
pins[0].position = 0;
6959 cached.
pins[0].startX = 0;
6960 cached.
pins[0].startY = 10;
6961 cached.
pins[0].hotptX = -10;
6962 cached.
pins[0].hotptY = 10;
6973 page.
name =
"PIN BODY END";
6977 design.
sourceId =
"placed-pin-body-end";
6979 design.
pages.push_back( std::move( page ) );
6983 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
6984 schematic->SetProject( &manager.
Prj() );
6987 path.push_back( root );
6991 BOOST_REQUIRE_EQUAL( symbol->
GetPins().size(), 1u );
7001 placed.
pkgName =
"MISSING_TESTPOINT.Normal";
7009 page.
name =
"MISSING TESTPOINT";
7018 design.
sourceId =
"synthesized-single-pin";
7019 design.
pages.push_back( std::move( page ) );
7023 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
7024 schematic->SetProject( &manager.
Prj() );
7033 BOOST_REQUIRE_EQUAL( generated.
pins.size(), 1u );
7045 primary.
name =
"BODY.Normal";
7048 primary.
pins.resize( 2 );
7049 primary.
pins[0].hotptX = 0;
7050 primary.
pins[1].hotptX = 20;
7051 primary.
pins[0].startX = primary.
pins[0].hotptX;
7052 primary.
pins[1].startX = primary.
pins[1].hotptX;
7057 alternate.
pins[0].hotptX = 99;
7058 alternate.
pins[1].hotptX = 119;
7059 alternate.
pins[0].startX = alternate.
pins[0].hotptX;
7060 alternate.
pins[1].startX = alternate.
pins[1].hotptX;
7061 primary.
variants.push_back( alternate );
7072 page.
name =
"CLOSEST BODY";
7076 design.
sourceId =
"s593487-closest-body";
7078 design.
pages.push_back( std::move( page ) );
7082 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
7083 schematic->SetProject( &manager.
Prj() );
7087 BOOST_REQUIRE_EQUAL( converted.
variants.size(), 2u );
7088 BOOST_REQUIRE_EQUAL( converted.
variants.back().primitives.size(), 1u );
7099 primary.
name =
"MIXED.Normal";
7103 primary.
pins.resize( 2 );
7104 primary.
pins[0].hotptX = 10;
7105 primary.
pins[0].hotptY = -10;
7106 primary.
pins[0].startX = primary.
pins[0].hotptX;
7107 primary.
pins[0].startY = primary.
pins[0].hotptY;
7108 primary.
pins[1].hotptX = 10;
7109 primary.
pins[1].hotptY = 40;
7110 primary.
pins[1].startX = primary.
pins[1].hotptX;
7111 primary.
pins[1].startY = primary.
pins[1].hotptY;
7115 alternate.
primitives.front().text =
"alternate cue";
7117 stale.
pins[0].hotptX = 0;
7118 stale.
pins[1].hotptX = 0;
7119 stale.
pins[0].startX = stale.
pins[0].hotptX;
7120 stale.
pins[1].startX = stale.
pins[1].hotptX;
7122 primary.
variants = { stale, alternate };
7134 page.
name =
"MIXED GRAPHICS";
7138 design.
sourceId =
"s593487-mixed-graphics";
7140 design.
pages.push_back( std::move( page ) );
7144 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
7145 schematic->SetProject( &manager.
Prj() );
7149 BOOST_REQUIRE_EQUAL( converted.
variants.size(), 3u );
7150 BOOST_CHECK( converted.
variants.front().synthesized );
7151 BOOST_REQUIRE_EQUAL( converted.
variants.front().primitives.size(), 1u );
7164 primary.
name =
"RESISTOR.Normal";
7169 primary.
pins.resize( 2 );
7170 primary.
pins[0].hotptX = -10;
7171 primary.
pins[0].hotptY = 10;
7172 primary.
pins[1].hotptX = 40;
7173 primary.
pins[1].hotptY = 10;
7180 alternate.
pins[0].hotptX = 10;
7181 alternate.
pins[0].hotptY = -10;
7182 alternate.
pins[1].hotptX = 10;
7183 alternate.
pins[1].hotptY = 40;
7184 primary.
variants.push_back( alternate );
7196 page.
name =
"SOURCE MATCHED GRAPHICS";
7200 design.
sourceId =
"source-matched-graphics";
7202 design.
pages.push_back( std::move( page ) );
7206 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
7207 schematic->SetProject( &manager.
Prj() );
7211 BOOST_REQUIRE_EQUAL( converted.
variants.size(), 1u );
7212 BOOST_REQUIRE_EQUAL( converted.
variants.front().primitives.size(), 1u );
7222 cached.
name =
"STACK.Normal";
7224 cached.
pins.resize( 3 );
7226 for(
size_t i = 0; i < cached.
pins.size(); ++i )
7228 cached.
pins[i].hotptX =
static_cast<int>( i ) * 10;
7229 cached.
pins[i].startX = cached.
pins[i].hotptX;
7241 page.
name =
"STACKED";
7245 design.
sourceId =
"s593487-stacked";
7247 design.
pages.push_back( std::move( page ) );
7251 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
7252 schematic->SetProject( &manager.
Prj() );
7255 path.push_back( root );
7259 std::map<wxString, VECTOR2I> positions;
7264 positions[
pin->GetNumber()] =
pin->GetPosition();
7268 BOOST_REQUIRE_EQUAL( positions.size(), 3u );
7269 BOOST_CHECK( positions[wxS(
"1" )] == positions[wxS(
"2" )] );
7270 BOOST_CHECK( positions[wxS(
"1" )] != positions[wxS(
"3" )] );
7281 stacked.
name =
"STACKED.Normal";
7287 load.
name =
"LOAD.Normal";
7291 auto makePlaced = [](
const std::string& aPackage,
const std::string& aReference,
int aX,
7292 std::initializer_list<uint32_t> aNets )
7296 placed.
sourcePackage = aPackage.substr( 0, aPackage.find(
'.' ) );
7302 for( uint32_t net : aNets )
7303 placed.
pins.push_back(
7304 ORCAD_PIN_INST{ .pinIndex =
static_cast<int16_t
>( pinIndex++ ), .x = aX, .wordB = net } );
7310 page.
name =
"DISTINCT STACKED NETS";
7311 page.
netmap = { { 1,
"LEFT" }, { 2,
"COMMON" }, { 3,
"RIGHT" } };
7312 page.
instances.push_back( makePlaced( stacked.
name,
"Q1", 100, { 1, 2 } ) );
7313 page.
instances.push_back( makePlaced( stacked.
name,
"Q2", 200, { 3, 2 } ) );
7314 page.
instances.push_back( makePlaced( load.
name,
"R1", 300, { 1 } ) );
7315 page.
instances.push_back( makePlaced( load.
name,
"R2", 400, { 3 } ) );
7318 design.
sourceId =
"distinct-stacked-nets";
7319 design.
symbols.emplace( stacked.
name, std::move( stacked ) );
7320 design.
symbols.emplace( load.
name, std::move( load ) );
7321 design.
pages.push_back( std::move( page ) );
7325 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
7326 schematic->SetProject( &manager.
Prj() );
7329 auto [consistent, checkable] =
7342 cached.
name =
"ORDER.Normal";
7344 cached.
pins.resize( 4 );
7346 for(
size_t i = 0; i < cached.
pins.size(); ++i )
7348 cached.
pins[i].hotptX =
static_cast<int>( i ) * 10;
7349 cached.
pins[i].startX = cached.
pins[i].hotptX;
7362 page.
name =
"REORDERED";
7366 design.
sourceId =
"s593487-reordered";
7368 design.
pages.push_back( std::move( page ) );
7372 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
7373 schematic->SetProject( &manager.
Prj() );
7376 BOOST_CHECK( !
reporter.GetMessages().Contains( wxS(
"pin positions mismatch" ) ) );
7379 path.push_back( root );
7382 std::map<int, VECTOR2I> positions;
7385 positions[std::stoi(
pin->GetNumber().ToStdString() )] =
pin->GetPosition();
7387 BOOST_REQUIRE_EQUAL( positions.size(), 4u );
7398 BOOST_CHECK( noConnect->
GetPosition() == positions[4] );
7404 auto makeDesign = []
7408 cached.
name =
"DETERMINISTIC.Normal";
7410 cached.
pins.resize( 3 );
7412 for(
size_t i = 0; i < cached.
pins.size(); ++i )
7413 cached.
pins[i].hotptX =
static_cast<int>( i ) * 10;
7424 page.
name =
"DETERMINISTIC";
7433 design.
sourceId =
"s593487-deterministic";
7435 design.
pages.push_back( std::move( page ) );
7444 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
7445 schematic->SetProject( &manager.
Prj() );
7448 path.push_back( root );
7451 std::string signature;
7455 signature +=
pin->GetNumber().ToStdString() +
"@" + std::to_string(
pin->GetPosition().x ) +
","
7456 + std::to_string(
pin->GetPosition().y ) +
";";
7459 signature +=
"variants=" + std::to_string( aDesign.symbols.at(
"DETERMINISTIC.Normal" ).variants.size() );
7475 definition.
name =
"MULTIPARTA.Normal";
7479 package.
name =
"MULTIPART";
7486 placed.
value =
"74HC125";
7489 placed.
props[
"Reference"] =
"U14";
7491 ORCAD_DISPLAY_PROP{ .name =
"Part Reference", .x = 30, .y = 10, .fontIdx = 0, .dispMode = 0x101 },
7492 ORCAD_DISPLAY_PROP{ .name =
"Value", .x = 30, .y = 20, .fontIdx = 0, .dispMode = 0x101 },
7496 page.
name =
"MULTIPART REFERENCE";
7500 design.
sourceId =
"multipart-reference";
7501 design.
symbols.emplace( definition.
name, std::move( definition ) );
7502 design.
packages.emplace( package.
name, std::move( package ) );
7503 design.
pages.push_back( std::move( page ) );
7507 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
7508 schematic->SetProject( &manager.
Prj() );
7511 path.push_back( root );
7521 BOOST_CHECK( displayedReference->
IsVisible() );
7534 definition.
name =
"TESTPOINT.Normal";
7536 definition.
props[
"Part Reference"] =
"TP119";
7539 package.
name =
"TESTPOINT";
7550 ORCAD_DISPLAY_PROP{ .name =
"Part Reference", .x = 30, .y = 10, .fontIdx = 0, .dispMode = 0x101 },
7554 page.
name =
"OCCURRENCE REFERENCE";
7558 design.
sourceId =
"occurrence-reference-display";
7559 design.
symbols.emplace( definition.
name, std::move( definition ) );
7560 design.
packages.emplace( package.
name, std::move( package ) );
7561 design.
pages.push_back( std::move( page ) );
7566 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
7567 schematic->SetProject( &manager.
Prj() );
7570 path.push_back( root );
7579 BOOST_CHECK( !templateReference || !templateReference->
IsVisible() );
7587 connectorDefinition.
name =
"BANANA, KEYSTONE-575-4.Normal";
7591 connectorPackage.
name =
"BANANA_KEYSTONE-575-4";
7601 ORCAD_DISPLAY_PROP{ .name =
"Part Reference", .x = 30, .fontIdx = 0, .dispMode = 0x100 },
7606 padDefinition.
name =
"PAD_2.Normal";
7610 padPackage.
name =
"PAD_2";
7614 pad.pkgName = padDefinition.
name;
7615 pad.sourcePackage = padPackage.
name;
7616 pad.reference =
"SW";
7619 pad.displayProps = {
7620 ORCAD_DISPLAY_PROP{ .name =
"Part Reference", .y = 26, .fontIdx = 0, .dispMode = 0x000 },
7621 ORCAD_DISPLAY_PROP{ .name =
"Reference", .x = 5, .y = 15, .fontIdx = 2, .dispMode = 0x100 },
7625 page.
name =
"SINGLE UNIT REFERENCE";
7629 design.
sourceId =
"single-unit-reference";
7630 design.
symbols.emplace( connectorDefinition.
name, std::move( connectorDefinition ) );
7631 design.
symbols.emplace( padDefinition.
name, std::move( padDefinition ) );
7632 design.
packages.emplace( connectorPackage.
name, std::move( connectorPackage ) );
7633 design.
packages.emplace( padPackage.
name, std::move( padPackage ) );
7634 design.
pages.push_back( std::move( page ) );
7638 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
7639 schematic->SetProject( &manager.
Prj() );
7642 path.push_back( root );
7648 BOOST_CHECK( connectorReference->
IsVisible() );
7650 BOOST_CHECK( !convertedConnector->
GetField( wxS(
"Part Reference" ) ) );
7656 BOOST_CHECK( padReference->
IsVisible() );
7665 thermistor.
name =
"THERMISTOR_2.Normal";
7667 thermistor.
pins.resize( 2 );
7668 thermistor.
pins[0].position = 0;
7669 thermistor.
pins[0].startX = 10;
7670 thermistor.
pins[0].hotptX = 10;
7671 thermistor.
pins[0].hotptY = -10;
7673 thermistor.
pins[1].position = 1;
7674 thermistor.
pins[1].startX = 10;
7675 thermistor.
pins[1].startY = 30;
7676 thermistor.
pins[1].hotptX = 10;
7677 thermistor.
pins[1].hotptY = 40;
7680 .kind =
ORCAD_PRIM_KIND::TEXT, .x1 = 12, .y1 = -8, .x2 = 30, .y2 = 7, .text =
"t", .fontIdx = 1 } );
7683 thermistor.
props[
"2ND PART FIELD"] =
"%";
7686 package.
name =
"THERMISTOR_2";
7689 package.
devices.push_back(
ORCAD_DEVICE{ .pinNumbers = {
"1",
"2" }, .pinIgnore = {
false,
false } } );
7695 placed.
value =
"3A";
7699 placed.
props[
"Assembly"] =
"Fitted";
7700 placed.
props[
"Datasheet"] =
"rt44.pdf";
7701 placed.
props[
"2nd Part Field"] =
"(OPT)";
7703 ORCAD_DISPLAY_PROP{ .name =
"Part Reference", .x = -20, .y = 10, .fontIdx = 0, .dispMode = 0x101 },
7704 ORCAD_DISPLAY_PROP{ .name =
"Reference", .x = 30, .y = 14, .fontIdx = 2, .dispMode = 0x001 },
7705 ORCAD_DISPLAY_PROP{ .name =
"Value", .x = 30, .y = 20, .fontIdx = 0, .dispMode = 0x101 },
7706 ORCAD_DISPLAY_PROP{ .name =
"PCB Footprint", .x = -20, .y = 20, .fontIdx = 2, .dispMode = 0x101 },
7707 ORCAD_DISPLAY_PROP{ .name =
"2nd Part Field", .x = -20, .y = 30, .fontIdx = 0, .dispMode = 0x101 },
7712 page.
name =
"RT44 FIDELITY";
7717 resistor.
value =
"100k";
7723 ORCAD_DISPLAY_PROP{ .name =
"Value", .x = 20, .y = 10, .fontIdx = 3, .dispMode = 0x101 },
7724 ORCAD_DISPLAY_PROP{ .name =
"PCB Footprint", .x = 20, .y = 20, .fontIdx = 4, .dispMode = 0x101 },
7730 q9Definition.
name =
"IRF7416_0.Normal";
7743 connectorDefinition.
name =
"CON24_46.Normal";
7746 connectorPackage.
name =
"CON24_46";
7747 connectorPackage.
refDes =
"J";
7748 connectorPackage.
devices.front().pinNumbers = {
"1",
"2" };
7768 blankMappedDefinition.
name =
"BLANK_MAPPED.Normal";
7770 blankMappedDefinition.
pins[0].name =
"1";
7771 blankMappedDefinition.
pins[1].name =
"2";
7773 blankMappedPackage.
name =
"BLANK_MAPPED";
7774 blankMappedPackage.
devices.front().pinNumbers = {
"",
"" };
7779 blankMapped.
x = 1800;
7780 blankMapped.
y = 500;
7782 page.
instances.push_back( blankMapped );
7785 dualPinTextDefinition.
name =
"DUAL_PIN_TEXT.Normal";
7788 dualPinTextPackage.
name =
"DUAL_PIN_TEXT";
7789 dualPinTextPackage.
devices.front().pinNumbers = {
"1",
"2" };
7794 dualPinText.
x = 2000;
7796 page.
instances.push_back( dualPinText );
7801 comment.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
7804 .text =
".5W\nNEXT", .fontIdx = 1 } );
7805 page.
graphics.push_back( std::move( comment ) );
7809 ercMarker.
name =
"ERC";
7812 page.
ercObjects.push_back( std::move( ercMarker ) );
7815 design.
sourceId =
"s593487-rt44-fidelity";
7818 ORCAD_FONT{ .height = -9, .width = 4, .pitchAndFamily = 0x31, .face =
"Courier New" } );
7821 design.
symbols.emplace( thermistor.
name, thermistor );
7822 design.
symbols.emplace( q9Definition.
name, q9Definition );
7823 design.
symbols.emplace( connectorDefinition.
name, connectorDefinition );
7824 design.
symbols.emplace( blankMappedDefinition.
name, blankMappedDefinition );
7825 design.
symbols.emplace( dualPinTextDefinition.
name, dualPinTextDefinition );
7827 design.
packages.emplace( connectorPackage.
name, connectorPackage );
7828 design.
packages.emplace( blankMappedPackage.
name, blankMappedPackage );
7829 design.
packages.emplace( dualPinTextPackage.
name, dualPinTextPackage );
7831 std::vector<uint8_t> packageStream;
7832 appendLe16( packageStream, 1 );
7834 appendLe16( packageStream, 0 );
7835 appendLzt( packageStream,
"THERMISTOR_2" );
7836 appendLzt( packageStream,
"" );
7837 appendLe16( packageStream, 1 );
7838 appendLzt( packageStream,
"THERMISTOR_2.Normal" );
7839 appendLe16( packageStream, 1 );
7841 appendLe16( packageStream, 0 );
7842 appendLzt( packageStream,
"THERMISTOR_2.Normal" );
7843 appendLzt( packageStream,
"" );
7844 appendLe32( packageStream, 0 );
7845 appendLe16( packageStream, 0 );
7847 for(
int coordinate : { 0, 0, 20, 30 } )
7848 appendLe16( packageStream,
static_cast<uint16_t
>( coordinate ) );
7850 appendLe16( packageStream, 0 );
7851 appendLe16( packageStream, 0 );
7852 appendLzt( packageStream,
"" );
7853 appendLzt( packageStream,
"" );
7854 appendLzt( packageStream,
"RT" );
7855 appendLzt( packageStream,
"" );
7856 appendLe16( packageStream, 6 );
7858 appendLe16( packageStream, 0 );
7859 appendLzt( packageStream,
"THERMISTOR_2" );
7860 appendLzt( packageStream,
"" );
7861 appendLzt( packageStream,
"RT" );
7862 appendLzt( packageStream,
"" );
7863 appendLzt( packageStream,
"2920" );
7864 appendLe16( packageStream, 0 );
7866 std::map<std::string, ORCAD_SYMBOL_DEF> packageSymbols;
7867 std::map<std::string, ORCAD_PACKAGE> packageDefinitions;
7869 packageDefinitions );
7871 design.
pages.push_back( std::move( page ) );
7875 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
7876 schematic->SetProject( &manager.
Prj() );
7879 path.push_back( root );
7881 const SCH_TEXT* commentText =
nullptr;
7886 &&
static_cast<const SCH_TEXT*
>( item )->
GetText() == wxS(
".5W\nNEXT" ) )
7887 commentText =
static_cast<const SCH_TEXT*
>( item );
7891 BOOST_CHECK_CLOSE( commentText->
GetLineSpacing(), 5.0 / 6.0, 0.1 );
7909 cueText =
static_cast<const SCH_TEXT*
>( &item );
7911 cueDegree =
static_cast<const SCH_SHAPE*
>( &item );
7925 int degreeRadius = cueDegree->
GetRadius();
7935 int valueBaseline = fieldBaseline;
7966 int sourceFontSize =
schIUScale.mmToIU( 1.70 );
7967 int sourceFontWidth =
schIUScale.mmToIU( 0.95 );
7980 BOOST_CHECK( !reference->
IsItalic() );
7982 BOOST_CHECK( !footprint->
IsItalic() );
7984 size_t secondPartFields = std::count_if(
7986 [](
const SCH_FIELD& aField ) { return aField.GetName().CmpNoCase( wxS(
"2nd Part Field" ) ) == 0; } );
7991 BOOST_CHECK( secondPartField->
IsVisible() );
8001 r31Cue =
static_cast<const SCH_TEXT*
>( &item );
8015 BOOST_CHECK( r31Reference->
IsVisible() );
8018 OrcadDbuToIu( 920, 690 ).y + pageOffset.
y + fieldBaseline );
8021 BOOST_CHECK( !r31Value->
IsItalic() );
8022 BOOST_CHECK( r31Footprint->
IsItalic() );
8032 std::set<VECTOR2I> noConnects;
8035 noConnects.insert( item->GetPosition() );
8043 BOOST_REQUIRE_EQUAL( jca3->
GetPins().size(), 2u );
8049 BOOST_REQUIRE_EQUAL( blankMappedSymbol->
GetPins().size(), 2u );
8052 size_t visiblePinNumbers = 0;
8053 std::set<wxString> blankMappedNumbers = { wxS(
"1" ), wxS(
"2" ) };
8058 && blankMappedNumbers.contains(
static_cast<const SCH_TEXT&
>( item ).
GetText() ) )
8060 ++visiblePinNumbers;
8074 BOOST_CHECK_GT(
pin->GetNameTextSize(), 0 );
8075 BOOST_CHECK_GT(
pin->GetNumberTextSize(), 0 );
8082 ||
static_cast<const SCH_TEXT&
>( item ).GetText() == wxS(
"2" ) ) )
8084 BOOST_ERROR(
"Pin data duplicated as SCH_TEXT" );
8090 const SCH_TEXT* mirroredCue =
nullptr;
8095 mirroredCue =
static_cast<const SCH_TEXT*
>( &item );
8113 TEMP_TEST_FILE specctra( wxS(
"qa_orcad_specctra_impostor.dsn" ),
8114 wxS(
"(pcb \"impostor.dsn\"\n (parser\n (string_quote \")\n )\n)\n" ) );
8117 BOOST_CHECK( !m_plugin.CanReadSchematicFile( specctra.m_path ) );
8123 wxFileName missing( wxFileName::GetTempDir(), wxS(
"qa_orcad_does_not_exist.dsn" ) );
8126 BOOST_CHECK( !m_plugin.CanReadSchematicFile( missing.GetFullPath() ) );
8132 TEMP_TEST_FILE textFile( wxS(
"qa_orcad_impostor.txt" ), wxS(
"Just some text, not a schematic.\n" ) );
8135 BOOST_CHECK( !m_plugin.CanReadSchematicFile( textFile.m_path ) );
8146 auto notSpace = [](
unsigned char c )
8148 return !std::isspace( c );
8150 aText.erase( aText.begin(), std::find_if( aText.begin(), aText.end(), notSpace ) );
8151 aText.erase( std::find_if( aText.rbegin(), aText.rend(), notSpace ).base(), aText.end() );
8153 if( aText.size() >= 2 && aText.front() ==
'"' && aText.back() ==
'"' )
8154 aText = aText.substr( 1, aText.size() - 2 );
8160static std::vector<std::string>
splitRefs(
const std::string& aCell )
8162 std::vector<std::string> refs;
8165 for(
char c : aCell )
8172 refs.push_back( r );
8185 refs.push_back( r );
8193 std::set<std::string> refs;
8194 std::ifstream in( aPath );
8198 while( std::getline( in, line ) )
8200 if( !line.empty() && line.back() ==
'\r' )
8203 std::vector<std::string> cols;
8206 for(
char c : line )
8210 cols.push_back( cell );
8219 cols.push_back( cell );
8224 for(
size_t i = 0; i < cols.size(); ++i )
8226 if(
trimCell( cols[i] ) ==
"Reference" )
8228 refCol =
static_cast<int>( i );
8236 if( refCol <
static_cast<int>( cols.size() ) )
8249 std::set<std::string> refs;
8250 std::ifstream in( aPath );
8253 while( std::getline( in, line ) )
8255 if( line.rfind(
".ADD_COM", 0 ) != 0 )
8259 std::string rest =
trimCell( line.substr( 8 ) );
8262 for(
char c : rest )
8264 if( std::isspace(
static_cast<unsigned char>( c ) ) )
8282 std::set<std::string> refs;
8295 wxString ref = symbol->
GetRef( &
path,
false );
8298 if( ref.IsEmpty() || ref.StartsWith( wxS(
"#" ) ) || ref.EndsWith( wxS(
"?" ) ) )
8301 refs.insert( std::string( ref.ToUTF8() ) );
8309static std::string
terminalToken(
const std::string& aRef,
const std::string& aPin )
8319 std::vector<std::set<std::string>> nets;
8320 std::set<std::string> current;
8321 std::ifstream in( aPath );
8326 if( current.size() >= 2 )
8327 nets.push_back( current );
8332 while( std::getline( in, line ) )
8334 if( !line.empty() && line.back() ==
'\r' )
8337 bool addTer = line.rfind(
".ADD_TER", 0 ) == 0;
8338 bool ter = line.rfind(
".TER", 0 ) == 0;
8339 bool cont = !line.empty() && std::isspace(
static_cast<unsigned char>( line[0] ) );
8341 if( line.rfind(
".END", 0 ) == 0 )
8347 if( addTer || ter || cont )
8349 std::istringstream ss( addTer ? line.substr( 8 ) : ter ? line.substr( 4 ) : line );
8350 std::string ref,
pin;
8352 if( ss >> ref >>
pin )
8365 std::vector<std::set<std::string>>* aInconsistent )
8370 std::map<std::string, int> pinNet;
8377 for(
SCH_ITEM* item : subgraph->GetItems() )
8388 wxString ref = symbol->
GetRef( &subgraph->GetSheet(),
false );
8390 if( ref.IsEmpty() || ref.StartsWith( wxS(
"#" ) ) || ref.EndsWith( wxS(
"?" ) ) )
8393 pinNet[
terminalToken( std::string( ref.ToUTF8() ), std::string(
pin->GetNumber().ToUTF8() ) )] = netId;
8402 const std::set<std::string>* terminals;
8406 std::vector<CHECKED_NET> checkedNets;
8407 std::map<int, int> sourceNetsPerImportedNet;
8409 for(
const std::set<std::string>& net : aNets )
8414 for(
const std::string& term : net )
8416 auto it = pinNet.find( term );
8418 if( it != pinNet.end() )
8420 ids.insert( it->second );
8427 if( ids.size() == 1 )
8428 sourceNetsPerImportedNet[*ids.begin()]++;
8430 checkedNets.push_back( { &net, std::move( ids ) } );
8436 for(
const CHECKED_NET& net : checkedNets )
8438 bool exact = net.ids.size() == 1 && sourceNetsPerImportedNet[*net.ids.begin()] == 1;
8442 else if( aInconsistent )
8443 aInconsistent->push_back( *net.terminals );
8446 return { consistent,
static_cast<int>( checkedNets.size() ) };
8459 for(
SCH_ITEM* item : subgraph->GetItems() )
8467 if( symbol && symbol->
GetRef( &subgraph->GetSheet(),
false ) == aReference
8468 &&
pin->GetNumber() == aPinNumber )
8481static std::set<std::string>
expectedRefsFor(
const std::filesystem::path& aDsn, std::string& aSource )
8483 for(
const char* ext : {
".NET",
".net",
".BOM",
".bom" } )
8485 std::filesystem::path candidate = aDsn;
8486 candidate.replace_extension( ext );
8488 if( std::filesystem::exists( candidate ) )
8490 aSource = candidate.filename().string();
8492 bool isNet = std::string( ext ) ==
".NET" || std::string( ext ) ==
".net";
8504 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
8506 if( !corpusEnv || !*corpusEnv )
8508 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping OrCAD corpus validation." );
8512 namespace fs = std::filesystem;
8513 fs::path root( corpusEnv );
8515 BOOST_REQUIRE_MESSAGE( fs::exists( root ),
"KICAD_ORCAD_CORPUS path does not exist." );
8517 std::vector<fs::path> designs;
8519 for(
auto it = fs::recursive_directory_iterator( root, fs::directory_options::skip_permission_denied );
8520 it != fs::recursive_directory_iterator(); ++it )
8522 if( !it->is_regular_file() )
8525 std::string ext = it->path().extension().string();
8526 std::transform( ext.begin(), ext.end(), ext.begin(),
8527 [](
unsigned char c )
8529 return std::tolower( c );
8533 designs.push_back( it->path() );
8536 std::sort( designs.begin(), designs.end() );
8538 BOOST_TEST_MESSAGE(
"OrCAD corpus: " << designs.size() <<
" .DSN files under " << root );
8540 int imported = 0, crashed = 0, unsupported = 0, rejected = 0, checked = 0;
8541 unsigned int totalExpected = 0, totalMatched = 0, totalMissing = 0, totalExtra = 0;
8542 int netConsistent = 0, netCheckable = 0, netTotal = 0;
8543 uint64_t importedPages = 0, importedComponents = 0, importedPowerSymbols = 0;
8544 uint64_t importedPins = 0, importedWires = 0, importedBuses = 0;
8545 uint64_t importedLabels = 0, importedShapes = 0, importedTexts = 0, importedBitmaps = 0;
8547 const char* debugEnv = std::getenv(
"KICAD_ORCAD_DEBUG" );
8548 std::string debugFilter = debugEnv ? debugEnv :
"";
8549 const char* filterEnv = std::getenv(
"KICAD_ORCAD_FILTER" );
8550 std::string designFilter = filterEnv ? filterEnv :
"";
8552 for(
const fs::path& dsn : designs )
8554 std::string rel = fs::relative( dsn, root ).string();
8556 if( !designFilter.empty() && rel.find( designFilter ) == std::string::npos )
8559 BOOST_TEST_INFO_SCOPE(
"OrCAD source: " << rel );
8562 uint64_t perDesignPages = 0, perDesignComponents = 0, perDesignPowerSymbols = 0;
8563 uint64_t perDesignPins = 0, perDesignWires = 0, perDesignBuses = 0;
8564 uint64_t perDesignLabels = 0, perDesignShapes = 0, perDesignTexts = 0;
8565 uint64_t perDesignBitmaps = 0;
8566 uint64_t perDesignRedWires = 0;
8567 uint64_t perDesignVddmPowerSymbols = 0;
8569 bool debug = !debugFilter.empty() && rel.find( debugFilter ) != std::string::npos;
8578 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
8580 schematic->SetProject( &manager.
Prj() );
8581 schematic->CurrentSheet().clear();
8582 schematic->CurrentSheet().push_back( &schematic->Root() );
8590 schematic->CurrentSheet().UpdateAllScreenReferences();
8592 catch(
const std::exception& e )
8595 if( std::string( e.what() ).find(
"pre-2003" ) != std::string::npos )
8618 switch( item->Type() )
8623 wxString ref = symbol->
GetRef( &
path,
false );
8625 if( ref.StartsWith( wxS(
"#" ) ) )
8627 ++importedPowerSymbols;
8628 ++perDesignPowerSymbols;
8631 ++perDesignVddmPowerSymbols;
8635 ++importedComponents;
8636 ++perDesignComponents;
8639 size_t pinCount = symbol->
GetPins( &
path ).size();
8640 importedPins += pinCount;
8641 perDesignPins += pinCount;
8660 ++perDesignRedWires;
8693 BOOST_TEST_MESSAGE(
" AUDIT " << rel <<
"|pages=" << perDesignPages <<
"|components=" << perDesignComponents
8694 <<
"|power=" << perDesignPowerSymbols <<
"|pins=" << perDesignPins
8695 <<
"|wires=" << perDesignWires <<
"|buses=" << perDesignBuses
8696 <<
"|labels=" << perDesignLabels <<
"|shapes=" << perDesignShapes
8697 <<
"|texts=" << perDesignTexts <<
"|bitmaps=" << perDesignBitmaps );
8699 if( rel ==
"allegro/beagleboard-xm/SCH/BeagleBoard-xM_ORCAD.DSN" )
8707 ==
"allegro/OpenCellular-LED/Rev-C/schematic/"
8708 "OpenCellular_Connect-1_LED_Life-3_Schematic.DSN" )
8714 ==
"orcad/OpenCellular-GBC-Elgon_ARM/Rev-A/schematics/"
8715 "CN81XX_GBCV2_sch_0530.DSN" )
8722 << std::string(
reporter.GetMessages().ToUTF8() ) );
8734 std::set<std::string> missing, extra;
8735 std::set_difference(
expected.begin(),
expected.end(), got.begin(), got.end(),
8736 std::inserter( missing, missing.begin() ) );
8737 std::set_difference( got.begin(), got.end(),
expected.begin(),
expected.end(),
8738 std::inserter( extra, extra.begin() ) );
8740 unsigned int matched =
static_cast<unsigned int>(
expected.size() - missing.size() );
8744 totalMatched += matched;
8745 totalMissing += missing.size();
8746 totalExtra += extra.size();
8749 <<
int( 100.0 * matched /
expected.size() ) <<
"%), extra " << extra.size()
8750 <<
" [" << source <<
"]" );
8754 for(
const std::string& ref : missing )
8757 for(
const std::string& ref : extra )
8762 std::filesystem::path net = dsn;
8763 net.replace_extension( source.size() >= 4 && source.substr( source.size() - 4 ) ==
".net" ?
".net" :
".NET" );
8765 if( std::filesystem::exists( net ) )
8771 std::vector<std::set<std::string>> inconsistent;
8772 auto [consistent, checkableNets] =
checkConnectivity( *schematic, nets, &inconsistent );
8773 netConsistent += consistent;
8774 netCheckable += checkableNets;
8775 netTotal +=
static_cast<int>( nets.size() );
8778 <<
" nets consistent" );
8782 for(
const std::set<std::string>& terminals : inconsistent )
8786 for(
const std::string& terminal : terminals )
8788 if( !joined.empty() )
8802 BOOST_TEST_MESSAGE(
" designs: " << designs.size() <<
" imported: " << imported <<
" crashed: " << crashed
8803 <<
" unsupported: " << unsupported <<
" rejected: " << rejected );
8805 << importedPages <<
" components " << importedComponents <<
" power " << importedPowerSymbols
8806 <<
" pins " << importedPins <<
" wires " << importedWires <<
" buses " << importedBuses
8807 <<
" labels " << importedLabels <<
" shapes " << importedShapes <<
" texts " << importedTexts
8808 <<
" bitmaps " << importedBitmaps );
8812 BOOST_TEST_MESSAGE(
" refdes coverage: " << totalMatched <<
"/" << totalExpected <<
" ("
8813 <<
int( 100.0 * totalMatched / totalExpected )
8814 <<
"%) missing: " << totalMissing <<
" extra: " << totalExtra );
8819 BOOST_TEST_MESSAGE(
" net connectivity: " << netConsistent <<
"/" << netCheckable <<
" ("
8820 <<
int( 100.0 * netConsistent / netCheckable ) <<
"%)" );
8824 BOOST_CHECK_MESSAGE( crashed == 0, crashed <<
" design(s) crashed during import." );
8826 const char* snapshotEnv = std::getenv(
"KICAD_ORCAD_CORPUS_SNAPSHOT" );
8829 if( designFilter.empty() )
8830 BOOST_REQUIRE_MESSAGE( checked > 0,
"No ground-truth .BOM/.NET companions were validated." );
8832 if( designFilter.empty() && snapshotEnv && *snapshotEnv )
8842 BOOST_CHECK_GE( 100.0 * totalMatched / totalExpected, 95.0 );
8848 BOOST_CHECK_GE( 100.0 * netCheckable / netTotal, 80.0 );
8854static std::filesystem::path
findCorpusDesign(
const std::filesystem::path& aRoot,
const std::string& aFileName )
8856 for(
const std::filesystem::directory_entry& entry : std::filesystem::recursive_directory_iterator( aRoot ) )
8858 if( entry.is_regular_file() && entry.path().filename() == aFileName )
8859 return entry.path();
8868 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
8870 if( !corpusEnv || !*corpusEnv )
8873 std::filesystem::path dsn =
8874 std::filesystem::path( corpusEnv ) /
"PADS" /
"skyworks-eval" /
"SI34061FB12V4KIT"
8875 /
"si34061-evb-ext_1.7.1.20220111" /
"schematic" /
"SI34061-EVB-EXT.DSN";
8877 if( !std::filesystem::exists( dsn ) )
8879 BOOST_TEST_MESSAGE(
"SI34061-EVB-EXT 12 V design not present; skipping CIS variant check." );
8883 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
8886 schematic->SetProject( &manager.
Prj() );
8887 schematic->CurrentSheet().clear();
8888 schematic->CurrentSheet().push_back( &schematic->Root() );
8893 std::map<wxString, SCH_SYMBOL*> symbols;
8900 symbols.emplace( symbol->
GetRef( &
path,
false ), symbol );
8909 wxS(
"NVMFS5C680NLT1G" ) );
8913 wxS(
"LABEL-Si34061-EVB-EXT-BOM-R1.7-12V" ) );
8914 BOOST_REQUIRE( symbols[wxS(
"U1" )]->GetField( wxS(
"Voltage" ) ) );
8915 BOOST_CHECK_EQUAL( symbols[wxS(
"U1" )]->GetField( wxS(
"Voltage" ) )->GetText(), wxS(
"60V" ) );
8919 BOOST_CHECK( symbols[wxS(
"D15" )]->GetDNP() );
8920 BOOST_CHECK( symbols[wxS(
"R35" )]->GetDNP() );
8921 BOOST_CHECK( symbols[wxS(
"TP1" )]->GetDNP() );
8925 bool variantNameFound =
false;
8929 const wxString&
text =
static_cast<SCH_TEXT*
>( item )->GetText();
8930 BOOST_CHECK_NE(
text, wxS(
"<Core Design>" ) );
8931 variantNameFound |=
text == wxS(
"12V" );
8934 BOOST_CHECK( variantNameFound );
8935 BOOST_CHECK_EQUAL(
path.LastScreen()->GetTitleBlock().GetComment( 1 ), wxS(
"Variant Name: 12V" ) );
8942 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
8944 if( !corpusEnv || !*corpusEnv )
8947 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"PROJET INDUS.DSN" );
8952 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
8955 schematic->SetProject( &manager.
Prj() );
8956 schematic->CurrentSheet().clear();
8957 schematic->CurrentSheet().push_back( &schematic->Root() );
8962 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
8963 size_t excluded = 0;
8964 size_t excludedSymbols = 0;
8968 excluded +=
path.GetExcludedFromBoard();
8970 if( !
path.GetExcludedFromBoard() )
8976 BOOST_CHECK(
static_cast<SCH_SYMBOL*
>( item )->GetExcludedFromBoard() );
8982 BOOST_CHECK_GT( excludedSymbols, 0u );
8988 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
8990 if( !corpusEnv || !*corpusEnv )
8993 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC1987A-2.DSN" );
8998 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
9001 schematic->SetProject( &manager.
Prj() );
9002 schematic->CurrentSheet().clear();
9003 schematic->CurrentSheet().push_back( &schematic->Root() );
9008 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
9009 BOOST_REQUIRE_EQUAL( sheets.size(), 1u );
9015 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
9017 if( !corpusEnv || !*corpusEnv )
9025 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
9028 schematic->SetProject( &manager.
Prj() );
9029 schematic->CurrentSheet().clear();
9030 schematic->CurrentSheet().push_back( &schematic->Root() );
9035 auto [consistent, checkable] =
9045 std::map<std::string, std::vector<std::string>> uuids;
9049 std::ostringstream identity;
9052 identity << item.
Type() <<
':' << item.
GetLayer() <<
':' << position.
x <<
',' << position.
y
9053 <<
':' << bounds.
GetX() <<
',' << bounds.
GetY() <<
',' << bounds.
GetWidth() <<
','
9056 auto text = [&](
const wxString& value )
9058 const std::string utf8 = value.ToStdString( wxConvUTF8 );
9059 identity <<
':' << utf8.size() <<
':' << utf8;
9062 if(
const auto* line =
dynamic_cast<const SCH_LINE*
>( &item ) )
9064 identity <<
':' << line->GetEndPoint().x <<
',' << line->GetEndPoint().y;
9067 if(
const auto* label =
dynamic_cast<const EDA_TEXT*
>( &item ) )
9069 text( label->GetText() );
9070 identity <<
':' << label->GetTextAngleDegrees() <<
':' << label->GetTextWidth() <<
','
9071 << label->GetTextHeight();
9074 if(
const auto* shape =
dynamic_cast<const SCH_SHAPE*
>( &item ) )
9076 identity << ':' << static_cast<int>( shape->GetShape() ) <<
':' << shape->GetStart().x
9077 <<
',' << shape->GetStart().y <<
':' << shape->GetEnd().x <<
',' << shape->GetEnd().y;
9080 identity <<
':' << shape->GetPolyShape().Format();
9082 identity <<
':' << shape->GetArcMid().x <<
',' << shape->GetArcMid().y;
9084 identity <<
':' << shape->GetBezierC1().x <<
',' << shape->GetBezierC1().y <<
':'
9085 << shape->GetBezierC2().x <<
',' << shape->GetBezierC2().y;
9088 if(
const auto* symbol =
dynamic_cast<const SCH_SYMBOL*
>( &item ) )
9091 text( symbol->GetLibId().Format() );
9092 identity <<
':' << symbol->GetUnitSelection( &
path ) <<
':' << symbol->GetOrientation();
9095 if(
const auto*
pin =
dynamic_cast<const SCH_PIN*
>( &item ) )
9099 identity <<
':' <<
pin->GetUnit() <<
':' <<
pin->GetBodyStyle() <<
':'
9100 <<
static_cast<int>(
pin->GetOrientation() ) <<
':' <<
pin->GetLength();
9103 if(
const auto* sheet =
dynamic_cast<const SCH_SHEET*
>( &item ) )
9105 text( sheet->GetName() );
9106 text( sheet->GetFileName() );
9109 return identity.str();
9119 const std::string
name = sheet->
GetName().ToStdString( wxConvUTF8 );
9120 scope += std::to_string(
name.size() ) +
':' +
name +
'/';
9131 const std::string identity = scope + itemIdentity( *item,
path );
9134 if(
auto* symbol =
dynamic_cast<SCH_SYMBOL*
>( item ) )
9136 for(
const std::unique_ptr<SCH_PIN>&
pin : symbol->GetRawPins() )
9137 uuids[identity +
"/pin/" + itemIdentity( *
pin,
path )].push_back(
pin->m_Uuid.AsStdString() );
9139 else if(
const auto* child =
dynamic_cast<const SCH_SHEET*
>( item ) )
9142 uuids[identity +
"/pin/" + itemIdentity( *
pin,
path )].push_back(
pin->m_Uuid.AsStdString() );
9148 for(
auto& [identity, values] : uuids )
9149 std::sort( values.begin(), values.end() );
9156 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
9158 if( !corpusEnv || !*corpusEnv )
9160 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping OrCAD determinism check." );
9168 BOOST_TEST_MESSAGE(
"mc33163.dsn not present in corpus; skipping OrCAD determinism check." );
9172 auto importUuids = [&](
const std::filesystem::path& aDsn )
9174 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
9177 schematic->SetProject( &manager.
Prj() );
9178 schematic->CurrentSheet().clear();
9179 schematic->CurrentSheet().push_back( &schematic->Root() );
9186 const auto first = importUuids( dsn );
9187 const auto second = importUuids( dsn );
9190 BOOST_REQUIRE_EQUAL( first.size(), second.size() );
9192 for(
const auto& [identity, values] : first )
9196 const auto found = second.find( identity );
9207 page.
name =
"ALIASES";
9208 page.
netmap[1] =
"N12345";
9215 page.
wires.push_back( std::move( wire ) );
9218 design.
sourceId =
"secondary-source-aliases";
9219 design.
pages.push_back( std::move( page ) );
9226 path.push_back( root );
9230 finalName = item->Connection( &
path )->Name();
9235 std::set<wxString> originalNames;
9245 BOOST_CHECK( originalNames == std::set<wxString>( {
"N12345",
"TABLE_ALIAS",
"PRIMARY",
"SECONDARY" } ) );
9251 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
9253 if( !corpusEnv || !*corpusEnv )
9255 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping generated net-name check." );
9259 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"CutiePi_V2.3-20210409.DSN" );
9263 BOOST_TEST_MESSAGE(
"CutiePi_V2.3-20210409.DSN not present in corpus; skipping generated "
9264 "net-name check." );
9268 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
9271 schematic->SetProject( &manager.
Prj() );
9272 schematic->CurrentSheet().clear();
9273 schematic->CurrentSheet().push_back( &schematic->Root() );
9281 for(
const auto& [sourceName, reference, number] :
9282 { std::tuple{ wxString(
"N12720539" ), wxString(
"D10" ), wxString(
"A" ) },
9283 std::tuple{ wxString(
"N132252170" ), wxString(
"D23" ), wxString(
"1" ) } } )
9286 BOOST_CHECK_NE( netName, sourceName );
9295 BOOST_CHECK( !entry.
terminals.empty() );
9300 BOOST_CHECK( found );
9302 for(
const SCH_SHEET_PATH& sheet : schematic->BuildSheetListSortedByPageNumbers() )
9304 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
9308 BOOST_CHECK_NE( label->GetText(), sourceName );
9310 || label->GetTextColor().a > 0 );
9320 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
9322 if( !corpusEnv || !*corpusEnv )
9324 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping Capture net/unit regression check." );
9328 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"BEAGLEBONEBLK_C3.DSN" );
9332 BOOST_TEST_MESSAGE(
"BEAGLEBONEBLK_C3.DSN not present in corpus; skipping Capture net/unit "
9333 "regression check." );
9337 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
9340 schematic->SetProject( &manager.
Prj() );
9341 schematic->CurrentSheet().clear();
9342 schematic->CurrentSheet().push_back( &schematic->Root() );
9347 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
9348 schematic->ConnectionGraph()->Recalculate( sheets,
true );
9350 std::map<std::tuple<std::string, std::string, std::string>,
int> terminalNets;
9353 for(
const auto& [key, subgraphs] : schematic->ConnectionGraph()->GetNetMap() )
9357 std::string page = subgraph->GetSheet().LastScreen()->GetFileName().ToStdString();
9359 for(
SCH_ITEM* item : subgraph->GetItems() )
9369 terminalNets[{ page, symbol->
GetRef( &subgraph->GetSheet(),
false ).ToStdString(),
9370 pin->GetNumber().ToStdString() }] = netId;
9378 auto findNet = [&](
const std::string& aPage,
const std::string& aRef,
const std::string& aPin )
9380 for(
const auto& [terminal,
id] : terminalNets )
9382 if( std::get<0>( terminal ).
find( aPage ) != std::string::npos && std::get<1>( terminal ) == aRef
9383 && std::get<2>( terminal ) == aPin )
9392 int ground = findNet(
"AM335x 2_3, USB",
"J1",
"1" );
9393 int rx = findNet(
"AM335x 2_3, USB",
"J1",
"4" );
9394 int tx = findNet(
"AM335x 2_3, USB",
"J1",
"5" );
9396 BOOST_REQUIRE_NE( ground, -1 );
9397 BOOST_REQUIRE_NE( rx, -1 );
9398 BOOST_REQUIRE_NE( tx, -1 );
9399 BOOST_CHECK_NE( ground, rx );
9400 BOOST_CHECK_NE( ground, tx );
9401 BOOST_CHECK_NE( rx, tx );
9403 BOOST_CHECK_EQUAL( findNet(
"LED, Config",
"D3",
"1" ), findNet(
"LED, Config",
"Q1",
"3" ) );
9404 BOOST_CHECK_EQUAL( findNet(
"LED, Config",
"R77",
"1" ), findNet(
"LED, Config",
"Q1",
"5" ) );
9406 std::set<int> q1Units;
9407 std::set<wxString> q1ShownReferences;
9411 if(
path.LastScreen()->GetFileName().Find( wxS(
"LED, Config" ) ) == wxNOT_FOUND )
9418 if( symbol->
GetRef( &
path,
false ) == wxS(
"Q1" ) )
9420 q1Units.insert( symbol->
GetUnit() );
9421 q1ShownReferences.insert( symbol->
GetRef( &
path,
true ) );
9426 const std::set<int> expectedUnits = { 1, 2 };
9429 const std::set<wxString> expectedShownReferences = { wxS(
"Q1" ) };
9431 expectedShownReferences.begin(), expectedShownReferences.end() );
9437 const char* corpus = std::getenv(
"KICAD_ORCAD_CORPUS" );
9439 if( !corpus || !*corpus )
9455 bool memberFound =
false;
9456 bool bundleFound =
false;
9457 wxString actualName =
terminalNetName( schematic, wxS(
"J10" ), wxS(
"25" ) );
9462 if( entry.
view != wxS(
"Hierarchical Interconnects" ) )
9470 BOOST_CHECK( !entry.
terminals.empty() );
9479 BOOST_CHECK( !entry.
itemUuids.empty() );
9480 std::set<std::string> mappedTerminals;
9487 mappedTerminals.insert(
terminalToken( symbol->GetRef( &
path,
false ).ToStdString(),
9491 const std::set<std::string>
expected = {
"J10.25",
"R77.2",
"RP16.7",
"U10.R8" };
9492 BOOST_CHECK( mappedTerminals ==
expected );
9495 BOOST_CHECK( memberFound );
9496 BOOST_CHECK( bundleFound );
9502 const char* corpus = std::getenv(
"KICAD_ORCAD_CORPUS" );
9504 if( !corpus || !*corpus )
9531 BOOST_CHECK( found );
9533 for(
const wxString& reference : { wxString(
"U1" ), wxString(
"U2" ), wxString(
"U4" ) } )
9540 const char* corpus = std::getenv(
"KICAD_ORCAD_CORPUS" );
9542 if( !corpus || !*corpus )
9545 std::filesystem::path dsn =
findCorpusDesign( corpus,
"meta_carrier_sch_rev1.dsn" );
9563 || entry.
occurrence != std::vector<wxString>( {
"TOP",
"9136400",
"TILE_AD9523" } ) )
9581 BOOST_CHECK( found );
9587 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
9589 if( !corpusEnv || !*corpusEnv )
9591 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping named wireless-pin check." );
9595 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"CURRENT_SENSOR.DSN" );
9599 BOOST_TEST_MESSAGE(
"CURRENT_SENSOR.DSN not present in corpus; skipping named wireless-pin check." );
9603 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
9606 schematic->SetProject( &manager.
Prj() );
9607 schematic->CurrentSheet().clear();
9608 schematic->CurrentSheet().push_back( &schematic->Root() );
9613 wxString netName =
terminalNetName( *schematic, wxS(
"U1" ), wxS(
"7" ) );
9617 bool mapped =
false;
9625 BOOST_CHECK( !entry.
terminals.empty() );
9630 BOOST_CHECK( mapped );
9636 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
9638 if( !corpusEnv || !*corpusEnv )
9641 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"reComputer J202_V1.0.DSN" );
9646 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
9649 schematic->SetProject( &manager.
Prj() );
9650 schematic->CurrentSheet().clear();
9651 schematic->CurrentSheet().push_back( &schematic->Root() );
9663 if( symbol->
GetRef( &
path,
false ) == wxS(
"R48" ) )
9675 size_t datasheetFields = std::count_if(
9677 [](
const SCH_FIELD& field ) { return field.GetName() == wxS(
"Datasheet" ); } );
9681 wxS(
"Y:\\01_Cadence_Library\\05_Datasheet\\301010000_YAGEO_RC0402JR-070RL_Datasheet.pdf" ) );
9687 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
9689 if( !corpusEnv || !*corpusEnv )
9692 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"CY4532 Power Board Schematic.DSN" );
9697 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
9700 schematic->SetProject( &manager.
Prj() );
9701 schematic->CurrentSheet().clear();
9702 schematic->CurrentSheet().push_back( &schematic->Root() );
9714 if( symbol->
GetRef( &
path,
false ) == wxS(
"C45" ) )
9726 size_t footprintFields = std::count_if(
9728 [](
const SCH_FIELD& field ) { return field.GetName() == wxS(
"Footprint" ); } );
9740 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
9742 if( !corpusEnv || !*corpusEnv )
9745 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"CY4532 Power Board Schematic.DSN" );
9750 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
9753 schematic->SetProject( &manager.
Prj() );
9754 schematic->CurrentSheet().clear();
9755 schematic->CurrentSheet().push_back( &schematic->Root() );
9768 wxString reference = symbol->
GetRef( &
path,
false );
9770 if( reference == wxS(
"C104" ) )
9772 else if( reference == wxS(
"R58" ) )
9774 else if( reference == wxS(
"TP8" ) )
9794 BOOST_CHECK( description->
IsVisible() );
9804 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
9806 if( !corpusEnv || !*corpusEnv )
9809 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC1859A-2.DSN" );
9814 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
9817 schematic->SetProject( &manager.
Prj() );
9818 schematic->CurrentSheet().clear();
9819 schematic->CurrentSheet().push_back( &schematic->Root() );
9831 if( symbol->
GetRef( &
path,
false ) == wxS(
"C2" ) )
9852 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
9854 if( !corpusEnv || !*corpusEnv )
9857 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SCH-48278.DSN" );
9862 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
9865 schematic->SetProject( &manager.
Prj() );
9866 schematic->CurrentSheet().clear();
9867 schematic->CurrentSheet().push_back( &schematic->Root() );
9872 bool renderedJumper =
false;
9880 if( symbol->
GetRef( &
path,
false ) == wxS(
"J2" ) )
9882 jumper = symbol->
GetField( wxS(
"JUMPER(DEFAULT)" ) );
9890 renderedJumper = renderedJumper
9891 ||
text->GetText() == wxS(
"JUMPER(DEFAULT) = OFF:POLARITY_SEL_L" );
9900 BOOST_CHECK( renderedJumper );
9931 property.name =
"BiasValue Power";
9934 property.name =
"BiasValue Current";
9937 property.name =
"BiasValue Voltage";
9944 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
9946 if( !corpusEnv || !*corpusEnv )
9948 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping wireless peer-net check." );
9952 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"CY3280_MBR3 EVK Schematic.DSN" );
9956 BOOST_TEST_MESSAGE(
"CY3280_MBR3 EVK Schematic.DSN not present; skipping wireless peer-net check." );
9960 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
9963 schematic->SetProject( &manager.
Prj() );
9964 schematic->CurrentSheet().clear();
9965 schematic->CurrentSheet().push_back( &schematic->Root() );
9970 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
9971 schematic->ConnectionGraph()->Recalculate( sheets,
true );
9974 for(
const auto& [key, subgraphs] : schematic->ConnectionGraph()->GetNetMap() )
9978 for(
SCH_ITEM* item : subgraph->GetItems() )
9987 pinNets[{ symbol->
GetRef( &subgraph->GetSheet(),
false ),
pin->GetNumber() }] = subgraph;
9992 BOOST_REQUIRE_EQUAL( pinNets.count( { wxS(
"R51" ), wxS(
"1" ) } ), 1u );
9993 BOOST_REQUIRE_EQUAL( pinNets.count( { wxS(
"R51" ), wxS(
"2" ) } ), 1u );
9994 BOOST_REQUIRE_EQUAL( pinNets.count( { wxS(
"R52" ), wxS(
"1" ) } ), 1u );
9995 BOOST_REQUIRE_EQUAL( pinNets.count( { wxS(
"R52" ), wxS(
"2" ) } ), 1u );
10001 BOOST_CHECK_NE( r51Pin1, r51Pin2 );
10002 BOOST_CHECK_NE( r52Pin1, r52Pin2 );
10008 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10010 if( !corpusEnv || !*corpusEnv )
10012 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping global-net case check." );
10016 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"BeagleBoard-xM_ORCAD.DSN" );
10020 BOOST_TEST_MESSAGE(
"BeagleBoard-xM_ORCAD.DSN not present in corpus; skipping global-net case check." );
10024 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10027 schematic->SetProject( &manager.
Prj() );
10028 schematic->CurrentSheet().clear();
10029 schematic->CurrentSheet().push_back( &schematic->Root() );
10034 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
10035 schematic->ConnectionGraph()->Recalculate( sheets,
true );
10037 std::map<std::tuple<std::string, std::string, std::string>,
int> terminalNets;
10040 for(
const auto& [key, subgraphs] : schematic->ConnectionGraph()->GetNetMap() )
10044 std::string page = subgraph->GetSheet().LastScreen()->GetFileName().ToStdString();
10046 for(
SCH_ITEM* item : subgraph->GetItems() )
10056 terminalNets[{ page, symbol->
GetRef( &subgraph->GetSheet(),
false ).ToStdString(),
10057 pin->GetNumber().ToStdString() }] = netId;
10065 auto findNet = [&](
const std::string& aPage,
const std::string& aRef,
const std::string& aPin )
10067 for(
const auto& [terminal,
id] : terminalNets )
10069 if( std::get<0>( terminal ).
find( aPage ) != std::string::npos && std::get<1>( terminal ) == aRef
10070 && std::get<2>( terminal ) == aPin )
10079 int processor = findNet(
"PROCESSOR_C",
"C75",
"1" );
10080 int power = findNet(
"PMIC _POWER",
"C122",
"1" );
10082 BOOST_REQUIRE_NE( processor, -1 );
10083 BOOST_REQUIRE_NE( power, -1 );
10090 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10092 if( !corpusEnv || !*corpusEnv )
10094 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping bus-range syntax check." );
10098 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"parallella_e16_z7020_schematic.dsn" );
10102 BOOST_TEST_MESSAGE(
"parallella_e16_z7020_schematic.dsn not present in corpus; skipping bus-range check." );
10106 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10109 schematic->SetProject( &manager.
Prj() );
10110 schematic->CurrentSheet().clear();
10111 schematic->CurrentSheet().push_back( &schematic->Root() );
10116 bool found =
false;
10123 BOOST_CHECK_NE(
text, wxS(
"DDR_DQ[31:0]" ) );
10124 found |=
text == wxS(
"DDR_DQ[31..0]" );
10128 BOOST_CHECK( found );
10134 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10136 if( !corpusEnv || !*corpusEnv )
10139 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"parallella_e16_z7020_schematic.dsn" );
10144 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10147 schematic->SetProject( &manager.
Prj() );
10148 schematic->CurrentSheet().clear();
10149 schematic->CurrentSheet().push_back( &schematic->Root() );
10161 if( symbol->
GetRef( &
path,
false ) == wxS(
"PTH1" ) )
10163 platedHole = symbol;
10173 size_t valueFields = std::count_if(
10175 [](
const SCH_FIELD& aField ) { return aField.GetName().CmpNoCase( wxS(
"Value" ) ) == 0; } );
10183 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10185 if( !corpusEnv || !*corpusEnv )
10188 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"parallella_e16_z7020_schematic.dsn" );
10193 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10196 schematic->SetProject( &manager.
Prj() );
10197 schematic->CurrentSheet().clear();
10198 schematic->CurrentSheet().push_back( &schematic->Root() );
10203 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
10204 schematic->ConnectionGraph()->Recalculate( sheets,
true );
10206 std::map<std::string, int> terminalNets;
10209 for(
const auto& [key, subgraphs] : schematic->ConnectionGraph()->GetNetMap() )
10213 for(
SCH_ITEM* item : subgraph->GetItems() )
10223 terminalNets[
terminalToken( symbol->
GetRef( &subgraph->GetSheet(),
false ).ToStdString(),
10224 pin->GetNumber().ToStdString() )] = netId;
10242 BOOST_CHECK_NE( terminalNets[
"R41.2"], terminalNets[
"R56.2"] );
10248 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10250 if( !corpusEnv || !*corpusEnv )
10253 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"parallella_gen0.dsn" );
10258 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10261 schematic->SetProject( &manager.
Prj() );
10262 schematic->CurrentSheet().clear();
10263 schematic->CurrentSheet().push_back( &schematic->Root() );
10279 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10281 if( !corpusEnv || !*corpusEnv )
10284 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SCH-20380.DSN" );
10289 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10292 schematic->SetProject( &manager.
Prj() );
10293 schematic->CurrentSheet().clear();
10294 schematic->CurrentSheet().push_back( &schematic->Root() );
10313 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10315 if( !corpusEnv || !*corpusEnv )
10318 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SCH-38863_CX1.DSN" );
10323 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10326 schematic->SetProject( &manager.
Prj() );
10327 schematic->CurrentSheet().clear();
10328 schematic->CurrentSheet().push_back( &schematic->Root() );
10335 std::set<wxString> netNames;
10337 for(
const auto& [reference, peer, sourceName] :
10338 { std::tuple{ wxString(
"J16" ), wxString(
"C520" ), wxString(
"GNDISOHU" ) },
10339 std::tuple{ wxString(
"J17" ), wxString(
"C590" ), wxString(
"GNDISOHV" ) },
10340 std::tuple{ wxString(
"J18" ), wxString(
"C661" ), wxString(
"GNDISOHW" ) } } )
10342 wxString netName =
terminalNetName( *schematic, reference, wxS(
"1" ) );
10345 netNames.insert( netName );
10346 bool mapped =
false;
10358 BOOST_CHECK( mapped );
10367 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10369 if( !corpusEnv || !*corpusEnv )
10371 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping duplicate page-net check." );
10379 BOOST_TEST_MESSAGE(
"MTB4.DSN not present in corpus; skipping duplicate page-net check." );
10383 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10386 schematic->SetProject( &manager.
Prj() );
10387 schematic->CurrentSheet().clear();
10388 schematic->CurrentSheet().push_back( &schematic->Root() );
10393 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
10394 schematic->ConnectionGraph()->Recalculate( sheets,
true );
10396 std::map<std::string, wxString> pinNets;
10398 for(
const auto& [key, subgraphs] : schematic->ConnectionGraph()->GetNetMap() )
10402 if( subgraph->GetSheet().LastScreen()->GetFileName().Find( wxS(
"PAGE 2 - MCU" ) ) == wxNOT_FOUND )
10405 for(
SCH_ITEM* item : subgraph->GetItems() )
10413 if( symbol && symbol->
GetRef( &subgraph->GetSheet(),
false ) == wxS(
"U1" ) )
10414 pinNets[
pin->GetNumber().ToStdString()] = key.Name;
10419 BOOST_REQUIRE_EQUAL( pinNets.count(
"F3" ), 1u );
10420 BOOST_REQUIRE_EQUAL( pinNets.count(
"F8" ), 1u );
10421 BOOST_REQUIRE_EQUAL( pinNets.count(
"G3" ), 1u );
10422 BOOST_REQUIRE_EQUAL( pinNets.count(
"G7" ), 1u );
10423 BOOST_CHECK( pinNets[
"F3"].EndsWith( wxS(
"I2C2_SDA" ) ) );
10424 BOOST_CHECK( pinNets[
"F8"].EndsWith( wxS(
"I2C2_SDA" ) ) );
10425 BOOST_CHECK( pinNets[
"G3"].EndsWith( wxS(
"I2C2_SCL" ) ) );
10426 BOOST_CHECK( pinNets[
"G7"].EndsWith( wxS(
"I2C2_SCL" ) ) );
10432 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10434 if( !corpusEnv || !*corpusEnv )
10436 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping duplicate page-net isolation check." );
10440 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC2125A-2.DSN" );
10444 BOOST_TEST_MESSAGE(
"DC2125A-2.DSN not present; skipping duplicate page-net isolation check." );
10448 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10451 schematic->SetProject( &manager.
Prj() );
10452 schematic->CurrentSheet().clear();
10453 schematic->CurrentSheet().push_back( &schematic->Root() );
10458 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
10459 schematic->ConnectionGraph()->Recalculate( sheets,
true );
10462 for(
const auto& [key, subgraphs] : schematic->ConnectionGraph()->GetNetMap() )
10466 for(
SCH_ITEM* item : subgraph->GetItems() )
10475 pinNets[{ symbol->
GetRef( &subgraph->GetSheet(),
false ),
pin->GetNumber() }] = subgraph;
10482 BOOST_CHECK_NE( earth, vportn );
10488 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10490 if( !corpusEnv || !*corpusEnv )
10492 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping alias-at-crossing isolation check." );
10496 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"OC_CONNECT1_FRONTEND_REV_C_V1P1.DSN" );
10500 BOOST_TEST_MESSAGE(
"OC_CONNECT1_FRONTEND_REV_C_V1P1.DSN not present; skipping alias-at-crossing check." );
10504 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10507 schematic->SetProject( &manager.
Prj() );
10508 schematic->CurrentSheet().clear();
10509 schematic->CurrentSheet().push_back( &schematic->Root() );
10514 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
10515 schematic->ConnectionGraph()->Recalculate( sheets,
true );
10518 for(
const auto& [key, subgraphs] : schematic->ConnectionGraph()->GetNetMap() )
10522 for(
SCH_ITEM* item : subgraph->GetItems() )
10531 pinNets[{ symbol->
GetRef( &subgraph->GetSheet(),
false ),
pin->GetNumber() }] = subgraph;
10544 BOOST_CHECK_NE( a0, a2 );
10545 BOOST_CHECK_NE( a0, io1 );
10546 BOOST_CHECK_NE( a2, io1 );
10552 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10554 if( !corpusEnv || !*corpusEnv )
10556 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping wireless page-net check." );
10560 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"Si828X-BW-GDB.DSN" );
10564 BOOST_TEST_MESSAGE(
"Si828X-BW-GDB.DSN not present; skipping wireless page-net check." );
10568 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10571 schematic->SetProject( &manager.
Prj() );
10572 schematic->CurrentSheet().clear();
10573 schematic->CurrentSheet().push_back( &schematic->Root() );
10578 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
10579 schematic->ConnectionGraph()->Recalculate( sheets,
true );
10580 std::map<std::pair<wxString, wxString>, wxString> pinNames;
10582 for(
const auto& [key, subgraphs] : schematic->ConnectionGraph()->GetNetMap() )
10586 for(
SCH_ITEM* item : subgraph->GetItems() )
10595 pinNames[{ symbol->
GetRef( &subgraph->GetSheet(),
false ),
pin->GetNumber() }] = key.Name;
10600 BOOST_CHECK_EQUAL( pinNames.at( { wxS(
"CB28" ), wxS(
"2" ) } ), wxS(
"5V" ) );
10601 BOOST_CHECK_EQUAL( pinNames.at( { wxS(
"RT17" ), wxS(
"2" ) } ), wxS(
"5V" ) );
10607 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10609 if( !corpusEnv || !*corpusEnv )
10611 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping ambiguous wireless-net check." );
10615 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC2047A-3-A.DSN" );
10619 BOOST_TEST_MESSAGE(
"DC2047A-3-A.DSN not present; skipping ambiguous wireless-net check." );
10623 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10626 schematic->SetProject( &manager.
Prj() );
10627 schematic->CurrentSheet().clear();
10628 schematic->CurrentSheet().push_back( &schematic->Root() );
10633 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
10634 schematic->ConnectionGraph()->Recalculate( sheets,
true );
10637 for(
const auto& [key, subgraphs] : schematic->ConnectionGraph()->GetNetMap() )
10641 for(
SCH_ITEM* item : subgraph->GetItems() )
10649 if( symbol && symbol->
GetRef( &subgraph->GetSheet(),
false ) == wxS(
"D15" )
10650 &&
pin->GetNumber() == wxS(
"2" ) )
10652 d15Pin2 = key.Name;
10664 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10666 if( !corpusEnv || !*corpusEnv )
10669 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC2084A-3.DSN" );
10674 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10677 schematic->SetProject( &manager.
Prj() );
10678 schematic->CurrentSheet().clear();
10679 schematic->CurrentSheet().push_back( &schematic->Root() );
10684 std::map<wxString, std::set<wxString>> pinNumbers;
10686 for(
const SCH_SHEET_PATH& sheet : schematic->BuildSheetListSortedByPageNumbers() )
10692 wxString reference = symbol->
GetRef( &sheet,
false );
10694 if( reference != wxS(
"C31" ) && reference != wxS(
"C42" ) )
10697 for(
const std::unique_ptr<SCH_PIN>&
pin : symbol->
GetRawPins() )
10698 pinNumbers[reference].insert(
pin->GetNumber() );
10702 BOOST_CHECK( pinNumbers[wxS(
"C31" )] == std::set<wxString>( { wxS(
"1" ), wxS(
"2" ) } ) );
10703 BOOST_CHECK( pinNumbers[wxS(
"C42" )] == std::set<wxString>( { wxS(
"1" ), wxS(
"2" ) } ) );
10709 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10711 if( !corpusEnv || !*corpusEnv )
10714 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC2091A-3.DSN" );
10719 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10722 schematic->SetProject( &manager.
Prj() );
10723 schematic->CurrentSheet().clear();
10724 schematic->CurrentSheet().push_back( &schematic->Root() );
10729 std::map<wxString, std::set<wxString>> pinNumbers;
10731 for(
const SCH_SHEET_PATH& sheet : schematic->BuildSheetListSortedByPageNumbers() )
10736 wxString reference = symbol->
GetRef( &sheet,
false );
10738 if( reference != wxS(
"C1" ) && reference != wxS(
"C2" ) )
10741 for(
const std::unique_ptr<SCH_PIN>&
pin : symbol->
GetRawPins() )
10742 pinNumbers[reference].insert(
pin->GetNumber() );
10746 const std::set<wxString>
expected = { wxS(
"1" ), wxS(
"2" ) };
10747 BOOST_CHECK( pinNumbers[wxS(
"C1" )] ==
expected );
10748 BOOST_CHECK( pinNumbers[wxS(
"C2" )] ==
expected );
10754 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10756 if( !corpusEnv || !*corpusEnv )
10759 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC2228A-3.DSN" );
10764 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10767 schematic->SetProject( &manager.
Prj() );
10768 schematic->CurrentSheet().clear();
10769 schematic->CurrentSheet().push_back( &schematic->Root() );
10783 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10785 if( !corpusEnv || !*corpusEnv )
10788 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC2228A-3.DSN" );
10793 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10796 schematic->SetProject( &manager.
Prj() );
10797 schematic->CurrentSheet().clear();
10798 schematic->CurrentSheet().push_back( &schematic->Root() );
10803 std::map<int, size_t> pinCounts;
10805 for(
const SCH_SHEET_PATH& sheet : schematic->BuildSheetListSortedByPageNumbers() )
10811 if( symbol->
GetRef( &sheet,
false ) == wxS(
"U9" ) )
10816 const std::map<int, size_t>
expected = {
10817 { 1, 2 }, { 2, 21 }, { 3, 14 }, { 4, 9 }, { 5, 11 }, { 6, 8 }, { 7, 13 },
10818 { 8, 8 }, { 9, 9 }, { 10, 7 }, { 11, 5 }, { 12, 7 }, { 13, 15 }, { 14, 17 },
10819 { 15, 16 }, { 16, 12 }, { 17, 32 }, { 18, 6 }, { 19, 22 }, { 20, 22 },
10821 BOOST_CHECK( pinCounts ==
expected );
10827 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10829 if( !corpusEnv || !*corpusEnv )
10832 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SI82AX-CX_NB8_EVB.DSN" );
10837 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10840 schematic->SetProject( &manager.
Prj() );
10841 schematic->CurrentSheet().clear();
10842 schematic->CurrentSheet().push_back( &schematic->Root() );
10847 bool foundR2 =
false;
10848 bool foundR17 =
false;
10849 wxString refsAtR2Position;
10850 wxString refsAtR17Position;
10852 for(
const SCH_SHEET_PATH& sheet : schematic->BuildSheetListSortedByPageNumbers() )
10857 wxString reference = symbol->
GetRef( &sheet,
false );
10861 refsAtR2Position += reference + wxS(
" " );
10862 foundR2 = foundR2 || reference == wxS(
"R2" );
10867 refsAtR17Position += reference + wxS(
" " );
10868 foundR17 = foundR17 || reference == wxS(
"R17" );
10873 BOOST_CHECK_MESSAGE( foundR2,
"references at R2 position: " << refsAtR2Position );
10874 BOOST_CHECK_MESSAGE( foundR17,
"references at R17 position: " << refsAtR17Position );
10880 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10882 if( !corpusEnv || !*corpusEnv )
10885 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"Low EMI demo board.DSN" );
10890 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10893 schematic->SetProject( &manager.
Prj() );
10894 schematic->CurrentSheet().clear();
10895 schematic->CurrentSheet().push_back( &schematic->Root() );
10902 BOOST_CHECK( refs.count(
"C1" ) );
10903 BOOST_CHECK( refs.count(
"U1" ) );
10904 BOOST_CHECK( !refs.count(
"C71" ) );
10905 BOOST_CHECK( !refs.count(
"U12" ) );
10911 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10913 if( !corpusEnv || !*corpusEnv )
10916 std::filesystem::path dsn;
10918 for(
const std::filesystem::directory_entry& entry :
10919 std::filesystem::recursive_directory_iterator( corpusEnv ) )
10921 if( entry.is_regular_file() && entry.path().filename() ==
"BDC.DSN"
10922 && entry.path().string().find(
"backpack-bdc" ) != std::string::npos )
10924 dsn = entry.path();
10932 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10935 schematic->SetProject( &manager.
Prj() );
10936 schematic->CurrentSheet().clear();
10937 schematic->CurrentSheet().push_back( &schematic->Root() );
10942 wxString reference;
10944 for(
const SCH_SHEET_PATH& sheet : schematic->BuildSheetListSortedByPageNumbers() )
10951 reference = symbol->
GetRef( &sheet,
false );
10961 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
10963 if( !corpusEnv || !*corpusEnv )
10966 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SuperSpeed Explorer Kit Schematic.DSN" );
10971 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
10974 schematic->SetProject( &manager.
Prj() );
10975 schematic->CurrentSheet().clear();
10976 schematic->CurrentSheet().push_back( &schematic->Root() );
10981 std::map<wxString, SCH_SYMBOL*> switches;
10983 for(
const SCH_SHEET_PATH& sheet : schematic->BuildSheetListSortedByPageNumbers() )
10988 wxString reference = symbol->
GetRef( &sheet,
false );
10990 if( reference == wxS(
"SW1" ) || reference == wxS(
"SW2" ) )
10991 switches[reference] = symbol;
10995 BOOST_REQUIRE_EQUAL( switches.size(), 2u );
10997 for(
const wxString& reference : { wxS(
"SW1" ), wxS(
"SW2" ) } )
10999 SCH_SYMBOL* symbol = switches.at( reference );
11003 wxS(
"Wurth Electronics Inc" ) );
11012 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11014 if( !corpusEnv || !*corpusEnv )
11017 auto checkFieldCleared = [&](
const wxString& aFileName,
const wxString& aReference,
11018 const wxString& aFieldName )
11020 std::filesystem::path dsn =
findCorpusDesign( corpusEnv, aFileName.ToStdString() );
11023 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11026 schematic->SetProject( &manager.
Prj() );
11027 schematic->CurrentSheet().clear();
11028 schematic->CurrentSheet().push_back( &schematic->Root() );
11035 for(
const SCH_SHEET_PATH& sheet : schematic->BuildSheetListSortedByPageNumbers() )
11041 if( symbol->
GetRef( &sheet,
false ) == aReference )
11042 field = symbol->
GetField( aFieldName );
11046 BOOST_CHECK( !field || field->
GetText().IsEmpty() );
11049 checkFieldCleared( wxS(
"DC2596A-3.DSN" ), wxS(
"L2" ), wxS(
"4th Part Field" ) );
11050 checkFieldCleared( wxS(
"CY4532 Power Board Schematic.DSN" ), wxS(
"J2" ), wxS(
"PART_NUMBER" ) );
11056 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11058 if( !corpusEnv || !*corpusEnv )
11061 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC2641A3-SCH.DSN" );
11066 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11069 schematic->SetProject( &manager.
Prj() );
11070 schematic->CurrentSheet().clear();
11071 schematic->CurrentSheet().push_back( &schematic->Root() );
11080 size_t nativePowerPins = 0;
11089 wxString ref = symbol->
GetRef( &
path,
false );
11091 if( ref != wxS(
"L1" ) && ref != wxS(
"L4" ) )
11096 if(
pin->GetNumber() != wxS(
"3" ) )
11100 BOOST_CHECK( !
pin->IsVisible() );
11101 BOOST_CHECK(
pin->IsGlobalPower() );
11108 BOOST_CHECK_NE( label->GetText(), wxString(
"$$$1" ) );
11120 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11122 if( !corpusEnv || !*corpusEnv )
11125 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SCH-54852_A5.DSN" );
11130 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11133 schematic->SetProject( &manager.
Prj() );
11134 schematic->CurrentSheet().clear();
11135 schematic->CurrentSheet().push_back( &schematic->Root() );
11149 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11151 if( !corpusEnv || !*corpusEnv )
11154 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SCH-31399_C4.DSN" );
11159 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11162 schematic->SetProject( &manager.
Prj() );
11163 schematic->CurrentSheet().clear();
11164 schematic->CurrentSheet().push_back( &schematic->Root() );
11179 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11181 if( !corpusEnv || !*corpusEnv )
11189 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11192 schematic->SetProject( &manager.
Prj() );
11193 schematic->CurrentSheet().clear();
11194 schematic->CurrentSheet().push_back( &schematic->Root() );
11211 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11213 if( !corpusEnv || !*corpusEnv )
11216 std::filesystem::path dsn =
11217 findCorpusDesign( corpusEnv,
"630-60651-01_04_CYW9BTM2BASE3_20829_BaseBoard_Schematics.DSN" );
11222 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11225 schematic->SetProject( &manager.
Prj() );
11226 schematic->CurrentSheet().clear();
11227 schematic->CurrentSheet().push_back( &schematic->Root() );
11242 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11244 if( !corpusEnv || !*corpusEnv )
11247 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"parallella_gen0.dsn" );
11252 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11255 schematic->SetProject( &manager.
Prj() );
11256 schematic->CurrentSheet().clear();
11257 schematic->CurrentSheet().push_back( &schematic->Root() );
11273 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11275 if( !corpusEnv || !*corpusEnv )
11278 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SI347X-DC-EB.DSN" );
11283 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11286 schematic->SetProject( &manager.
Prj() );
11287 schematic->CurrentSheet().clear();
11288 schematic->CurrentSheet().push_back( &schematic->Root() );
11293 std::vector<std::set<std::string>>
expected;
11295 for(
int channel = 1; channel <= 8; ++channel )
11297 std::string q =
"Q" + std::to_string( channel );
11298 std::string r =
"R" + std::to_string( channel );
11299 std::string gatePin = std::to_string( std::array{ 1, 7, 8, 14, 29, 35, 36, 42 }[channel - 1] );
11300 std::string sourcePin = std::to_string( std::array{ 2, 6, 9, 13, 30, 34, 37, 41 }[channel - 1] );
11314 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11316 if( !corpusEnv || !*corpusEnv )
11319 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"Si828X-BW-GDB.DSN" );
11324 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11327 schematic->SetProject( &manager.
Prj() );
11328 schematic->CurrentSheet().clear();
11329 schematic->CurrentSheet().push_back( &schematic->Root() );
11334 std::vector<std::set<std::string>>
expected = {
11350 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11352 if( !corpusEnv || !*corpusEnv )
11355 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SI8284v2-EVB.DSN" );
11360 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11363 schematic->SetProject( &manager.
Prj() );
11364 schematic->CurrentSheet().clear();
11365 schematic->CurrentSheet().push_back( &schematic->Root() );
11372 BOOST_CHECK( refs.count(
"Q1-1" ) );
11373 BOOST_CHECK( refs.count(
"Q1-2" ) );
11374 BOOST_CHECK( refs.count(
"Q8-1" ) );
11375 BOOST_CHECK( refs.count(
"Q8-2" ) );
11381 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11383 if( !corpusEnv || !*corpusEnv )
11386 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SI8284v2-EVB.DSN" );
11391 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11394 schematic->SetProject( &manager.
Prj() );
11395 schematic->CurrentSheet().clear();
11396 schematic->CurrentSheet().push_back( &schematic->Root() );
11402 wxString( wxS(
"s3" ) ) );
11408 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11410 if( !corpusEnv || !*corpusEnv )
11413 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SI8284v2-EVB.DSN" );
11418 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11421 schematic->SetProject( &manager.
Prj() );
11422 schematic->CurrentSheet().clear();
11423 schematic->CurrentSheet().push_back( &schematic->Root() );
11428 wxString boostNet =
terminalNetName( *schematic, wxS(
"C36" ), wxS(
"1" ) );
11429 wxString supplyNet =
terminalNetName( *schematic, wxS(
"C12" ), wxS(
"1" ) );
11433 BOOST_CHECK_NE( boostNet, supplyNet );
11437 auto mapped = std::find_if( map->
entries.begin(), map->
entries.end(),
11440 return entry.sourceNetId == 16939716
11441 && entry.originalName == wxS(
"N16864826" );
11451 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11453 if( !corpusEnv || !*corpusEnv )
11456 for(
const char* filename : {
"Si828X-BW-GDB.DSN",
"SI828X-AW-GDB.DSN" } )
11461 BOOST_REQUIRE_MESSAGE( !dsn.empty(), filename <<
" not present in corpus." );
11468 wxString netName =
terminalNetName( schematic, wxS(
"C306" ), wxS(
"1" ) );
11471 for(
const auto& [reference,
pin] :
11472 { std::pair{ wxString(
"U2" ), wxString(
"16" ) },
11473 std::pair{ wxString(
"C307" ), wxString(
"2" ) },
11474 std::pair{ wxString(
"C309" ), wxString(
"1" ) },
11475 std::pair{ wxString(
"C310" ), wxString(
"1" ) },
11476 std::pair{ wxString(
"R333" ), wxString(
"1" ) },
11477 std::pair{ wxString(
"UB8" ), wxString(
"3" ) },
11478 std::pair{ wxString(
"UT6" ), wxString(
"5" ) } } )
11483 std::set<wxString> powerNames;
11499 BOOST_REQUIRE_EQUAL( powerNames.size(), 1u );
11508 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11510 if( !corpusEnv || !*corpusEnv )
11513 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"CN81XX_GBCV2_sch_0530.DSN" );
11518 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11521 schematic->SetProject( &manager.
Prj() );
11522 schematic->CurrentSheet().clear();
11523 schematic->CurrentSheet().push_back( &schematic->Root() );
11528 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
11529 schematic->ConnectionGraph()->Recalculate( sheets,
true );
11530 wxString r13Pin1Net;
11532 for(
const auto& [key, subgraphs] : schematic->ConnectionGraph()->GetNetMap() )
11536 for(
SCH_ITEM* item : subgraph->GetItems() )
11544 if( symbol && symbol->
GetRef( &subgraph->GetSheet(),
false ) == wxS(
"R13" )
11545 &&
pin->GetNumber() == wxS(
"1" ) )
11547 r13Pin1Net = key.Name;
11559 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11561 if( !corpusEnv || !*corpusEnv )
11569 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11572 schematic->SetProject( &manager.
Prj() );
11573 schematic->CurrentSheet().clear();
11574 schematic->CurrentSheet().push_back( &schematic->Root() );
11591 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11593 if( !corpusEnv || !*corpusEnv )
11596 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC726A-1.DSN" );
11601 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11604 schematic->SetProject( &manager.
Prj() );
11605 schematic->CurrentSheet().clear();
11606 schematic->CurrentSheet().push_back( &schematic->Root() );
11625 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11627 if( !corpusEnv || !*corpusEnv )
11630 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC2283A-2.DSN" );
11635 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11638 schematic->SetProject( &manager.
Prj() );
11639 schematic->CurrentSheet().clear();
11640 schematic->CurrentSheet().push_back( &schematic->Root() );
11655 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11657 if( !corpusEnv || !*corpusEnv )
11665 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11668 schematic->SetProject( &manager.
Prj() );
11669 schematic->CurrentSheet().clear();
11670 schematic->CurrentSheet().push_back( &schematic->Root() );
11686 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11688 if( !corpusEnv || !*corpusEnv )
11691 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC2793A-3.DSN" );
11696 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11699 schematic->SetProject( &manager.
Prj() );
11700 schematic->CurrentSheet().clear();
11701 schematic->CurrentSheet().push_back( &schematic->Root() );
11716 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11718 if( !corpusEnv || !*corpusEnv )
11721 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"CY4532 Power Board Schematic.DSN" );
11726 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11729 schematic->SetProject( &manager.
Prj() );
11730 schematic->CurrentSheet().clear();
11731 schematic->CurrentSheet().push_back( &schematic->Root() );
11745 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11747 if( !corpusEnv || !*corpusEnv )
11750 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC2047A-3-A.DSN" );
11755 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11758 schematic->SetProject( &manager.
Prj() );
11759 schematic->CurrentSheet().clear();
11760 schematic->CurrentSheet().push_back( &schematic->Root() );
11774 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11776 if( !corpusEnv || !*corpusEnv )
11779 std::filesystem::path dsn =
11780 findCorpusDesign( corpusEnv,
"630-60651-01_04_CYW9BTM2BASE3_20829_BaseBoard_Schematics.DSN" );
11785 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11788 schematic->SetProject( &manager.
Prj() );
11789 schematic->CurrentSheet().clear();
11790 schematic->CurrentSheet().push_back( &schematic->Root() );
11807 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11809 if( !corpusEnv || !*corpusEnv )
11812 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"CY4532 Power Board Schematic.DSN" );
11817 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
11820 schematic->SetProject( &manager.
Prj() );
11821 schematic->CurrentSheet().clear();
11822 schematic->CurrentSheet().push_back( &schematic->Root() );
11838 rootPage.
name =
"ROOT";
11839 rootPage.
width = 10000;
11844 drawn.
x1 = drawn.
y1 = 100;
11845 drawn.
w = drawn.
h = 100;
11847 .x = 100, .y = 150 } );
11848 rootPage.
blocks.push_back( std::move( drawn ) );
11851 childPage.
name =
"CHILD";
11852 childPage.
width = 10000;
11853 childPage.
height = 8000;
11854 childPage.
netmap[1] =
"gate";
11859 wire.
y1 = wire.
y2 = 100;
11860 childPage.
wires.push_back( wire );
11863 offpage.
x = offpage.
y = 100;
11864 childPage.
offpage.push_back( std::move( offpage ) );
11870 design.
sourceId =
"offpage-parent-input-binding";
11871 design.
pages.push_back( std::move( rootPage ) );
11882 child =
static_cast<SCH_SHEET*
>( item );
11885 BOOST_REQUIRE_EQUAL( child->
GetPins().size(), 1u );
11892 if( label->
GetText().CmpNoCase(
"gate" ) != 0 )
11906 for(
int mode : { 0, 1, 2 } )
11908 bool endpoint = mode == 1;
11909 bool ambiguous = mode == 2;
11911 page.
name =
"OFFPAGE AT CUT CROSSING";
11912 page.
width = 10000;
11914 page.
netmap[1] =
"VERTICAL";
11915 page.
netmap[2] =
"HORIZONTAL";
11919 vertical.
x1 = vertical.
x2 = 100;
11920 vertical.
y1 = endpoint ? 100 : 50;
11922 page.
wires.push_back( vertical );
11926 horizontal.
x1 = 50;
11927 horizontal.
x2 = 150;
11928 horizontal.
y1 = horizontal.
y2 = 100;
11929 page.
wires.push_back( horizontal );
11932 offpage.
logicalName = ambiguous ?
"UNKNOWN" :
"VERTICAL";
11933 offpage.
x = offpage.
y = 100;
11934 page.
offpage.push_back( std::move( offpage ) );
11937 design.
sourceId = endpoint ?
"offpage-at-cut-endpoint" :
"offpage-at-cut-interior";
11938 design.
pages.push_back( std::move( page ) );
11953 SCH_LINE* horizontalWire =
nullptr;
11966 verticalWire = line;
11968 horizontalWire = line;
11974 if( label->
GetText() ==
"VERTICAL"
11984 BOOST_CHECK_NE( verticalWire->
Connection( &sheets.front() )->
Name(),
11992 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
11994 if( !corpusEnv || !*corpusEnv )
11997 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SI347XY_MB_EVB.DSN" );
12016 if( label->
GetText() !=
"VDD" )
12043 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
12045 if( !corpusEnv || !*corpusEnv )
12048 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC2659A-4.DSN" );
12063 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
12071 if( label->
GetText() !=
"VOUT2"
12073 > int64_t( 15000 ) * 15000 )
12081 for(
SCH_ITEM* other : sheet.LastScreen()->Items() )
12093 BOOST_CHECK_LE( incident, 1 );
12103 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
12105 if( !corpusEnv || !*corpusEnv )
12107 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping off-page display-name check." );
12111 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC2509A-1.DSN" );
12115 BOOST_TEST_MESSAGE(
"DC2509A-1.DSN not present in corpus; skipping off-page display-name check." );
12119 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12122 schematic->SetProject( &manager.
Prj() );
12123 schematic->CurrentSheet().clear();
12124 schematic->CurrentSheet().push_back( &schematic->Root() );
12129 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
12130 schematic->ConnectionGraph()->Recalculate( sheets,
true );
12132 std::map<std::string, CONNECTION_SUBGRAPH*> pinNets;
12134 for(
const auto& [key, subgraphs] : schematic->ConnectionGraph()->GetNetMap() )
12138 for(
SCH_ITEM* item : subgraph->GetItems() )
12146 if( !symbol ||
pin->GetNumber() != wxS(
"1" ) )
12149 wxString ref = symbol->
GetRef( &subgraph->GetSheet(),
false );
12151 if( ref == wxS(
"U3" ) || ref == wxS(
"U4" ) )
12152 pinNets[ref.ToStdString()] = subgraph;
12157 BOOST_REQUIRE_EQUAL( pinNets.count(
"U3" ), 1u );
12158 BOOST_REQUIRE_EQUAL( pinNets.count(
"U4" ), 1u );
12165 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
12167 if( !corpusEnv || !*corpusEnv )
12169 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping single leaf occurrence check." );
12173 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SCH-28988.DSN" );
12177 BOOST_TEST_MESSAGE(
"SCH-28988.DSN not present in corpus; skipping single leaf occurrence check." );
12181 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12184 schematic->SetProject( &manager.
Prj() );
12185 schematic->CurrentSheet().clear();
12186 schematic->CurrentSheet().push_back( &schematic->Root() );
12191 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
12192 schematic->ConnectionGraph()->Recalculate( sheets,
true );
12195 for(
const auto& [key, subgraphs] : schematic->ConnectionGraph()->GetNetMap() )
12199 for(
SCH_ITEM* item : subgraph->GetItems() )
12207 if( symbol && symbol->
GetRef( &subgraph->GetSheet(),
false ) == wxS(
"C3" )
12208 &&
pin->GetNumber() == wxS(
"1" ) )
12210 netName = key.Name;
12223 auto mapped = std::find_if( map->
entries.begin(), map->
entries.end(),
12226 return entry.sourceNetId == 16645429
12227 && entry.originalName == wxS(
"ANALOG5V" );
12239 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
12241 if( !corpusEnv || !*corpusEnv )
12243 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping package-variant check." );
12247 auto load = [&](
const char* aName )
12250 BOOST_REQUIRE_MESSAGE( !dsn.empty(), aName <<
" not present in corpus." );
12252 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12255 schematic->SetProject( &manager->
Prj() );
12256 schematic->CurrentSheet().clear();
12257 schematic->CurrentSheet().push_back( &schematic->Root() );
12261 return std::pair( std::move( schematic ), std::unique_ptr<SETTINGS_MANAGER>( manager ) );
12264 auto [breakout, breakoutManager] = load(
"OC_CONNECT_1_BRKOUT_BRD.DSN" );
12265 std::map<wxString, std::set<wxString>> switchPins;
12272 wxString ref = symbol->
GetRef( &
path,
false );
12274 if( ref != wxS(
"S1" ) && ref != wxS(
"S3" ) )
12278 switchPins[ref].insert(
pin->GetNumber() );
12282 const std::set<wxString> expectedS1 = { wxS(
"1" ), wxS(
"2" ), wxS(
"3" ), wxS(
"4" ) };
12283 const std::set<wxString> expectedS3 = { wxS(
"1" ), wxS(
"2" ), wxS(
"3" ) };
12285 expectedS1.end() );
12287 expectedS3.end() );
12289 auto [j401, j401Manager] = load(
"reServer industrial J401 Carrier Board v11.DSN" );
12290 std::set<wxString> j10Pins;
12298 if( symbol->
GetRef( &
path,
false ) != wxS(
"J10" ) )
12302 j10Pins.insert(
pin->GetNumber() );
12314 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
12316 if( !corpusEnv || !*corpusEnv )
12318 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping legacy package-map check." );
12326 BOOST_TEST_MESSAGE(
"EXAMPLE.DSN not present in corpus; skipping legacy package-map check." );
12330 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12333 schematic->SetProject( &manager.
Prj() );
12334 schematic->CurrentSheet().clear();
12335 schematic->CurrentSheet().push_back( &schematic->Root() );
12340 std::set<wxString> pins;
12348 if( symbol->
GetRef( &
path,
false ) != wxS(
"U4" ) )
12352 pins.insert(
pin->GetNumber() );
12356 const std::set<wxString>
expected = { wxS(
"2" ), wxS(
"3" ), wxS(
"4" ), wxS(
"5" ), wxS(
"12" ) };
12363 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
12365 if( !corpusEnv || !*corpusEnv )
12367 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping S-593487 connector check." );
12371 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"S-593487-REV-B.DSN" );
12372 BOOST_REQUIRE_MESSAGE( !dsn.empty(),
"S-593487-REV-B.DSN not present in corpus." );
12374 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12377 schematic->SetProject( &manager.
Prj() );
12378 schematic->CurrentSheet().clear();
12379 schematic->CurrentSheet().push_back( &schematic->Root() );
12384 auto [consistent, checkable] =
12396 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
12398 if( !corpusEnv || !*corpusEnv )
12400 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping M5275 visible-power-pin check." );
12404 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"M5275EVB.DSN" );
12405 BOOST_REQUIRE_MESSAGE( !dsn.empty(),
"M5275EVB.DSN not present in corpus." );
12407 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12410 schematic->SetProject( &manager.
Prj() );
12411 schematic->CurrentSheet().clear();
12412 schematic->CurrentSheet().push_back( &schematic->Root() );
12417 std::map<wxString, bool> visible;
12425 if( symbol->
GetRef( &
path,
false ) != wxS(
"U21" ) )
12429 visible[
pin->GetNumber()] =
pin->IsVisible();
12433 BOOST_REQUIRE_EQUAL( visible.size(), 6u );
12434 BOOST_CHECK( visible[wxS(
"2" )] );
12435 BOOST_CHECK( visible[wxS(
"5" )] );
12441 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
12443 if( !corpusEnv || !*corpusEnv )
12445 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping SI34062 stacked-pin check." );
12449 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SI34062-ISO-FB-EVB.DSN" );
12450 BOOST_REQUIRE_MESSAGE( !dsn.empty(),
"SI34062-ISO-FB-EVB.DSN not present in corpus." );
12452 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12455 schematic->SetProject( &manager.
Prj() );
12456 schematic->CurrentSheet().clear();
12457 schematic->CurrentSheet().push_back( &schematic->Root() );
12471 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
12473 if( !corpusEnv || !*corpusEnv )
12475 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping duplicate power-alias check." );
12479 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SI8284v2-EVB.DSN" );
12480 BOOST_REQUIRE_MESSAGE( !dsn.empty(),
"SI8284v2-EVB.DSN not present in corpus." );
12482 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12485 schematic->SetProject( &manager.
Prj() );
12486 schematic->CurrentSheet().clear();
12487 schematic->CurrentSheet().push_back( &schematic->Root() );
12492 auto [consistent, checkable] =
12502 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
12504 if( !corpusEnv || !*corpusEnv )
12506 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping logical power-pin check." );
12510 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"CY8CKIT-041-41XX Schematic.DSN" );
12511 BOOST_REQUIRE_MESSAGE( !dsn.empty(),
"CY8CKIT-041-41XX Schematic.DSN not present in corpus." );
12513 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12516 schematic->SetProject( &manager.
Prj() );
12517 schematic->CurrentSheet().clear();
12518 schematic->CurrentSheet().push_back( &schematic->Root() );
12523 bool checkedHeaderPin =
false;
12531 if( symbol->
GetRef( &
path,
false ) != wxS(
"J8" )
12532 || !
path.Last()->GetName().Contains( wxS(
"PSoC 5LP Programmer" ) ) )
12539 if(
pin->GetNumber() == wxS(
"3" ) )
12542 checkedHeaderPin =
true;
12550 auto [consistent, checkable] =
12564 symbol.
name =
"PART.Normal";
12568 ORCAD_SYMBOL_PIN{ .name =
"K", .position = 1, .hotptX = 30, .hotptY = 10 } };
12571 package.
name =
"PART";
12574 package.
devices.push_back(
ORCAD_DEVICE{ .pinNumbers = {
"1",
"2" }, .pinIgnore = {
false,
false } } );
12577 variant.
devices.front().pinNumbers = {
"1",
"3" };
12578 package.
variants.push_back( std::move( variant ) );
12591 page.
name =
"PACKAGE SOURCE";
12592 page.
instances.push_back( std::move( placed ) );
12595 design.
sourceId =
"package-source-before-footprint";
12596 design.
symbols.emplace( symbol.
name, std::move( symbol ) );
12597 design.
packages.emplace( package.
name, std::move( package ) );
12598 design.
pages.push_back( std::move( page ) );
12602 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12603 schematic->SetProject( &manager.
Prj() );
12606 path.push_back( root );
12609 std::set<wxString> pinNumbers;
12612 pinNumbers.insert(
pin->GetNumber() );
12614 const std::set<wxString>
expected = { wxS(
"1" ), wxS(
"3" ) };
12623 symbol.
name =
"VERTICAL.Normal";
12627 .hotptX = 10, .hotptY = 0 },
12628 ORCAD_SYMBOL_PIN{ .name =
"HIN", .position = 1, .startX = 0, .startY = 20,
12629 .hotptX = -10, .hotptY = 20 } };
12631 rotated.
name =
"ROTATED.Normal";
12635 package.
name =
"VERTICAL";
12636 package.
devices.push_back(
ORCAD_DEVICE{ .pinNumbers = {
"2",
"3" }, .pinIgnore = {
false,
false } } );
12638 rotatedPackage.
name =
"ROTATED";
12651 rotatedPlaced.
x = 200;
12655 page.
name =
"VERTICAL PIN TEXT";
12656 page.
instances.push_back( std::move( placed ) );
12657 page.
instances.push_back( std::move( rotatedPlaced ) );
12660 design.
sourceId =
"vertical-pin-text";
12662 .face =
"Arial Narrow" },
12663 ORCAD_FONT{ .height = -8, .face =
"Arial" } };
12669 design.
symbols.emplace( symbol.
name, std::move( symbol ) );
12670 design.
symbols.emplace( rotated.
name, std::move( rotated ) );
12671 design.
packages.emplace( package.
name, std::move( package ) );
12672 design.
packages.emplace( rotatedPackage.
name, std::move( rotatedPackage ) );
12673 design.
pages.push_back( std::move( page ) );
12677 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12678 schematic->SetProject( &manager.
Prj() );
12681 path.push_back( root );
12697 BOOST_CHECK_NE(
text.GetText(), wxS(
"2" ) );
12715 BOOST_CHECK_NE(
text.GetText(), wxS(
"2" ) );
12732 .fontIdx = 1, .color = 48, .dispMode = 0x01E9 };
12735 symbol.
name =
"PIN_OVERRIDE.Normal";
12744 .displayProps = { display } } };
12747 package.
name =
"PIN_OVERRIDE";
12748 package.
devices.push_back(
ORCAD_DEVICE{ .pinNumbers = {
"1" }, .pinIgnore = {
false } } );
12759 page.
name =
"PIN DISPLAY OVERRIDE";
12760 page.
instances.push_back( std::move( placed ) );
12763 design.
sourceId =
"pin-display-override";
12765 .face =
"Arial Narrow" } };
12767 design.
symbols.emplace( symbol.
name, std::move( symbol ) );
12768 design.
packages.emplace( package.
name, std::move( package ) );
12769 design.
pages.push_back( std::move( page ) );
12773 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12774 schematic->SetProject( &manager.
Prj() );
12777 path.push_back( root );
12790 BOOST_ERROR(
"Pin name duplicated as SCH_TEXT" );
12799 symbol.
name =
"ROTATED_PIN_NUMBER.Normal";
12803 .hotptX = 0, .hotptY = 10 } };
12806 package.
name =
"ROTATED_PIN_NUMBER";
12807 package.
devices.push_back(
ORCAD_DEVICE{ .pinNumbers = {
"1" }, .pinIgnore = {
false } } );
12818 page.
name =
"ROTATED PIN NUMBER";
12819 page.
instances.push_back( std::move( placed ) );
12822 design.
sourceId =
"rotated-pin-number";
12823 design.
symbols.emplace( symbol.
name, std::move( symbol ) );
12824 design.
packages.emplace( package.
name, std::move( package ) );
12825 design.
pages.push_back( std::move( page ) );
12829 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12830 schematic->SetProject( &manager.
Prj() );
12833 path.push_back( root );
12838 BOOST_CHECK_GT(
pin->GetNumberTextSize(), 0 );
12843 BOOST_ERROR(
"Pin number duplicated as SCH_TEXT" );
12852 symbol.
name =
"ORDERED.Normal";
12859 pin.startX =
pin.hotptX;
12862 package.
name =
"ORDERED";
12864 package.
devices.push_back(
ORCAD_DEVICE{ .pinNumbers = {
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10" },
12865 .pinIgnore = std::vector<bool>( 10,
false ) } );
12876 placed.
pins.push_back(
ORCAD_PIN_INST{ static_cast<int16_t>( pin ), 90 + 10 * pin, 100 } );
12879 page.
name =
"ORDERED";
12880 page.
instances.push_back( std::move( placed ) );
12883 design.
sourceId =
"numeric-cache-pins";
12884 design.
symbols.emplace( symbol.
name, std::move( symbol ) );
12885 design.
packages.emplace( package.
name, std::move( package ) );
12886 design.
pages.push_back( std::move( page ) );
12890 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12891 schematic->SetProject( &manager.
Prj() );
12894 path.push_back( root );
12897 std::map<wxString, VECTOR2I> positions;
12900 positions[
pin->GetNumber()] =
pin->GetPosition();
12902 BOOST_REQUIRE_EQUAL( positions.size(), 4u );
12911 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
12913 if( !corpusEnv || !*corpusEnv )
12916 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"CY4605_Schematic.dsn" );
12921 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12924 schematic->SetProject( &manager.
Prj() );
12925 schematic->CurrentSheet().clear();
12926 schematic->CurrentSheet().push_back( &schematic->Root() );
12941 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
12943 if( !corpusEnv || !*corpusEnv )
12946 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"CYW920706WCDEVAL Evaluation Kit Schematics.DSN" );
12951 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12954 schematic->SetProject( &manager.
Prj() );
12955 schematic->CurrentSheet().clear();
12956 schematic->CurrentSheet().push_back( &schematic->Root() );
12971 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
12973 if( !corpusEnv || !*corpusEnv )
12976 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC2263A-2.DSN" );
12981 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
12984 schematic->SetProject( &manager.
Prj() );
12985 schematic->CurrentSheet().clear();
12986 schematic->CurrentSheet().push_back( &schematic->Root() );
13001 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13003 if( !corpusEnv || !*corpusEnv )
13006 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"OC_CONNECT-1_BB_BOARD_20072023_01.DSN" );
13011 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13014 schematic->SetProject( &manager.
Prj() );
13015 schematic->CurrentSheet().clear();
13016 schematic->CurrentSheet().push_back( &schematic->Root() );
13031 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13033 if( !corpusEnv || !*corpusEnv )
13036 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"710-DC2693A_REV02_PCA_SCHEMATIC.DSN" );
13041 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13044 schematic->SetProject( &manager.
Prj() );
13045 schematic->CurrentSheet().clear();
13046 schematic->CurrentSheet().push_back( &schematic->Root() );
13062 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13064 if( !corpusEnv || !*corpusEnv )
13067 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"OpenCellular_Connect-1_GBC_Life-3_Schematic_v1.2.DSN" );
13072 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13075 schematic->SetProject( &manager.
Prj() );
13076 schematic->CurrentSheet().clear();
13077 schematic->CurrentSheet().push_back( &schematic->Root() );
13092 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13094 if( !corpusEnv || !*corpusEnv )
13102 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13105 schematic->SetProject( &manager.
Prj() );
13106 schematic->CurrentSheet().clear();
13107 schematic->CurrentSheet().push_back( &schematic->Root() );
13121 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13123 if( !corpusEnv || !*corpusEnv )
13126 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"710-DC2222A_REV07_PCA_SCHEMATIC.DSN" );
13131 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13134 schematic->SetProject( &manager.
Prj() );
13135 schematic->CurrentSheet().clear();
13136 schematic->CurrentSheet().push_back( &schematic->Root() );
13153 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13155 if( !corpusEnv || !*corpusEnv )
13158 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC2382A-1.DSN" );
13163 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13166 schematic->SetProject( &manager.
Prj() );
13167 schematic->CurrentSheet().clear();
13168 schematic->CurrentSheet().push_back( &schematic->Root() );
13173 std::set<wxString> pinNumbers;
13181 if( symbol->
GetRef( &
path,
false ) != wxS(
"J3" ) )
13185 pinNumbers.insert(
pin->GetNumber() );
13192 expected.insert( wxString::Format( wxS(
"%d" ),
pin ) );
13209 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13211 if( !corpusEnv || !*corpusEnv )
13214 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"DC2382A-1.DSN" );
13219 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13222 schematic->SetProject( &manager.
Prj() );
13223 schematic->CurrentSheet().clear();
13224 schematic->CurrentSheet().push_back( &schematic->Root() );
13237 if( symbol->
GetRef( &
path,
false ) == wxS(
"JP4" ) )
13245 int bodyRectangles = 0;
13259 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13261 if( !corpusEnv || !*corpusEnv )
13264 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"X375D_VER72.DSN" );
13269 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13272 schematic->SetProject( &manager.
Prj() );
13273 schematic->CurrentSheet().clear();
13274 schematic->CurrentSheet().push_back( &schematic->Root() );
13287 if( symbol->
GetRef( &
path,
false ) != wxS(
"CLKOUT0" ) )
13301 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13303 if( !corpusEnv || !*corpusEnv )
13306 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SI8281V2-EVB.DSN" );
13311 m_plugin.LoadSchematicFile( dsn.string(), m_schematic.get() );
13312 std::map<wxString, SCH_SCREEN*> screensByFile;
13313 size_t connectorPins = 0;
13315 for(
const SCH_SHEET_PATH&
path : m_schematic->BuildSheetListSortedByPageNumbers() )
13318 auto [entry, inserted] = screensByFile.emplace( screen->
GetFileName().Lower(), screen );
13319 BOOST_CHECK_MESSAGE( inserted || entry->second == screen,
13320 "Distinct sheets share output file " << screen->
GetFileName() );
13326 if( symbol->
GetRef( &
path,
false ) == wxS(
"J24" ) )
13327 connectorPins += symbol->
GetPins().size();
13337 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13339 if( !corpusEnv || !*corpusEnv )
13342 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"M5275EVB.DSN" );
13347 m_plugin.LoadSchematicFile( dsn.string(), m_schematic.get() );
13350 for(
const SCH_SHEET_PATH&
path : m_schematic->BuildSheetListSortedByPageNumbers() )
13357 "Hidden hierarchical port " << label->
GetText() );
13362 BOOST_CHECK_GT( ports, 0 );
13368 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13370 if( !corpusEnv || !*corpusEnv )
13372 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping legacy hierarchy check." );
13376 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SCH-20380.DSN" );
13380 BOOST_TEST_MESSAGE(
"SCH-20380.DSN not present in corpus; skipping legacy hierarchy check." );
13384 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13387 schematic->SetProject( &manager.
Prj() );
13388 schematic->CurrentSheet().clear();
13389 schematic->CurrentSheet().push_back( &schematic->Root() );
13393 schematic->CurrentSheet().UpdateAllScreenReferences();
13396 size_t components = 0;
13421 *schematic, { {
"J7.54",
"RP17.3",
"U10.C13" },
13422 {
"J10.35",
"J12.9",
"RP15.7",
"U10.N10" } } );
13430 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13432 if( !corpusEnv || !*corpusEnv )
13435 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SCH-20380.DSN" );
13440 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13443 schematic->SetProject( &manager.
Prj() );
13444 schematic->CurrentSheet().clear();
13445 schematic->CurrentSheet().push_back( &schematic->Root() );
13450 const std::vector<std::set<std::string>>
expected = {
13462 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13464 if( !corpusEnv || !*corpusEnv )
13467 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SCH-20380.DSN" );
13472 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13475 schematic->SetProject( &manager.
Prj() );
13476 schematic->CurrentSheet().clear();
13477 schematic->CurrentSheet().push_back( &schematic->Root() );
13482 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
13483 schematic->ConnectionGraph()->Recalculate( sheets,
true );
13484 wxString j1Pin7Net;
13486 for(
const auto& [key, subgraphs] : schematic->ConnectionGraph()->GetNetMap() )
13490 for(
SCH_ITEM* item : subgraph->GetItems() )
13498 if( symbol && symbol->
GetRef( &subgraph->GetSheet(),
false ) == wxS(
"J1" )
13499 &&
pin->GetNumber() == wxS(
"7" ) )
13501 j1Pin7Net = key.Name;
13507 BOOST_CHECK( !j1Pin7Net.IsEmpty() );
13513 auto mapped = std::find_if( map->
entries.begin(), map->
entries.end(),
13516 return entry.sourceNetId == 3221698
13517 && entry.originalName == wxS(
"BDM_/RSTIN" );
13523 bool sourcePort =
false;
13528 sourcePort |=
static_cast<SCH_HIERLABEL*
>( item )->GetText() == wxS(
"BDM_/RSTIN" );
13531 BOOST_CHECK( sourcePort );
13537 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13539 if( !corpusEnv || !*corpusEnv )
13542 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SCH-21095.DSN" );
13547 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13550 schematic->SetProject( &manager.
Prj() );
13551 schematic->CurrentSheet().clear();
13552 schematic->CurrentSheet().push_back( &schematic->Root() );
13556 schematic->CurrentSheet().UpdateAllScreenReferences();
13565 if(
path.LastScreen()->GetFileName().Upper().Contains( wxS(
"MRAM" ) ) )
13567 else if(
path.LastScreen()->GetFileName().Upper().Contains( wxS(
"RESET" ) ) )
13580 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13582 if( !corpusEnv || !*corpusEnv )
13584 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping legacy flat-page check." );
13588 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"X375D_VER72.DSN" );
13592 BOOST_TEST_MESSAGE(
"X375D_VER72.DSN not present in corpus; skipping legacy flat-page check." );
13596 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13599 schematic->SetProject( &manager.
Prj() );
13600 schematic->CurrentSheet().clear();
13601 schematic->CurrentSheet().push_back( &schematic->Root() );
13611 catch(
const std::exception& e )
13613 BOOST_FAIL( e.what() <<
"\n" <<
reporter.GetMessages() );
13618 size_t components = 0;
13647 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13649 if( !corpusEnv || !*corpusEnv )
13651 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping legacy power-table check." );
13659 BOOST_TEST_MESSAGE(
"DC1414B.DSN not present in corpus; skipping legacy power-table check." );
13663 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13666 schematic->SetProject( &manager.
Prj() );
13667 schematic->CurrentSheet().clear();
13668 schematic->CurrentSheet().push_back( &schematic->Root() );
13672 schematic->CurrentSheet().UpdateAllScreenReferences();
13675 size_t components = 0;
13704 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13706 if( !corpusEnv || !*corpusEnv )
13720 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13723 schematic->SetProject( &manager.
Prj() );
13724 schematic->CurrentSheet().clear();
13725 schematic->CurrentSheet().push_back( &schematic->Root() );
13730 std::vector<SCH_SHEET*> topSheets = schematic->GetTopLevelSheets();
13731 BOOST_REQUIRE_EQUAL( topSheets.size(), 1u );
13733 SCH_SCREEN* rootScreen = topSheets.front()->GetScreen();
13735 size_t sheetPins = 0;
13741 sheetPins += sheet->
GetPins().size();
13744 const std::vector<wxString> expectedNames = { wxS(
"PAG_2" ), wxS(
"PAG_3" ), wxS(
"PAG_4" ), wxS(
"PAG_5" ),
13745 wxS(
"PAG_6" ), wxS(
"PAG_7" ), wxS(
"PAG_8" ), wxS(
"PAG_9" ) };
13746 const std::vector<size_t> expectedPinCounts = { 31, 24, 39, 47, 40, 33, 26, 10 };
13747 SCH_SHEET_LIST hierarchy = schematic->BuildSheetListSortedByPageNumbers();
13748 std::vector<wxString> sheetNames;
13749 std::vector<size_t> pinCounts;
13751 for(
auto it = std::next( hierarchy.begin() ); it != hierarchy.end(); ++it )
13754 std::set<wxString> sheetPinNames;
13755 std::set<wxString> hierarchicalLabelNames;
13758 pinCounts.push_back( sheet->
GetPins().size() );
13761 sheetPinNames.insert(
pin->GetText() );
13764 hierarchicalLabelNames.insert(
static_cast<SCH_HIERLABEL*
>( item )->GetText() );
13767 hierarchicalLabelNames.end() );
13770 schematic->ConnectionGraph()->Recalculate( hierarchy,
true );
13777 expectedPinCounts.end() );
13783 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13785 if( !corpusEnv || !*corpusEnv )
13791 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"SE_NGFOC-L_01.DSN" );
13795 BOOST_TEST_MESSAGE(
"SE_NGFOC-L_01.DSN not present in corpus; skipping issue 25009." );
13799 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13802 schematic->SetProject( &manager.
Prj() );
13803 schematic->CurrentSheet().clear();
13804 schematic->CurrentSheet().push_back( &schematic->Root() );
13809 const std::vector<wxString> expectedNames = { wxS(
"01.REV.HISTORY" ), wxS(
"02.uC" ), wxS(
"03.CAN" ),
13810 wxS(
"04. Ethercat" ), wxS(
"05.EtherSynch" ), wxS(
"06.RS-485" ),
13811 wxS(
"11.GPIO" ), wxS(
"12.Analog" ), wxS(
"13:IMU" ),
13812 wxS(
"14.Bridge" ), wxS(
"15.Encoder" ), wxS(
"29.uCPower" ),
13813 wxS(
"30.PowerSupply" ), wxS(
"31.Expansion" ) };
13815 std::vector<SCH_SHEET*> sheets = schematic->GetTopLevelSheets();
13816 BOOST_REQUIRE_EQUAL( sheets.size(), expectedNames.size() );
13823 for(
size_t i = 0; i < sheets.size(); ++i )
13827 for(
SCH_ITEM* item : sheets[i]->GetScreen()->Items() )
13866 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13868 if( !corpusEnv || !*corpusEnv )
13870 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping OrCAD OLB library import." );
13874 namespace fs = std::filesystem;
13875 std::vector<fs::path> libs;
13877 for(
auto it = fs::recursive_directory_iterator( fs::path( corpusEnv ),
13878 fs::directory_options::skip_permission_denied );
13879 it != fs::recursive_directory_iterator(); ++it )
13881 if( !it->is_regular_file() )
13884 std::string ext = it->path().extension().string();
13885 std::transform( ext.begin(), ext.end(), ext.begin(),
13886 [](
unsigned char c )
13888 return std::tolower( c );
13891 if( ext ==
".olb" )
13892 libs.push_back( it->path() );
13895 std::sort( libs.begin(), libs.end() );
13898 int totalSymbols = 0, emptySymbols = 0, checkedLibs = 0, rejectedLibs = 0, crashedLibs = 0;
13900 for(
const fs::path& lib : libs )
13903 std::vector<LIB_SYMBOL*> symbols;
13916 catch(
const std::exception& e )
13924 int withGeometry = 0;
13931 if( symbol->GetPinCount() > 0 || !symbol->GetDrawItems().empty() )
13937 BOOST_TEST_MESSAGE(
" " << lib.filename().string() <<
" : " << symbols.size() <<
" symbols, " << withGeometry
13938 <<
" with pins/graphics" );
13941 BOOST_TEST_MESSAGE(
"OLB summary: " << checkedLibs <<
" libs, " << rejectedLibs <<
" rejected, " << crashedLibs
13942 <<
" crashed, " << totalSymbols <<
" symbols, " << emptySymbols <<
" empty" );
13946 BOOST_CHECK_GT( totalSymbols, 0 );
13949 BOOST_CHECK_LT( emptySymbols, totalSymbols / 2 );
13957 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
13959 if( !corpusEnv || !*corpusEnv )
13961 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping OrCAD multi-page import." );
13965 namespace fs = std::filesystem;
13966 fs::path dsn = fs::path( corpusEnv ) /
"cutiepi-board" /
"CutiePi_V2.3-20210409.DSN";
13968 if( !fs::exists( dsn ) )
13974 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
13977 schematic->SetProject( &manager.
Prj() );
13978 schematic->CurrentSheet().clear();
13979 schematic->CurrentSheet().push_back( &schematic->Root() );
13988 std::vector<SCH_SHEET*> tops = schematic->GetTopLevelSheets();
13989 BOOST_REQUIRE_EQUAL( tops.size(), 3u );
13995 std::set<wxString> globalLabels;
14000 globalLabels.insert(
static_cast<SCH_LABEL_BASE*
>( item )->GetText() );
14004 BOOST_CHECK( globalLabels.count( wxS(
"CAM0_IO1" ) ) );
14005 BOOST_CHECK( globalLabels.count( wxS(
"AMP_SHUTDOWN" ) ) );
14008 bool checkedField =
false;
14016 if( sym->
GetRef( &
path,
false ) == wxS(
"R3197" ) )
14019 checkedField =
true;
14024 BOOST_CHECK( checkedField );
14030 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
14032 if( !corpusEnv || !*corpusEnv )
14034 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping flat-page instance-path check." );
14038 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"OCTOPAES_10.DSN" );
14042 BOOST_TEST_MESSAGE(
"OCTOPAES_10.DSN not present in corpus; skipping instance-path check." );
14046 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
14049 schematic->SetProject( &manager.
Prj() );
14050 schematic->CurrentSheet().clear();
14051 schematic->CurrentSheet().push_back( &schematic->Root() );
14060 if( !
path.LastScreen()->GetFileName().Contains( wxS(
"CPLD Power" ) ) )
14067 if( symbol->
GetRef( &
path,
false ) != wxS(
"P?" ) )
14073 return aInstance.m_Path == path.Path();
14075 std::string stored;
14078 stored += instance.m_Path.AsString().ToStdString() +
" ";
14080 BOOST_CHECK_MESSAGE( canonical,
"expected=" <<
path.Path().AsString() <<
" stored=" << stored );
14091 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
14093 if( !corpusEnv || !*corpusEnv )
14095 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping multi-page hierarchy check." );
14099 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"HB1A-AAFM.DSN" );
14103 BOOST_TEST_MESSAGE(
"HB1A-AAFM.DSN not present in corpus; skipping multi-page hierarchy check." );
14107 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
14110 schematic->SetProject( &manager.
Prj() );
14111 schematic->CurrentSheet().clear();
14112 schematic->CurrentSheet().push_back( &schematic->Root() );
14117 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
14118 schematic->ConnectionGraph()->Recalculate( sheets,
true );
14120 std::map<std::tuple<std::string, std::string, std::string>,
int> terminalNets;
14123 for(
const auto& [key, subgraphs] : schematic->ConnectionGraph()->GetNetMap() )
14127 std::string page = subgraph->GetSheet().LastScreen()->GetFileName().ToStdString();
14129 for(
SCH_ITEM* item : subgraph->GetItems() )
14139 terminalNets[{ page, symbol->
GetRef( &subgraph->GetSheet(),
false ).ToStdString(),
14140 pin->GetNumber().ToStdString() }] = netId;
14148 auto findNet = [&](
const std::string& aPage,
const std::string& aRef,
const std::string& aPin )
14150 for(
const auto& [terminal,
id] : terminalNets )
14152 if( std::get<0>( terminal ).
find( aPage ) != std::string::npos && std::get<1>( terminal ) == aRef
14153 && std::get<2>( terminal ) == aPin )
14162 int clockNet = findNet(
"Clock Generator",
"J1",
"1" );
14163 int fmcNet = findNet(
"FMC Connector",
"P1",
"H38" );
14164 BOOST_REQUIRE_NE( clockNet, -1 );
14165 BOOST_REQUIRE_NE( fmcNet, -1 );
14168 BOOST_CHECK_EQUAL( findNet(
"Clock Generator",
"J1",
"2" ), findNet(
"FMC Connector",
"P1",
"G37" ) );
14169 BOOST_CHECK_EQUAL( findNet(
"Clock Generator",
"U12",
"7" ), findNet(
"MAX II CPLD",
"U9",
"73" ) );
14170 BOOST_CHECK_EQUAL( findNet(
"Current Sense",
"U2",
"2" ), findNet(
"PROM & Misc",
"U6",
"4" ) );
14172 int mvddUr = findNet(
"Power & Control",
"TP13",
"1" );
14173 int mvddUl = findNet(
"Power & Control",
"TP30",
"1" );
14174 int mvddLr = findNet(
"Power & Control",
"TP14",
"1" );
14175 int mvddLl = findNet(
"Power & Control",
"TP31",
"1" );
14176 BOOST_REQUIRE_NE( mvddUr, -1 );
14177 BOOST_REQUIRE_NE( mvddUl, -1 );
14178 BOOST_REQUIRE_NE( mvddLr, -1 );
14179 BOOST_REQUIRE_NE( mvddLl, -1 );
14180 BOOST_CHECK_NE( mvddUr, mvddUl );
14181 BOOST_CHECK_NE( mvddUr, mvddLr );
14182 BOOST_CHECK_NE( mvddUr, mvddLl );
14183 BOOST_CHECK_NE( mvddUl, mvddLr );
14184 BOOST_CHECK_NE( mvddUl, mvddLl );
14185 BOOST_CHECK_NE( mvddLr, mvddLl );
14187 int urLclk = findNet(
"Link Ports NORTH_SOUTH",
"U4",
"V6" );
14188 int lrLclk = findNet(
"Link Ports NORTH_SOUTH",
"U8",
"A13" );
14189 BOOST_REQUIRE_NE( urLclk, -1 );
14190 BOOST_REQUIRE_NE( lrLclk, -1 );
14192 BOOST_CHECK_NE( urLclk, findNet(
"Link Ports NORTH_SOUTH",
"U4",
"V7" ) );
14194 int p1c35 = findNet(
"FMC Connector",
"P1",
"C35" );
14195 int p1c37 = findNet(
"FMC Connector",
"P1",
"C37" );
14196 BOOST_REQUIRE_NE( p1c35, -1 );
14197 BOOST_REQUIRE_NE( p1c37, -1 );
14200 wxString( wxS(
"ll_ul_ns_data_p_0" ) ) );
14206 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
14208 if( !corpusEnv || !*corpusEnv )
14210 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping power-symbol connectivity check." );
14214 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"POWER_SOURCE_BOARD_20180717.DSN" );
14218 BOOST_TEST_MESSAGE(
"POWER_SOURCE_BOARD_20180717.DSN not present; skipping power-symbol connectivity check." );
14222 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
14225 schematic->SetProject( &manager.
Prj() );
14226 schematic->CurrentSheet().clear();
14227 schematic->CurrentSheet().push_back( &schematic->Root() );
14232 std::vector<std::set<std::string>>
expected = {
14243 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
14245 if( !corpusEnv || !*corpusEnv )
14248 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"meta_carrier_sch_rev1.dsn" );
14252 BOOST_TEST_MESSAGE(
"meta_carrier_sch_rev1.dsn not present in corpus; skipping repeated bus check." );
14256 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
14259 schematic->SetProject( &manager.
Prj() );
14260 schematic->CurrentSheet().clear();
14261 schematic->CurrentSheet().push_back( &schematic->Root() );
14266 std::vector<std::set<std::string>>
expected = {
14267 {
"J1.1",
"J11.1" },
14268 {
"J12.239",
"J5.239" },
14269 {
"J15.239",
"J3.239" },
14270 {
"J4.1",
"J6.1" },
14276 wxString netName =
terminalNetName( *schematic, wxS(
"C103" ), wxS(
"1" ) );
14281 std::set<wxString> occurrenceNames;
14292 BOOST_CHECK( occurrenceNames.contains( netName ) );
14299 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
14301 if( !corpusEnv || !*corpusEnv )
14304 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"meta_module_sch_rev1.dsn" );
14308 BOOST_TEST_MESSAGE(
"meta_module_sch_rev1.dsn not present in corpus; skipping nested bus check." );
14312 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
14315 schematic->SetProject( &manager.
Prj() );
14316 schematic->CurrentSheet().clear();
14317 schematic->CurrentSheet().push_back( &schematic->Root() );
14322 std::vector<std::set<std::string>>
expected = {
14330 wxString netName =
terminalNetName( *schematic, wxS(
"R138" ), wxS(
"1" ) );
14335 std::set<wxString> occurrenceNames;
14346 BOOST_CHECK( occurrenceNames.contains( netName ) );
14353 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
14355 if( !corpusEnv || !*corpusEnv )
14358 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"HB1A-AAFM.DSN" );
14362 BOOST_TEST_MESSAGE(
"HB1A-AAFM.DSN not present in corpus; skipping renamed bus check." );
14366 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
14369 schematic->SetProject( &manager.
Prj() );
14370 schematic->CurrentSheet().clear();
14371 schematic->CurrentSheet().push_back( &schematic->Root() );
14376 std::vector<std::set<std::string>>
expected = {
14389 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
14391 if( !corpusEnv || !*corpusEnv )
14394 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"HB1A-AAFM.DSN" );
14399 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
14402 schematic->SetProject( &manager.
Prj() );
14403 schematic->CurrentSheet().clear();
14404 schematic->CurrentSheet().push_back( &schematic->Root() );
14409 auto [consistent, checkable] =
14421 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
14423 if( !corpusEnv || !*corpusEnv )
14426 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"buddy_sch_rev1.dsn" );
14430 BOOST_TEST_MESSAGE(
"buddy_sch_rev1.dsn not present in corpus; skipping block-pin geometry check." );
14434 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
14437 schematic->SetProject( &manager.
Prj() );
14438 schematic->CurrentSheet().clear();
14439 schematic->CurrentSheet().push_back( &schematic->Root() );
14444 std::vector<std::set<std::string>>
expected = {
14445 {
"J1.C10",
"U1.J19" }, {
"J1.C11",
"U1.K19" }, {
"J3.C10",
"U1.W33" },
14446 {
"J3.F28",
"U1.J35" }, {
"J1.E33",
"U1.B38" }, {
"J3.E33",
"U1.AV40" },
14452 wxString netName =
terminalNetName( *schematic, wxS(
"J6" ), wxS(
"F35" ) );
14453 BOOST_CHECK( !netName.IsEmpty() );
14456 auto mapped = std::find_if( map->
entries.begin(), map->
entries.end(),
14459 return entry.sourceNetId == 9578237
14460 && entry.originalName == wxS(
"CTRL_N3" )
14461 && entry.nameAtImport == netName;
14465 BOOST_REQUIRE_EQUAL( mapped->occurrence.size(), 3u );
14472 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
14474 if( !corpusEnv || !*corpusEnv )
14480 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"MC2_REV1_16_2.DSN" );
14488 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
14491 schematic->SetProject( &manager.
Prj() );
14492 schematic->CurrentSheet().clear();
14493 schematic->CurrentSheet().push_back( &schematic->Root() );
14508 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
14510 if( !corpusEnv || !*corpusEnv )
14513 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"710-DC2693A_REV02_PCA_SCHEMATIC.DSN" );
14519 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
14521 schematic->SetProject( &manager.
Prj() );
14522 schematic->CurrentSheet().clear();
14523 schematic->CurrentSheet().push_back( &schematic->Root() );
14539 BOOST_REQUIRE_EQUAL( j1->
GetPins().size(), 5u );
14541 std::vector<wxString> displayedNumbers;
14546 displayedNumbers.push_back(
pin->GetNumber() );
14549 BOOST_REQUIRE_EQUAL( displayedNumbers.size(), 1u );
14556 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
14558 if( !corpusEnv || !*corpusEnv )
14562 corpusEnv,
"CY8CPROTO-040T_PSoC_4000T_CapSense_Prototyping_Board_Schematic.DSN" );
14568 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
14570 schematic->SetProject( &manager.
Prj() );
14571 schematic->CurrentSheet().clear();
14572 schematic->CurrentSheet().push_back( &schematic->Root() );
14577 auto displayedPinNumbers = [](
SCH_SYMBOL& aSymbol )
14579 std::set<wxString> numbers;
14581 if( aSymbol.GetShowPinNumbers() )
14583 for(
const SCH_PIN*
pin : aSymbol.GetPins() )
14585 if(
pin->IsVisible() &&
pin->GetNumberTextSize() > 0 )
14586 numbers.insert(
pin->GetNumber() );
14615 BOOST_REQUIRE_EQUAL( j1->
GetPins().size(), 20u );
14617 std::set<wxString> j1PinText;
14621 BOOST_CHECK( !
pin->GetName().IsEmpty() );
14622 BOOST_CHECK( !
pin->GetNumber().IsEmpty() );
14623 BOOST_CHECK_GT(
pin->GetNameTextSize(), 0 );
14624 BOOST_CHECK_GT(
pin->GetNumberTextSize(), 0 );
14625 j1PinText.insert(
pin->GetName() );
14626 j1PinText.insert(
pin->GetNumber() );
14632 BOOST_CHECK( !j1PinText.contains(
static_cast<const SCH_TEXT&
>( item ).
GetText() ) );
14637 BOOST_CHECK( displayedPinNumbers( *u1 ).contains( wxS(
"23" ) ) );
14638 BOOST_CHECK( displayedPinNumbers( *u1 ).contains( wxS(
"H" ) ) );
14639 BOOST_CHECK( displayedPinNumbers( *j11 ).contains( wxS(
"1" ) ) );
14640 BOOST_CHECK( displayedPinNumbers( *j11 ).contains( wxS(
"10" ) ) );
14646 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
14648 if( !corpusEnv || !*corpusEnv )
14651 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"CY8CKIT-149 Schematic.DSN" );
14657 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
14659 schematic->SetProject( &manager.
Prj() );
14660 schematic->CurrentSheet().clear();
14661 schematic->CurrentSheet().push_back( &schematic->Root() );
14666 const wxImage* blockDiagram =
nullptr;
14667 size_t redShapesOnBlockDiagram = 0;
14668 size_t elephantNotes = 0;
14672 if(
path.Last()->GetName().Contains( wxS(
"Block Diagram" ) ) )
14679 ++redShapesOnBlockDiagram;
14687 if(
text.GetText() == wxS(
"*All Test Points are No Load" ) )
14691 int sourceBottom =
path.Last()->GetName().Contains( wxS(
"PSoC 4100S" ) ) ? 623 : 613;
14693 ink.
Offset(
text.GetSchematicTextOffset(
nullptr )
14694 +
text.GetOffsetToMatchSCH_FIELD(
nullptr ) );
14705 const wxImage*
image =
static_cast<SCH_BITMAP*
>( item )->GetReferenceImage().GetImage().GetImageData();
14710 > blockDiagram->GetWidth() * blockDiagram->GetHeight() ) )
14712 blockDiagram =
image;
14717 BOOST_REQUIRE_MESSAGE( blockDiagram,
"CY8CKIT-149 block diagram was not rendered at full size" );
14720 BOOST_CHECK( schematic->GetEmbeddedFiles()->HasFile( wxS(
"KiCadOrCADElephant-Black.ttf" ) ) );
14721 BOOST_CHECK( schematic->GetAreFontsEmbedded() );
14723 std::array<size_t, 3> blueColumns{};
14724 std::array<size_t, 3> blueRows{};
14725 const int width = blockDiagram->GetWidth();
14726 const int height = blockDiagram->GetHeight();
14728 for(
int y = 0; y < height; ++y )
14730 for(
int x = 0; x < width; ++x )
14732 int red = blockDiagram->GetRed( x, y );
14733 int green = blockDiagram->GetGreen( x, y );
14734 int blue = blockDiagram->GetBlue( x, y );
14738 ++blueColumns[std::min( 2, x * 3 / width )];
14739 ++blueRows[std::min( 2, y * 3 / height )];
14744 const size_t minimumBluePixels =
static_cast<size_t>( width ) * height / 500;
14746 BOOST_TEST_MESSAGE(
"block diagram size=" << width <<
'x' << height <<
" columns=" << blueColumns[0] <<
','
14747 << blueColumns[1] <<
',' << blueColumns[2] <<
" rows="
14748 << blueRows[0] <<
',' << blueRows[1] <<
',' << blueRows[2] );
14750 for(
size_t count : blueColumns )
14751 BOOST_CHECK_GE( count, minimumBluePixels );
14753 for(
size_t count : blueRows )
14754 BOOST_CHECK_GE( count, minimumBluePixels );
14762 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
14764 if( !corpusEnv || !*corpusEnv )
14766 BOOST_TEST_MESSAGE(
"KICAD_ORCAD_CORPUS not set; skipping OrCAD component detail." );
14770 namespace fs = std::filesystem;
14771 fs::path dsn = fs::path( corpusEnv ) /
"cutiepi-board" /
"CutiePi_V2.3-20210409.DSN";
14773 if( !fs::exists( dsn ) )
14779 std::unique_ptr<SCHEMATIC> schematic(
new SCHEMATIC(
nullptr ) );
14782 schematic->SetProject( &manager.
Prj() );
14783 schematic->CurrentSheet().clear();
14784 schematic->CurrentSheet().push_back( &schematic->Root() );
14789 std::map<wxString, SCH_SYMBOL*> symbols;
14790 std::multimap<wxString, int> labelSpins;
14791 int noConnects = 0;
14793 for(
SCH_SHEET*
top : schematic->GetTopLevelSheets() )
14798 for(
SCH_ITEM* item :
top->GetScreen()->Items() )
14819 BOOST_CHECK( symbols[wxS(
"U3" )]->GetShowPinNumbers() );
14820 BOOST_CHECK( symbols[wxS(
"U3" )]->GetShowPinNames() );
14822 BOOST_CHECK( !symbols[wxS(
"R3174" )]->GetShowPinNumbers() );
14823 BOOST_CHECK( !symbols[wxS(
"R3174" )]->GetShowPinNames() );
14827 BOOST_CHECK( !symbols[wxS(
"FB8" )]->GetField(
FIELD_T::VALUE )->IsVisible() );
14833 BOOST_CHECK_GT( fb8Ref->
GetPosition().
x, symbols[wxS(
"FB8" )]->GetPosition().x );
14840 for(
const wxString& ref : { wxS(
"R3186" ), wxS(
"C2517" ), wxS(
"R3189" ), wxS(
"FB13" ), wxS(
"FB9" ) } )
14842 BOOST_REQUIRE_MESSAGE( symbols.count( ref ), ref );
14851 bool checkedPower =
false;
14853 for(
SCH_SHEET*
top : schematic->GetTopLevelSheets() )
14860 if( val == wxS(
"REG1V8" ) || val == wxS(
"REG3V3" ) )
14863 checkedPower =
true;
14868 BOOST_CHECK( checkedPower );
14871 BOOST_CHECK_GE( noConnects, 17 );
14876 auto range = labelSpins.equal_range( aText );
14878 for(
auto it = range.first; it != range.second; ++it )
14880 if( it->second == (
int) aSpin )
14894 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
14896 if( !corpusEnv || !*corpusEnv )
14899 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"buddy_sch_rev1.dsn" );
14900 BOOST_REQUIRE_MESSAGE( !dsn.empty(),
"buddy_sch_rev1.dsn not present in corpus." );
14908 std::set<SCH_SCREEN*> visited;
14914 if( !visited.insert( screen ).second )
14917 std::vector<SCH_ITEM*> hidden;
14927 hidden.push_back( item );
14934 auto [consistent, checkable] =
14935 checkConnectivity( schematic, { {
"U1.BB5",
"J6.J30" }, {
"U1.BA5",
"J6.K31" } } );
14943 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
14945 if( !corpusEnv || !*corpusEnv )
14948 std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"M5275EVB.DSN" );
14949 BOOST_REQUIRE_MESSAGE( !dsn.empty(),
"M5275EVB.DSN not present in corpus." );
14957 std::set<SCH_SCREEN*> visited;
14963 if( !visited.insert( screen ).second )
14966 std::vector<SCH_LABEL_BASE*> hidden;
14973 hidden.push_back( label );
14978 screen->
Append(
new SCH_LABEL( label->GetPosition(), label->GetText() ) );
14983 const std::vector<std::set<std::string>>
expected = {
14984 {
"J3.38",
"RP49.7",
"U6.D10" },
14985 {
"J3.40",
"RP49.5",
"U6.D11" },
14986 {
"J3.42",
"RP49.3",
"U6.D12" },
14987 {
"J3.44",
"RP49.1",
"U6.D13" },
14988 {
"J4.43",
"RP16.4",
"RP45.5",
"RP9.8",
"TP33.1",
"U1.40",
"U7.47" },
14989 {
"J4.45",
"RP16.8",
"RP45.3",
"RP9.6",
"TP35.1",
"U1.39",
"U7.20" },
14990 {
"J4.47",
"RP9.4" },
14991 {
"J4.49",
"RP15.2",
"RP9.2",
"TP31.1",
"U7.24" },
14992 {
"J5.21",
"R37.2",
"RP50.1",
"U6.G13" },
14993 {
"J5.22",
"RP47.3",
"U6.E13" },
14994 {
"J5.23",
"RP50.3",
"U6.H16" },
14995 {
"J5.24",
"RP47.1",
"U2.6",
"U6.F13" },
14996 {
"J5.25",
"RP50.5",
"U6.H15" },
14997 {
"J5.27",
"RP50.7",
"U6.H14" },
14998 {
"J5.29",
"J9.11",
"RP48.3",
"U6.J14" },
14999 {
"J5.31",
"RP48.5",
"U6.J13",
"U8.25" },
15000 {
"J5.33",
"RP48.7",
"U6.K13",
"U9.25" },
15001 {
"J6.15",
"RP47.7",
"TP4.1",
"U11.12",
"U12.A8",
"U2.1",
"U6.R6" },
15002 {
"J6.21",
"RP47.5",
"U1.6",
"U2.3",
"U6.N7" },
15013 for(
int mode : { 0, 1, 2 } )
15015 const bool collide = mode != 0;
15016 const bool remoteGlobal = mode == 2;
15022 definition.
name =
"LOAD.Normal";
15026 page.
name =
"REPAIR NAMES";
15027 page.
netmap[1] =
"N1001";
15029 peerPage.
name =
"OTHER PAGE";
15034 const int x = (
index + 1 ) * 100;
15043 target.
instances.push_back( std::move( instance ) );
15047 const std::string
name =
index == 2 ?
"Net-(R1-Pad1)" :
"Net-(R1-Pad1)_2";
15049 ORCAD_WIRE wire{ .id = net, .x1 = x, .x2 = x + 40 };
15055 connector.
x = x + 20;
15056 target.
offpage.push_back( std::move( connector ) );
15064 target.
wires.push_back( std::move( wire ) );
15069 design.
sourceId =
"generated-repair-name-collision";
15070 design.
symbols.emplace( definition.
name, std::move( definition ) );
15071 design.
pages.push_back( std::move( page ) );
15074 design.
pages.push_back( std::move( peerPage ) );
15081 path.push_back( root );
15086 BOOST_REQUIRE_EQUAL( first->
GetPins( &
path ).size(), 1u );
15087 BOOST_REQUIRE_EQUAL( second->
GetPins( &
path ).size(), 1u );
15094 collide ? wxString(
"Net-(R1-Pad1)_3" ) : wxString(
"Net-(R1-Pad1)" ) );
15099 std::set<int> nets = { repaired->
NetCode() };
15105 collisionPath.
clear();
15111 for(
const wxString& reference : { wxString(
"R3" ), wxString(
"R4" ) } )
15115 BOOST_REQUIRE_EQUAL( symbol->
GetPins( &collisionPath ).size(), 1u );
15116 SCH_CONNECTION* connection = symbol->
GetPins( &collisionPath ).front()->Connection( &collisionPath );
15118 nets.insert( connection->
NetCode() );
15120 ? wxString(
"Net-(R1-Pad1)" ) : wxString(
"Net-(R1-Pad1)_2" ) );
15127 bool mapped =
false;
15131 if( entry.originalName == wxS(
"N1001" ) )
15138 BOOST_CHECK( mapped );
15146 const char* corpusEnv = std::getenv(
"KICAD_ORCAD_CORPUS" );
15148 if( !corpusEnv || !*corpusEnv )
15151 const std::filesystem::path dsn =
findCorpusDesign( corpusEnv,
"HB1A-AAFM.DSN" );
15155 BOOST_TEST_MESSAGE(
"HB1A-AAFM.DSN not present in corpus; skipping sheet-pin repair check." );
15165 std::set<std::set<std::string>> partitions;
15169 std::set<std::string> terminals;
15173 for(
SCH_ITEM* item : subgraph->GetItems() )
15180 wxString reference = symbol->
GetRef( &subgraph->GetSheet(),
false );
15182 if( !reference.IsEmpty() && !reference.StartsWith( wxS(
"#" ) ) )
15184 terminals.insert(
terminalToken( reference.ToStdString( wxConvUTF8 ),
15185 pin->GetNumber().ToStdString( wxConvUTF8 ) ) );
15190 partitions.insert( std::move( terminals ) );
15194 const std::map<std::string, std::set<std::string>>
expected = {
15205 BOOST_CHECK( partitions.count( terminals ) == 1 );
15213 const char* corpus = std::getenv(
"KICAD_ORCAD_CORPUS" );
15215 if( !corpus || !*corpus )
15227 BOOST_REQUIRE_NO_THROW( plugin.
LoadSchematicFile( dsn.string(), &schematic ) );
15228 bool found =
false;
15239 if(
pin->GetNumber() != wxS(
"3" ) )
15243 bool labelled =
false;
15244 bool junction =
false;
15249 BOOST_CHECK( !wire->GetSeg().Contains(
pin->GetPosition() ) );
15251 if( item->GetPosition() !=
pin->GetPosition() )
15256 if(
auto* label =
dynamic_cast<SCH_LABEL*
>( item ) )
15258 labelled |= label->GetText() == wxS(
"Agnd" );
15260 || label->GetTextColor().a > 0 );
15264 BOOST_CHECK( junction );
15265 BOOST_CHECK( labelled );
15269 BOOST_CHECK( found );
15271 for(
const wxString& reference : { wxString(
"COUT1" ), wxString(
"COUT2" ), wxString(
"COUT3" ) } )
15278 for(
int mode = 0; mode < 4; ++mode )
15280 const bool port = mode & 1;
15281 const bool entryOnBranch = mode & 2;
15287 definition.
name =
"LOAD.Normal";
15291 page.
name =
"LATE PIN";
15292 page.
netmap[1] =
"SIGNAL";
15293 const int branchEnd = entryOnBranch ? 20 : 5;
15295 ORCAD_WIRE{ .id = 1, .x1 = 100, .x2 = 100, .y2 = branchEnd } };
15304 page.
ports.push_back( std::move( connector ) );
15306 page.
offpage.push_back( std::move( connector ) );
15314 instance.
x =
index ? 200 : 100;
15315 instance.
y =
index ? 0 : branchEnd;
15317 .y = instance.
y, .wordB = 1 } );
15318 page.
instances.push_back( std::move( instance ) );
15322 design.
sourceId =
"interface-anchor-late-pin";
15323 design.
symbols.emplace( definition.
name, std::move( definition ) );
15324 design.
pages.push_back( std::move( page ) );
15330 path.push_back( root );
15335 BOOST_REQUIRE_EQUAL( first->
GetPins( &
path ).size(), 1u );
15336 BOOST_REQUIRE_EQUAL( second->
GetPins( &
path ).size(), 1u );
15350 for(
const VECTOR2I& point : item->GetConnectionPoints() )
15354 size_t contacts = 0;
constexpr EDA_IU_SCALE schIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
constexpr coord_type GetY() const
constexpr size_type GetWidth() const
constexpr Vec Centre() const
constexpr coord_type GetX() const
constexpr size_type GetHeight() const
constexpr const Vec & GetOrigin() const
constexpr coord_type GetRight() const
constexpr void Offset(coord_type dx, coord_type dy)
constexpr coord_type GetBottom() const
const NET_MAP & GetNetMap() const
void Recalculate(const SCH_SHEET_LIST &aSheetList, bool aUnconditional=false, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
Update the connection graph for the given list of sheets.
A subgraph is a set of items that are electrically connected on a single sheet.
virtual VECTOR2I GetPosition() const
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
KICAD_T Type() const
Returns the type of object.
virtual void SetEnd(const VECTOR2I &aEnd)
FILL_T GetFillMode() const
std::vector< VECTOR2I > GetPolyPoints() const
Duplicate the polygon outlines into a flat list of VECTOR2I points.
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
virtual VECTOR2I GetTextSize() const
COLOR4D GetTextColor() const
virtual const wxString & GetText() const
Return the string associated with the text object.
virtual bool IsVisible() const
virtual int GetTextHeight() const
KIFONT::FONT * GetFont() const
virtual EDA_ANGLE GetDrawRotation() const
BOX2I GetTextBox(const RENDER_SETTINGS *aSettings, int aLine=-1) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
virtual int GetTextWidth() const
GR_TEXT_H_ALIGN_T GetHorizJustify() const
double GetLineSpacing() const
virtual EDA_ANGLE GetTextAngle() const
std::shared_ptr< SHAPE_COMPOUND > GetEffectiveTextShape(bool aTriangulate=true, const BOX2I &aBBox=BOX2I(), const EDA_ANGLE &aAngle=ANGLE_0) const
build a list of segments (SHAPE_SEGMENT) to describe a text shape.
int GetInterline(const RENDER_SETTINGS *aSettings) const
Return the distance between two lines of text.
EE_TYPE OfType(KICAD_T aType) const
virtual void SetReporter(REPORTER *aReporter)
Set an optional reporter for warnings/errors.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
const wxString & GetName() const
A color representation with 4 components: red, green, blue, alpha.
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
std::string AsStdString() const
static KIID FromName(const std::string &aName)
Return a KIID derived from a name, the same name always gives the same KIID.
Define a library symbol object.
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
bool IsGlobalPower() const override
const SCH_PIN * GetPin(const wxString &aNumber, int aUnit=0, int aBodyStyle=0) const
Return pin object with the requested pin aNumber.
SCH_SHEET * Convert(SCH_SHEET *aRootSheet)
aRootSheet must have a screen and be registered on the schematic.
Limit reads to one record so a malformed body cannot consume the next record.
The caller owns the buffer.
static constexpr uint8_t PREAMBLE[4]
Magic preceding every framed structure body: FF E4 5C 39.
ReadStructure can recover from a body error when the prefix supplies a valid end offset.
ORCAD_PREFIXES ReadPrefixes(int aExpectedType=-1, size_t aEnclosingEnd=ORCAD_STREAM::npos, size_t aLongPrefixCount=ORCAD_STREAM::npos)
aLongPrefixCount overrides the type depth; aEnclosingEnd bounds all stops.
Describe the page size and margins of a paper page on which to eventually print or plot.
double GetHeightMils() const
int GetWidthIU(double aIUScale) const
Gets the page width in IU.
double GetWidthMils() const
const PAGE_SIZE_TYPE & GetType() const
A pure virtual class used to derive REPORTER objects from.
Holds all the data relating to one schematic.
SCH_SHEET_LIST BuildSheetListSortedByPageNumbers() const
SCH_ITEM * ResolveItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr, bool aAllowNullptrReturn=false) const
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
SCH_SHEET * GetTopLevelSheet(int aIndex=0) const
const IMPORT_NET_MAP * GetImportNetMap() const
void SetProject(PROJECT *aPrj)
CONNECTION_GRAPH * ConnectionGraph() const
void SetTopLevelSheets(const std::vector< SCH_SHEET * > &aSheets)
Replace the top level sheets, rebuilding the hierarchy and connectivity around them.
std::vector< SCH_SHEET * > GetTopLevelSheets() const
Get the list of top-level sheets.
SCH_SHEET_PATH & CurrentSheet() const
Object to handle a bitmap image that can be inserted in a schematic.
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString Name(bool aIgnoreSheet=false) const
GR_TEXT_V_ALIGN_T GetEffectiveVertJustify() const
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
VECTOR2I GetPosition() const override
EDA_ANGLE GetDrawRotation() const override
Adjusters to allow EDA_TEXT to draw/print/etc.
virtual const wxString & GetText() const override
Return the string associated with the text object.
wxString GetShownText(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, const wxString &aVariantName=wxEmptyString, int aDepth=0) const
GR_TEXT_H_ALIGN_T GetEffectiveHorizJustify() const
A SCH_IO derivation for loading schematic files using the new s-expression file format.
void SaveSchematicFile(const wxString &aFileName, SCH_SHEET *aSheet, SCHEMATIC *aSchematic, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aSchematic to a storage file in a format that this SCH_IO implementation knows about,...
SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load information from some input file format that this SCH_IO implementation knows about,...
bool CanReadSchematicFile(const wxString &aFileName) const override
The .dsn extension also identifies SPECCTRA files.
SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load information from some input file format that this SCH_IO implementation knows about,...
bool CanReadLibrary(const wxString &aFileName) const override
Checks if this IO object can read the specified library file/directory.
void EnumerateSymbolLib(wxArrayString &aSymbolNameList, const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Populate a list of LIB_SYMBOL alias names contained within the library aLibraryPath.
Base class for any item which can be embedded within the SCHEMATIC container class,...
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
SPIN_STYLE GetSpinStyle() const
LABEL_FLAG_SHAPE GetShape() const
Segment description base class to describe items which have 2 end points (track, wire,...
VECTOR2I GetEndPoint() const
VECTOR2I GetStartPoint() const
SEG GetSeg() const
Get the geometric aspect of the wire as a SEG.
COLOR4D GetLineColor() const
Return COLOR4D::UNSPECIFIED if a custom color hasn't been set for this line.
VECTOR2I GetPosition() const override
int GetNumberTextSize() const
const wxString & GetName() const
VECTOR2I GetPosition() const override
int GetNameTextSize() const
const PAGE_INFO & GetPageSettings() const
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
const wxString & GetFileName() const
const KIID & GetUuid() const
TITLE_BLOCK & GetTitleBlock()
void DeleteItem(SCH_ITEM *aItem)
Remove aItem from the linked list and deletes the object.
void SetPosition(const VECTOR2I &aPos) override
STROKE_PARAMS GetStroke() const override
VECTOR2I GetPosition() const override
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
SCH_SCREEN * LastScreen()
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
void clear()
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
void SetName(const wxString &aName)
SCH_SCREEN * GetScreen() const
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
std::vector< SCH_SHEET_PIN * > & GetPins()
bool GetShowPinNumbers() const override
std::vector< std::unique_ptr< SCH_PIN > > & GetRawPins()
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
std::vector< const SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
bool GetShowPinNames() const override
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
VECTOR2I GetPosition() const override
const LIB_ID & GetLibId() const override
const wxString GetValue(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, const wxString &aVariantName=wxEmptyString) const override
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
VECTOR2I GetPosition() const override
VECTOR2I GetOffsetToMatchSCH_FIELD(SCH_RENDER_SETTINGS *aRenderSettings) const
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
virtual VECTOR2I GetSchematicTextOffset(const RENDER_SETTINGS *aSettings) const
This offset depends on the orientation, the type of text, and the area required to draw the associate...
bool Contains(const SEG &aSeg) const
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Load a project or sets up a new project with a specified path.
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
KIGFX::COLOR4D GetColor() const
const TRANSFORM & GetTransform() const
const wxString & GetRevision() const
A wrapper for reporting to a wxString object.
static bool empty(const wxTextEntryBase *aCtrl)
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_VERTICAL
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
@ FILLED_SHAPE
Fill with object color.
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
@ BUS
the source net is carried by a bus
@ RESOLVED
exactly one physical net carries the source net
std::string GetEeschemaTestDataDir()
Get the configured location of Eeschema test data.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
bool OleRenderEmf(const std::vector< uint8_t > &aEmf, int aMaxWidth, int aMaxHeight, wxImage &aImage, double aTargetAspect)
std::vector< uint8_t > OleExtractCiImage(const std::vector< uint8_t > &aPayload)
The CI marker follows the preview DIB; the raster has a counted decimal length.
VECTOR2I OleWmfRenderSize(int aNaturalWidth, int aNaturalHeight, int aMaxWidth, int aMaxHeight, double aTargetAspect)
bool OleRenderWmf(const std::vector< uint8_t > &aWmf, int aMaxWidth, int aMaxHeight, wxImage &aImage, double aTargetAspect)
OLE_IMAGE_PAYLOAD ExtractOleImageFromPayload(const std::vector< uint8_t > &aPayload)
Read the picture out of an OLE object payload that carries the 26-byte prologue.
bool OleRenderMetafilePreview(const std::vector< uint8_t > &aWmf, int aMaxWidth, int aMaxHeight, wxImage &aImage, double aTargetAspect, bool *aUsedEmbeddedEmf)
Render a metafile preview, preferring an EMF the WMF carries over the WMF itself.
std::vector< uint8_t > OleExtractEmbeddedEmf(const std::vector< uint8_t > &aWmf)
Reassemble an EMF carried by WMF META_ESCAPE_ENHANCED_METAFILE records.
wxString OleDescribeImagePayload(const std::vector< uint8_t > &aPayload)
Include leading bytes when the payload format is unknown.
OLE_IMAGE_PAYLOAD ExtractOleImage(const uint8_t *aCfb, size_t aSize)
Prefer CONTENTS, then OlePres000, then the native stream.
void OrcadMergeSymbolGeneralProperties(std::map< std::string, ORCAD_SYMBOL_DEF > &aSymbols, const std::map< std::string, ORCAD_SYMBOL_DEF > &aMetadataSymbols)
std::optional< ORCAD_SYMBOL_PIN > OrcadReadSymbolPin(ORCAD_STRUCT_READER &aReader)
A zero byte marks an empty pin slot and returns nullopt.
std::optional< ORCAD_PRIMITIVE > OrcadReadPrimitive(ORCAD_STREAM &aStream)
Consumes one primitive and its optional preamble.
void OrcadParseCache(const std::vector< char > &aData, const std::vector< std::string > &aStrings, const ORCAD_WARN_FN &aWarn, std::map< std::string, ORCAD_SYMBOL_DEF > &aSymbols, std::map< std::string, ORCAD_PACKAGE > &aPackages)
The first entry is the default; later entries become variants.
ORCAD_SYMBOL_DEF OrcadReadSymbolDef(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes, bool aWithPins)
Set aWithPins to read the trailing pin and property lists.
std::map< uint32_t, bool > OrcadCisParseMemberships(const std::vector< char > &aData)
std::map< uint32_t, std::map< std::string, std::string > > OrcadCisParsePropertyUpdates(const std::vector< char > &aData)
std::string OrcadCisSelectVariant(const std::vector< std::string > &aNames, const std::optional< std::string > &aRequested)
ORCAD_CIS_SCHEMATIC_INFO OrcadCisParseSchematicInfo(const std::vector< char > &aData)
std::vector< std::string > OrcadCisParseCountedList(const std::vector< char > &aData, uint8_t aSeparator)
VECTOR2I OrcadDbuToIu(int aX, int aY)
bool OrcadDisplayPropShowsName(const ORCAD_DISPLAY_PROP &aProp)
FILL_T OrcadFillType(int aFillStyle, int aHatchStyle)
int OrcadLineWidthIu(int aWidth)
std::pair< double, double > OrcadDashRatios(int aFormatVersionMajor)
int OrcadTextBaselineOffset(int aTextSize)
std::vector< SEG > OrcadHatchLines(const EDA_SHAPE &aShape, int aHatchStyle, int aPitch)
int OrcadPageOrder(wxString &aName)
Return a numeric page prefix (or -1); strip only the "N - title" convention.
int OrcadHatchPitchIu(uint32_t aModifyTimestamp)
bool OrcadDisplayPropShowsValue(const ORCAD_DISPLAY_PROP &aProp)
int OrcadHatchLineWidthIu(uint32_t aModifyTimestamp)
KIGFX::COLOR4D OrcadColor(int aColorIndex)
wxString OrcadPinNameMarkup(const wxString &aName)
constexpr int ORCAD_IU_PER_DBU
Schematic internal units per OrCAD DBU: 10 mil * 254 IU/mil.
bool OrcadDisplayPropVisible(const ORCAD_DISPLAY_PROP &aProp)
LINE_STYLE OrcadLineStyle(int aStyle)
int OrcadPageGraphicLineWidthIu(int aWidth)
VECTOR2I OrcadStretchedImageSize(int aWidth, int aHeight, int aBoxWidth, int aBoxHeight)
ORCAD_PAGE_SETTINGS OrcadParsePageSettings(ORCAD_STREAM &aStream)
Consumes 156 bytes; throws IO_ERROR on overrun.
ORCAD_LIBRARY_INFO OrcadParseLibrary(const std::vector< char > &aData)
The Library version selects the string-count width.
std::vector< std::string > OrcadParsePageOrderV2(const std::vector< char > &aData, const std::vector< std::string > &aStrings)
Returns display order; throws IO_ERROR for invalid legacy framing.
void OrcadParseCacheV2(const std::vector< char > &aData, const std::vector< std::string > &aStrings, const ORCAD_WARN_FN &aWarn, std::map< std::string, ORCAD_SYMBOL_DEF > &aSymbols, std::map< std::string, ORCAD_PACKAGE > &aPackages)
Keep decoded entries if a framing error ends the legacy cache.
void OrcadParseOlbSymbolStreamV2(const std::vector< char > &aData, const std::vector< std::string > &aStrings, std::map< std::string, ORCAD_SYMBOL_DEF > &aSymbols, bool aShortDisplayProp)
aShortDisplayProp selects the version 1 display-property layout.
ORCAD_RAW_PAGE OrcadParsePageV2(const std::vector< char > &aData, const std::vector< std::string > &aStrings, const ORCAD_WARN_FN &, bool aShortDisplayProp)
Legacy records have no stop offsets.
void OrcadParseOlbPackageStreamV2(const std::vector< char > &aData, const std::vector< std::string > &aStrings, std::map< std::string, ORCAD_SYMBOL_DEF > &aSymbols, std::map< std::string, ORCAD_PACKAGE > &aPackages, bool aShortDisplayProp)
aShortDisplayProp selects the version 1 display-property layout.
std::vector< std::string > OrcadParsePageOrder(const std::vector< char > &aData)
Returns display order.
ORCAD_OCC_SCOPE OrcadReadOccurrenceTree(const std::vector< char > &aData, const std::vector< std::string > &aStrings, const ORCAD_WARN_FN &aWarn)
Returns occurrence references and child scopes.
ORCAD_OCC_SCOPE OrcadReadOccurrenceTreeV2(const std::vector< char > &aData, const std::vector< std::string > &aStrings)
Parse a short-prefix-only v2.0 Hierarchy stream without scan recovery.
std::vector< std::string > OrcadParseSchematicFolderOrder(const std::vector< char > &aData)
Unlisted Views storages can be stale.
std::function< void(const wxString &aMsg)> ORCAD_WARN_FN
Coordinates use DBU with Y down.
@ ORCAD_PRIM_COMMENT_TEXT
@ ORCAD_PRIM_SYMBOL_VECTOR
nested prefix-framed vector graphic
@ ORCAD_ST_TITLEBLOCK_SYMBOL
@ ORCAD_ST_GRAPHIC_ARC_INST
@ ORCAD_ST_SYMBOL_PIN_SCALAR
@ ORCAD_ST_DRAWN_INSTANCE
hierarchical block instance
@ ORCAD_ST_GLOBAL
placed power symbol
@ ORCAD_ST_OFFPAGE_CONNECTOR
@ ORCAD_ST_GLOBAL_SYMBOL
power symbol definition
@ ORCAD_ST_GRAPHIC_COMMENT_TEXT_INST
@ ORCAD_ST_GRAPHIC_ELLIPSE_INST
@ ORCAD_ST_ERC_OBJECT
saved design-rule-check marker
@ ORCAD_ST_SYMBOL_DISPLAY_PROP
@ ORCAD_ST_GRAPHIC_OLE_INST
ORCAD_BUS_ENTRY OrcadReadBusEntryBody(ORCAD_STREAM &aStream)
std::optional< size_t > OrcadLongPrefixCount(int aTypeId)
Registered number of long prefixes for a modern framed structure type.
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin.
std::string OrcadNormalizeCfbName(const std::string &aName)
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
bool collide(T aObject, U aAnotherObject, int aLayer, int aMinDistance)
Used by SHAPE_INDEX to implement Query().
std::vector< wxString > occurrence
std::vector< KIID > itemUuids
std::vector< IMPORT_NET_TERMINAL > terminals
Import provenance, held only for the lifetime of the importing SCHEMATIC.
std::vector< IMPORT_NET_MAP_ENTRY > entries
std::vector< uint8_t > data
The owning wire defines the connection.
Axis-aligned box in OrCAD DBU; corner order as stored (not normalized).
One interface pin of a hierarchical block, at its absolute page position.
Child-folder pages are instantiated for each occurrence, with that occurrence's references.
ORCAD_LIBRARY_INFO library
std::string sourceId
stable checksum of the input file
ORCAD_OCC_SCOPE occurrenceRoot
Occurrence references distinguish repeated placements of a child schematic.
std::map< std::string, ORCAD_SYMBOL_DEF > symbols
cache, keyed by cache name
std::map< std::string, ORCAD_PACKAGE > packages
keyed by package name
std::map< std::string, std::vector< ORCAD_RAW_PAGE > > childFolderPages
Child schematic folder pages, keyed by lower-cased folder name; instantiated once per hierarchical bl...
std::vector< ORCAD_RAW_PAGE > pages
root schematic folder pages
Device unit names omit the view suffix.
Display positions use symbol coordinates; rotFont combines the font index and quarter turns.
int rotation
0..3 quarter turns
std::string name
resolved property name (empty when index invalid)
The inline LibraryPart defines the block interface; placed pin records supply absolute positions.
std::string name
intrinsic Name property used for flat-net scoping
int x1
block rectangle top-left, page DBU
std::vector< ORCAD_BLOCK_PIN > pins
std::vector< ORCAD_DISPLAY_PROP > displayProps
Font indices are one-based; zero selects the default.
Free graphics use nested primitive coordinates.
std::unique_ptr< ORCAD_SYMBOL_DEF > nested
SthInPages0 body, else nullptr.
std::map< std::string, std::string > props
std::string name
cache symbol name
std::vector< ORCAD_DISPLAY_PROP > displayProps
std::string logicalName
ports: resolved net/port name
int typeId
ORCAD_ST value.
std::vector< std::string > strings
global string table
std::vector< ORCAD_FONT > fonts
int pinNumberFont
Design Template font ID (slot 11)
std::vector< int > templateFonts
template font ID -> 1-based LOGFONT index
int pinNameFont
Design Template font ID (slot 10)
Repeated child folders have separate scopes and reference designators.
uint32_t targetDbId
type-12 drawn-instance dbId on the parent page
ORCAD_OCC_SCOPE scope
the child's occurrences under this path
std::string childFolder
child schematic folder name
Each scope holds the references and child blocks for one instantiation path.
std::vector< ORCAD_OCC_BLOCK > blocks
hierarchical block occurrences
std::map< uint32_t, std::map< std::string, std::string > > partProps
dbId -> occurrence properties
std::map< uint32_t, std::string > netNames
occurrence net id -> effective net name
std::map< uint32_t, std::string > partRefs
type-13 dbId -> occurrence refdes
std::map< std::string, std::string > props
Part-level properties shared by every placement (Description, Tolerance, ...).
std::vector< ORCAD_PACKAGE > variants
later same-name cache entries in stream order
std::vector< ORCAD_DEVICE > devices
Dimensions use mils when isMetric is zero, otherwise micrometres.
Pin positions are absolute page connection points.
The placed box includes displayed text.
std::string sourcePackage
package base name
std::vector< ORCAD_DISPLAY_PROP > displayProps
int rotation
0..3 quarter turns
uint16_t unitIndex
zero-based package device index
std::map< std::string, std::string > props
short-prefix property pairs
bool mirror
orientation bit 2
std::string sourceLibrary
source library path from the placed-instance header
std::string value
resolved Part Value
std::vector< ORCAD_PIN_INST > pins
successfully parsed T0x10 records
Integer point in OrCAD DBU.
Prefix lengths supply structure bounds.
std::vector< size_t > stops
< (from the outermost long prefix); < 0 when unknown
int typeId
ORCAD_ST value (u8 in the stream)
std::vector< std::pair< uint32_t, uint32_t > > props
short prefix (nameIdx, valueIdx) pairs
std::vector< uint32_t > bodyLens
one per long prefix, outermost first
size_t end
offset right after the whole structure
Primitive byte lengths can include or exclude the eight-byte size envelope.
Wire IDs refer to netmap, which supplies the source net names.
std::vector< ORCAD_GRAPHIC_INST > ports
size_t sourcePageCount
pages in the OrCAD folder
std::map< uint32_t, std::vector< std::string > > netAliases
every name recorded for a net db id
std::vector< ORCAD_GRAPHIC_INST > globals
placed power symbols
std::map< uint32_t, std::string > netmap
net db id -> net name
std::vector< ORCAD_WIRE > wires
size_t sourcePageNumber
1-based within the OrCAD folder
uint32_t width
mils, or um when isMetric
std::vector< ORCAD_NET_GROUP > netGroups
bus net id -> member net ids
std::vector< ORCAD_DRAWN_INSTANCE > blocks
hierarchical blocks (detection only)
std::vector< ORCAD_PLACED_INSTANCE > instances
std::vector< ORCAD_GRAPHIC_INST > graphics
free comment text/shapes/images
std::vector< ORCAD_GRAPHIC_INST > offpage
off-page connectors
std::vector< ORCAD_GRAPHIC_INST > titleBlocks
std::vector< ORCAD_BUS_ENTRY > busEntries
std::string pageSize
page-size name string, e.g. "B"
std::vector< ORCAD_GRAPHIC_INST > ercObjects
saved design-rule-check markers
ORCAD_SCH_IMPORT_FIXTURE()
SCH_SHEET * LoadOrcadSchematic(const std::string &aRelPath)
std::unique_ptr< SCHEMATIC > m_schematic
std::string dataPath(const std::string &aRelPath) const
SETTINGS_MANAGER m_manager
~ORCAD_SCH_IMPORT_FIXTURE()
The bounding box occupies the final eight bytes before the next prefix stop.
std::string name
cache name, e.g. "C.Normal"
std::vector< ORCAD_SYMBOL_PIN > pins
std::vector< ORCAD_PRIMITIVE > primitives
bool synthesized
placeholder built from T0x10 data
std::map< std::string, std::string > props
int typeId
ORCAD_ST value.
std::optional< ORCAD_BBOX > bbox
symbol-space body box
std::vector< ORCAD_SYMBOL_DEF > variants
Variant zero is this entry.
int generalFlags
LibraryPart GeneralProperties flags (-1 = absent); bit0 = pin names visible, bit1 = pin text rotates ...
Pin coordinates use symbol space with Y down.
The wire ID refers to the page net table.
std::vector< ORCAD_ALIAS > aliases
A simple container for schematic symbol instance information.
@ DESCRIPTION
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ DATASHEET
name of datasheet
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_CHECK_EQUAL_COLLECTIONS(mixed.begin(), mixed.end(), expMixed.begin(), expMixed.end())
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
IbisParser parser & reporter
KIBIS top(path, &reporter)
VECTOR3I expected(15, 30, 45)
static std::vector< std::string > splitRefs(const std::string &aCell)
static std::filesystem::path findCorpusDesign(const std::filesystem::path &aRoot, const std::string &aFileName)
static std::set< std::string > parseBomRefs(const std::string &aPath)
static std::vector< std::set< std::string > > parseNetTerminals(const std::string &aPath)
Net terminal sets from .NET.
static std::set< std::string > expectedRefsFor(const std::filesystem::path &aDsn, std::string &aSource)
Ground-truth companion beside .DSN, .NET preferred over .BOM.
static std::string trimCell(std::string aText)
static SCH_SYMBOL * findConvertedSymbol(SCH_SCREEN &aScreen, const SCH_SHEET_PATH &aPath, const wxString &aReference)
static std::pair< int, int > checkConnectivity(SCHEMATIC &aSchematic, const std::vector< std::set< std::string > > &aNets, std::vector< std::set< std::string > > *aInconsistent=nullptr)
Count ground-truth nets whose resolvable terminals all land on one KiCad net after connectivity rebui...
static std::set< std::string > parseNetComs(const std::string &aPath)
static std::string terminalToken(const std::string &aRef, const std::string &aPin)
BOOST_AUTO_TEST_CASE(CisVariantFallbackSortsBomNamesBytewise)
static std::set< std::string > collectImportedRefs(SCHEMATIC &aSchematic)
Unique refdes of real (non-power) parts.
static wxString terminalNetName(SCHEMATIC &aSchematic, const wxString &aReference, const wxString &aPinNumber)
static SCH_SHEET * convertRawDesign(ORCAD_DESIGN &aDesign, SCHEMATIC &aSchematic, REPORTER *aReporter=nullptr)
static std::map< std::string, std::vector< std::string > > collectImportedUuids(const SCHEMATIC &aSchematic)
BOOST_TEST_CONTEXT("Test Clearance")
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I