@@ -126,7 +126,9 @@ nodenum_t nodes_c1c2s[NODES][2*NODES];
126
126
count_t nodes_gatecount [NODES ];
127
127
count_t nodes_c1c2count [NODES ];
128
128
nodenum_t nodes_dependants [NODES ];
129
+ nodenum_t nodes_left_dependants [NODES ];
129
130
nodenum_t nodes_dependant [NODES ][NODES ];
131
+ nodenum_t nodes_left_dependant [NODES ][NODES ];
130
132
131
133
/*
132
134
* The "value" propertiy of VCC and GND is never evaluated in the code,
@@ -225,6 +227,8 @@ list_t listout = {
225
227
.list = list2 ,
226
228
};
227
229
230
+ DECLARE_BITMAP (listout_bitmap , NODES );
231
+
228
232
static inline nodenum_t
229
233
listin_get (count_t i )
230
234
{
@@ -249,12 +253,16 @@ static inline void
249
253
listout_clear ()
250
254
{
251
255
listout .count = 0 ;
256
+ bitmap_clear (listout_bitmap , NODES );
252
257
}
253
258
254
259
static inline void
255
260
listout_add (nodenum_t i )
256
261
{
257
- listout .list [listout .count ++ ] = i ;
262
+ if (!get_bitmap (listout_bitmap , i )) {
263
+ listout .list [listout .count ++ ] = i ;
264
+ set_bitmap (listout_bitmap , i , 1 );
265
+ }
258
266
}
259
267
260
268
/************************************************************
@@ -265,7 +273,7 @@ listout_add(nodenum_t i)
265
273
266
274
/*
267
275
* a group is a set of connected nodes, which consequently
268
- * share the same potential
276
+ * share the same value
269
277
*
270
278
* we use an array and a count for O(1) insert and
271
279
* iteration, and a redundant bitmap for O(1) lookup
@@ -312,29 +320,49 @@ group_count()
312
320
*
313
321
************************************************************/
314
322
315
- BOOL group_contains_pullup ;
316
- BOOL group_contains_pulldown ;
317
- BOOL group_contains_hi ;
323
+ enum {
324
+ contains_nothing ,
325
+ contains_hi ,
326
+ contains_pullup ,
327
+ contains_pulldown ,
328
+ contains_vcc ,
329
+ contains_vss
330
+ } group_contains_value ;
318
331
319
332
static void
320
333
addNodeToGroup (nodenum_t n )
321
334
{
335
+ /*
336
+ * We need to stop at vss and vcc, otherwise we'll revisit other groups
337
+ * with the same value - just because they all derive their value from
338
+ * the fact that they are connected to vcc or vss.
339
+ */
340
+ if (n == vss ) {
341
+ group_contains_value = contains_vss ;
342
+ return ;
343
+ }
344
+ if (n == vcc ) {
345
+ if (group_contains_value != contains_vss )
346
+ group_contains_value = contains_vcc ;
347
+ return ;
348
+ }
349
+
322
350
if (group_contains (n ))
323
351
return ;
324
352
325
353
group_add (n );
326
354
327
- if (get_nodes_pullup (n ))
328
- group_contains_pullup = YES ;
329
- if ( get_nodes_pulldown ( n ))
330
- group_contains_pulldown = YES ;
331
- if ( get_nodes_value ( n ))
332
- group_contains_hi = YES ;
333
-
334
- if ( n == vss || n == vcc )
335
- return ;
355
+ if (group_contains_value < contains_pulldown && get_nodes_pulldown (n )) {
356
+ group_contains_value = contains_pulldown ;
357
+ }
358
+ if ( group_contains_value < contains_pullup && get_nodes_pullup ( n )) {
359
+ group_contains_value = contains_pullup ;
360
+ }
361
+ if ( group_contains_value < contains_hi && get_nodes_value ( n )) {
362
+ group_contains_value = contains_hi ;
363
+ }
336
364
337
- /* revisit all transistors that are controlled by this node */
365
+ /* revisit all transistors that control this node */
338
366
for (count_t t = 0 ; t < nodes_c1c2count [n ]; t ++ ) {
339
367
transnum_t tn = nodes_c1c2s [n ][t ];
340
368
/* if the transistor connects c1 and c2... */
@@ -353,29 +381,24 @@ addAllNodesToGroup(node)
353
381
{
354
382
group_clear ();
355
383
356
- group_contains_pullup = NO ;
357
- group_contains_pulldown = NO ;
358
- group_contains_hi = NO ;
384
+ group_contains_value = contains_nothing ;
359
385
360
386
addNodeToGroup (node );
361
387
}
362
388
363
389
static inline BOOL
364
390
getGroupValue ()
365
391
{
366
- if (group_contains (vss ))
367
- return NO ;
368
-
369
- if (group_contains (vcc ))
370
- return YES ;
371
-
372
- if (group_contains_pulldown )
373
- return NO ;
374
-
375
- if (group_contains_pullup )
376
- return YES ;
377
-
378
- return group_contains_hi ;
392
+ switch (group_contains_value ) {
393
+ case contains_vcc :
394
+ case contains_pullup :
395
+ case contains_hi :
396
+ return YES ;
397
+ case contains_vss :
398
+ case contains_pulldown :
399
+ case contains_nothing :
400
+ return NO ;
401
+ }
379
402
}
380
403
381
404
void
@@ -402,24 +425,33 @@ recalcNode(nodenum_t node)
402
425
set_nodes_value (nn , newv );
403
426
for (count_t t = 0 ; t < nodes_gatecount [nn ]; t ++ ) {
404
427
transnum_t tn = nodes_gates [nn ][t ];
405
- set_transistors_on (tn , !get_transistors_on (tn ));
428
+ set_transistors_on (tn , newv );
429
+ }
430
+
431
+ if (newv ) {
432
+ for (count_t g = 0 ; g < nodes_left_dependants [nn ]; g ++ ) {
433
+ listout_add (nodes_left_dependant [nn ][g ]);
434
+ }
435
+ } else {
436
+ for (count_t g = 0 ; g < nodes_dependants [nn ]; g ++ ) {
437
+ listout_add (nodes_dependant [nn ][g ]);
438
+ }
406
439
}
407
- listout_add (nn );
408
440
}
409
441
}
410
442
}
411
443
412
444
void
413
- recalcNodeList (const nodenum_t * source , count_t count )
445
+ recalcNodeList ()
414
446
{
415
- listout_clear ();
416
-
417
- for (count_t i = 0 ; i < count ; i ++ )
418
- recalcNode (source [i ]);
419
-
420
- lists_switch ();
421
-
422
447
for (int j = 0 ; j < 100 ; j ++ ) { /* loop limiter */
448
+ /*
449
+ * make the secondary list our primary list, use
450
+ * the data storage of the primary list as the
451
+ * secondary list
452
+ */
453
+ lists_switch ();
454
+
423
455
if (!listin_count ())
424
456
break ;
425
457
@@ -434,25 +466,10 @@ recalcNodeList(const nodenum_t *source, count_t count)
434
466
*/
435
467
for (count_t i = 0 ; i < listin_count (); i ++ ) {
436
468
nodenum_t n = listin_get (i );
437
- for (count_t g = 0 ; g < nodes_dependants [n ]; g ++ )
438
- recalcNode (nodes_dependant [n ][g ]);
469
+ recalcNode (n );
439
470
}
440
- /*
441
- * make the secondary list our primary list, use
442
- * the data storage of the primary list as the
443
- * secondary list
444
- */
445
- lists_switch ();
446
471
}
447
- }
448
-
449
- void
450
- recalcAllNodes ()
451
- {
452
- nodenum_t temp [NODES ];
453
- for (count_t i = 0 ; i < NODES ; i ++ )
454
- temp [i ] = i ;
455
- recalcNodeList (temp , NODES );
472
+ listout_clear ();
456
473
}
457
474
458
475
/************************************************************
@@ -464,9 +481,12 @@ recalcAllNodes()
464
481
static inline void
465
482
setNode (nodenum_t nn , BOOL state )
466
483
{
467
- set_nodes_pullup (nn , state );
468
- set_nodes_pulldown (nn , !state );
469
- recalcNodeList (& nn , 1 );
484
+ BOOL oldstate = get_nodes_pullup (nn );
485
+ if (state != oldstate ) {
486
+ set_nodes_pullup (nn , state );
487
+ set_nodes_pulldown (nn , !state );
488
+ listout_add (nn );
489
+ }
470
490
}
471
491
472
492
static inline BOOL
@@ -593,11 +613,12 @@ chipStatus()
593
613
readP (),
594
614
readIR ());
595
615
596
- if (clk )
616
+ if (clk ) {
597
617
if (r_w )
598
618
printf (" R$%04X=$%02X" , a , memory [a ]);
599
619
else
600
620
printf (" W$%04X=$%02X" , a , d );
621
+ }
601
622
printf ("\n" );
602
623
}
603
624
@@ -642,6 +663,7 @@ step()
642
663
643
664
/* invert clock */
644
665
setNode (clk0 , !clk );
666
+ recalcNodeList ();
645
667
646
668
/* handle memory reads and writes */
647
669
if (!clk )
@@ -668,6 +690,16 @@ add_nodes_dependant(nodenum_t a, nodenum_t b)
668
690
nodes_dependant [a ][nodes_dependants [a ]++ ] = b ;
669
691
}
670
692
693
+ static inline void
694
+ add_nodes_left_dependant (nodenum_t a , nodenum_t b )
695
+ {
696
+ for (count_t g = 0 ; g < nodes_left_dependants [a ]; g ++ )
697
+ if (nodes_left_dependant [a ][g ] == b )
698
+ return ;
699
+
700
+ nodes_left_dependant [a ][nodes_left_dependants [a ]++ ] = b ;
701
+ }
702
+
671
703
void
672
704
setupNodesAndTransistors ()
673
705
{
@@ -722,10 +754,22 @@ setupNodesAndTransistors()
722
754
723
755
for (i = 0 ; i < NODES ; i ++ ) {
724
756
nodes_dependants [i ] = 0 ;
757
+ nodes_left_dependants [i ] = 0 ;
725
758
for (count_t g = 0 ; g < nodes_gatecount [i ]; g ++ ) {
726
759
transnum_t t = nodes_gates [i ][g ];
727
- add_nodes_dependant (i , transistors_c1 [t ]);
728
- add_nodes_dependant (i , transistors_c2 [t ]);
760
+ nodenum_t c1 = transistors_c1 [t ];
761
+ if (c1 != vss && c1 != vcc ) {
762
+ add_nodes_dependant (i , c1 );
763
+ }
764
+ nodenum_t c2 = transistors_c2 [t ];
765
+ if (c2 != vss && c2 != vcc ) {
766
+ add_nodes_dependant (i , c2 );
767
+ }
768
+ if (c1 != vss && c1 != vcc ) {
769
+ add_nodes_left_dependant (i , c1 );
770
+ } else {
771
+ add_nodes_left_dependant (i , c2 );
772
+ }
729
773
}
730
774
}
731
775
}
@@ -748,14 +792,18 @@ resetChip()
748
792
setNode (irq , 1 );
749
793
setNode (nmi , 1 );
750
794
751
- recalcAllNodes ();
795
+ for (count_t i = 0 ; i < NODES ; i ++ )
796
+ listout_add (i );
797
+
798
+ recalcNodeList ();
752
799
753
800
/* hold RESET for 8 cycles */
754
801
for (int i = 0 ; i < 16 ; i ++ )
755
802
step ();
756
803
757
804
/* release RESET */
758
805
setNode (res , 1 );
806
+ recalcNodeList ();
759
807
760
808
cycle = 0 ;
761
809
}
0 commit comments