1/*.......1.........2.........3.........4.........5.........6.........7.........8 2================================================================================ 3 4FILE d_ram/cfunc.mod 5 6Public Domain 7 8Georgia Tech Research Corporation 9Atlanta, Georgia 30332 10PROJECT A-8503-405 11 12 13AUTHORS 14 15 23 Aug 1991 Jeffrey P. Murray 16 17 18MODIFICATIONS 19 20 30 Sep 1991 Jeffrey P. Murray 21 22 23SUMMARY 24 25 This file contains the model-specific routines used to 26 functionally describe the d_ram code model. 27 28 29INTERFACES 30 31 FILE ROUTINE CALLED 32 33 CMevt.c void *cm_event_alloc() 34 void *cm_event_get_ptr() 35 36 37 38REFERENCED FILES 39 40 Inputs from and outputs to ARGS structure. 41 42 43NON-STANDARD FEATURES 44 45 NONE 46 47===============================================================================*/ 48 49/*=== INCLUDE FILES ====================*/ 50 51#include <stdio.h> 52#include <ctype.h> 53#include <math.h> 54#include <string.h> 55 56 57 58/*=== CONSTANTS ========================*/ 59 60 61 62 63/*=== MACROS ===========================*/ 64 65 66 67 68/*=== LOCAL VARIABLES & TYPEDEFS =======*/ 69 70 71 72 73/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ 74 75 76 77 78 79/*============================================================================== 80 81FUNCTION cm_address_to_decimal() 82 83AUTHORS 84 85 27 Jun 1991 Jeffrey P. Murray 86 87MODIFICATIONS 88 89 8 Jul 1991 Jeffrey P. Murray 90 30 Sep 1991 Jeffrey P. Murray 91 92SUMMARY 93 94 Calculates a decimal value from binary values passed. 95 96INTERFACES 97 98 FILE ROUTINE CALLED 99 100 N/A N/A 101 102 103RETURNED VALUE 104 105 A pointer containing the total (*total). 106 107GLOBAL VARIABLES 108 109 NONE 110 111NON-STANDARD FEATURES 112 113 NONE 114 115==============================================================================*/ 116 117/*=== CM_ADDRESS_TO_DECIMAL ROUTINE ===*/ 118 119/************************************************ 120* The following routine calculates a * 121* decimal value equivalent to the binary * 122* value passed to it on address[i] bits. * 123* The determined value is written to the * 124* integer *total. * 125* * 126* Created 6/27/91 J.P.Murray * 127************************************************/ 128 129 130static int cm_address_to_decimal(Digital_State_t *address,int address_size,int *total) 131{ 132 int i, /* indexing variable */ 133 multiplier, /* binary multiplier value */ 134 err; /* error value: 1 => output is unknown 135 0 => output is valid */ 136 137 err = 0; 138 *total = 0; 139 multiplier = 1; 140 141 for (i=0; i<address_size; i++) { 142 if ( UNKNOWN == address[i] ) { 143 err = 1; 144 break; 145 } 146 else { 147 if (address[i] == ONE) { 148 *total += multiplier; 149 } 150 } 151 multiplier *= 2; 152 } 153 154 return err; 155} 156 157 158 159/*============================================================================== 160 161FUNCTION cm_mask_and_store() 162 163AUTHORS 164 165 8 Jul 1991 Jeffrey P. Murray 166 167MODIFICATIONS 168 169 30 Sep 1991 Jeffrey P. Murray 170 171SUMMARY 172 173 Masks and stores a two-bit value into a passed short pointer, 174 using an offset value. This effectively handles storage of 175 eight two-bit values into a single short integer space in 176 order to conserve memory. 177 178INTERFACES 179 180 FILE ROUTINE CALLED 181 182 N/A N/A 183 184 185RETURNED VALUE 186 187 Returns updated *base value. 188 189GLOBAL VARIABLES 190 191 NONE 192 193NON-STANDARD FEATURES 194 195 NONE 196 197==============================================================================*/ 198 199/*=== CM_MASK_AND_STORE ROUTINE ===*/ 200 201/************************************************ 202* The following routine masks and stores * 203* the value passed to it by the out value * 204* by masking the appropriate bits in the * 205* base integer. The particular bit affected * 206* is determined by the ram_offset value. * 207* * 208* Created 7/8/91 J.P.Murray * 209************************************************/ 210 211static void cm_mask_and_store(short *base,int ram_offset,Digital_State_t out) 212{ 213 int val; 214 215 if ( ZERO == out ) 216 val = 0; 217 else if (ONE == out) 218 val = 1; 219 else 220 val = 2; 221 222 *base &= (short) ~ (3 << (ram_offset * 2)); 223 *base |= (short) (val << (ram_offset * 2)); 224} 225 226 227 228 229 230/*============================================================================== 231 232FUNCTION cm_mask_and_retrieve() 233 234AUTHORS 235 236 8 Jul 1991 Jeffrey P. Murray 237 238MODIFICATIONS 239 240 30 Sep 1991 Jeffrey P. Murray 241 242SUMMARY 243 244 This is a companion function to cm_mask_and_store(). 245 Masks off and retrieves a two-bit value from a short 246 integer word passed to the function, using an offset value. 247 This effectively handles retrieval of eight two-bit values 248 from a single short integer space in order to conserve memory. 249 250INTERFACES 251 252 FILE ROUTINE CALLED 253 254 N/A N/A 255 256 257RETURNED VALUE 258 259 Returns updated *base value. 260 261GLOBAL VARIABLES 262 263 NONE 264 265NON-STANDARD FEATURES 266 267 NONE 268 269==============================================================================*/ 270 271/*=== CM_MASK_AND_RETRIEVE ROUTINE ===*/ 272 273/************************************************** 274* The following routine masks and retrieves * 275* the value passed to it by the out value * 276* by masking the appropriate bits in the * 277* base integer. The particular bit affected * 278* is determined by the ram_offset value. * 279* * 280* Created 7/8/91 J.P.Murray * 281**************************************************/ 282 283static Digital_State_t cm_mask_and_retrieve(short base, int ram_offset) 284{ 285 int value = 0x0003 & (base >> (ram_offset * 2)); 286 287 switch (value) { 288 case 0: return ZERO; 289 case 1: return ONE; 290 default: return UNKNOWN; 291 } 292} 293 294 295 296/*============================================================================== 297 298FUNCTION cm_initialize_ram() 299 300AUTHORS 301 302 9 Jul 1991 Jeffrey P. Murray 303 304MODIFICATIONS 305 306 30 Sep 1991 Jeffrey P. Murray 307 308SUMMARY 309 310 This function stores digital data into specific short 311 integer array locations. 312 313INTERFACES 314 315 FILE ROUTINE CALLED 316 317 N/A N/A 318 319 320RETURNED VALUE 321 322 Returns updated ram[] value. 323 324GLOBAL VARIABLES 325 326 NONE 327 328NON-STANDARD FEATURES 329 330 NONE 331 332==============================================================================*/ 333 334/*=== CM_INITIALIZE_RAM ROUTINE ===*/ 335 336/************************************************ 337* The following routine stores two-bit * 338* data into short integer array "ram". The * 339* integers are assumed to be at least two * 340* bytes each, so each will hold eight two- * 341* bit values. * 342* * 343* Created 7/9/91 J.P.Murray * 344************************************************/ 345 346 347static void cm_initialize_ram(Digital_State_t out,int word_width,int bit_number, 348 int word_number,short *ram) 349{ 350 int /*err,*/ /* error index value */ 351 int1, /* temp storage variable */ 352 /*int2,*/ /* temp storage variable */ 353 ram_index, /* ram base address at which word bits will 354 be found */ 355 ram_offset; /* offset from ram base address at which bit[0] 356 of the required word can be found */ 357 358 short base; /* variable to hold current base integer for 359 comparison purposes. */ 360 361 362 /* obtain offset value from word_number, word_width & 363 bit_number */ 364 int1 = word_number * word_width + bit_number; 365 366 ram_index = int1 >> 3; 367 ram_offset = int1 & 7; 368 369 /* retrieve entire base_address ram integer... */ 370 base = ram[ram_index]; 371 372 /* for each offset, mask off the bits and store values */ 373 cm_mask_and_store(&base,ram_offset,out); 374 375 /* store modified base value */ 376 ram[ram_index] = base; 377 378} 379 380 381 382 383/*============================================================================== 384 385FUNCTION cm_store_ram_value() 386 387AUTHORS 388 389 27 Jun 1991 Jeffrey P. Murray 390 391MODIFICATIONS 392 393 9 Jul 1991 Jeffrey P. Murray 394 30 Sep 1991 Jeffrey P. Murray 395 396SUMMARY 397 398 This function stores digital data into specific short 399 integer array locations, after decoding address bits 400 passed to it (using cm_address_to_decimal routine). 401 402INTERFACES 403 404 FILE ROUTINE CALLED 405 406 N/A N/A 407 408 409RETURNED VALUE 410 411 Returns updated ram[] value via *ram pointer. 412 413GLOBAL VARIABLES 414 415 NONE 416 417NON-STANDARD FEATURES 418 419 NONE 420 421==============================================================================*/ 422 423/*=== CM_STORE_RAM_VALUE ROUTINE ===*/ 424 425/************************************************ 426* The following routine stores two-bit * 427* data into short integer array "ram". The * 428* integers are assumed to be at least two * 429* bytes each, so each will hold eight two- * 430* bit values. A sister routine, cm_get_ * 431* ram_value is used to retrieve the two- * 432* bit values from the "ram" array. * 433* * 434* Created 6/27/91 J.P.Murray * 435************************************************/ 436 437 438static void cm_store_ram_value(Digital_State_t out,int word_width,int bit_number, 439 Digital_State_t *address,int address_size, 440 short *ram) 441{ 442 int err, /* error index value */ 443 int1, /* temp storage variable */ 444 word_number, /* particular word of interest...this value 445 is derived from the passed address bits */ 446 ram_index, /* ram base address at which word bits will 447 be found */ 448 ram_offset; /* offset from ram base address at which bit[0] 449 of the required word can be found */ 450 451 short base; /* variable to hold current base integer for 452 comparison purposes. */ 453 454 /** first obtain word_number from *address values **/ 455 err = cm_address_to_decimal(address,address_size,&word_number); 456 457 if ( FALSE == err ) { /** valid data was returned...store value **/ 458 459 /* obtain offset value from word_number, word_width & 460 bit_number */ 461 int1 = word_number * word_width + bit_number; 462 463 ram_index = int1 >> 3; 464 ram_offset = int1 & 7; 465 466 /* retrieve entire base_address ram integer... */ 467 base = ram[ram_index]; 468 469 /* for each offset, mask off the bits and store values */ 470 cm_mask_and_store(&base,ram_offset,out); 471 472 /* store modified base value */ 473 ram[ram_index] = base; 474 475 } 476} 477 478 479 480 481 482/*============================================================================== 483 484FUNCTION cm_get_ram_value() 485 486AUTHORS 487 488 27 Jun 1991 Jeffrey P. Murray 489 490MODIFICATIONS 491 492 30 Sep 1991 Jeffrey P. Murray 493 494SUMMARY 495 496 This function retrieves digital data from specific short 497 integer array locations, after decoding address bits 498 passed to it (using cm_address_to_decimal routine). This 499 is a sister routine to cm_store_ram_value. 500 501INTERFACES 502 503 FILE ROUTINE CALLED 504 505 N/A N/A 506 507 508RETURNED VALUE 509 510 Returns output value via *out pointer. 511 512GLOBAL VARIABLES 513 514 NONE 515 516NON-STANDARD FEATURES 517 518 NONE 519 520==============================================================================*/ 521 522/*=== CM_GET_RAM_VALUE ROUTINE ===*/ 523 524/************************************************ 525* The following routine retrieves two-bit * 526* data from short integer array "ram". The * 527* integers are assumed to be at least two * 528* bytes each, so each will hold eight two- * 529* bit values. A sister routine, cm_store_ * 530* ram_value is used to store the two-bit * 531* values into the "ram" array. * 532* * 533* Created 6/27/91 J.P.Murray * 534************************************************/ 535 536static Digital_State_t cm_get_ram_value(int word_width,int bit_number,Digital_State_t *address, 537 int address_size,short *ram) 538 539{ 540 int err, /* error index value */ 541 int1, /* temp storage variable */ 542 word_number, /* particular word of interest...this value 543 is derived from the passed address bits */ 544 ram_index, /* ram base address at which word bits will 545 be found */ 546 ram_offset; /* offset from ram base address at which bit[0] 547 of the required word can be found */ 548 549 short base; /* variable to hold current base integer for 550 comparison purposes. */ 551 552 553 /** first obtain word_number from *address values **/ 554 err = cm_address_to_decimal(address,address_size,&word_number); 555 556 if ( FALSE == err ) { /** valid data was returned **/ 557 558 /* obtain offset value from word_number, word_width & 559 bit_number */ 560 int1 = word_number * word_width + bit_number; 561 562 ram_index = int1 >> 3; 563 ram_offset = int1 & 7; 564 565 /* retrieve entire base_address ram integer... */ 566 base = ram[ram_index]; 567 568 /* for each offset, mask off the bits and determine values */ 569 570 return cm_mask_and_retrieve(base,ram_offset); 571 572 } 573 else { /** incorrect data returned...return UNKNOWN values **/ 574 return UNKNOWN; 575 } 576} 577 578 579 580 581/*============================================================================== 582 583FUNCTION cm_d_ram() 584 585AUTHORS 586 587 26 Jun 1991 Jeffrey P. Murray 588 589MODIFICATIONS 590 591 30 Sep 1991 Jeffrey P. Murray 592 593SUMMARY 594 595 This function implements the d_ram code model. 596 597INTERFACES 598 599 FILE ROUTINE CALLED 600 601 CMevt.c void *cm_event_alloc() 602 void *cm_event_get_ptr() 603 604 605RETURNED VALUE 606 607 Returns inputs and outputs via ARGS structure. 608 609GLOBAL VARIABLES 610 611 NONE 612 613NON-STANDARD FEATURES 614 615 NONE 616 617==============================================================================*/ 618 619/*=== CM_D_RAM ROUTINE ===*/ 620 621/************************************************ 622* The following is the model for the * 623* digital M x N random access memory for the * 624* ATESSE Version 2.0 system. * 625* * 626* Created 6/26/91 J.P.Murray * 627************************************************/ 628 629 630void cm_d_ram(ARGS) 631 632{ 633 int i, /* generic loop counter index */ 634 j, /* generic loop counter index */ 635 ram_size, /* total number of words in ram */ 636 num_of_ram_ints, /* actual number of "short" integer 637 values necessary to store all of the 638 ram_size integers */ 639 address_size, /* total number of address lines */ 640 select_size, /* total number of address lines */ 641 select_value, /* decimal value compared with 642 select inputs to confirm that the 643 ram has indeed been activated */ 644 word_width, /* width of each word in bits */ 645 int_test, /* integer test variable */ 646 address_changed, /* TRUE if address is different from 647 that on the previous call...FALSE 648 otherwise */ 649 address_unknown; /* TRUE if currently-read address has 650 at least one line which is an unknown 651 value. */ 652 653 short int *ram, /* storage words...note that the 654 total ram data will be stored in the 655 two-bytes-per-Digital_State_t...since 656 we require 2 bits per ram bit (for 657 ZERO, ONE & UNKNOWN), we will store 658 8 ram bits per Digital_State_t 659 location */ 660 *ram_old; /* previous values of storage words */ 661 662 663 664 Digital_State_t *address, /* address line values */ 665 *address_old, /* previous address line values */ 666 *write_en, /* write_en value */ 667 *write_en_old, /* previous write_en value */ 668 *select, /* current selected state of ram... 669 note that this is derived from all 670 of the select lines into the ram */ 671 *select_old, /* previous selected state of ram */ 672 d_test, /* digital debugging variable */ 673 out; /* current output bit */ 674 675 676 677 678 679 /** retrieve device size values...& other parameters **/ 680 address_size = PORT_SIZE(address); 681 682 /* calculate ram word size from address size */ 683 ram_size = 1; 684 for (i=0; i<address_size; i++) { 685 ram_size *= 2; 686 } 687 688 select_size = PORT_SIZE(select); 689 select_value = PARAM(select_value); 690 word_width = PORT_SIZE(data_in); 691 692 693 num_of_ram_ints = (ram_size * word_width + 7) / 8; 694 695 696 697 698 /*** Setup required state variables ***/ 699 if(INIT) { /* initial pass */ 700 701 /* allocate storage */ 702 cm_event_alloc(0, address_size * (int) sizeof(Digital_State_t)); 703 cm_event_alloc(1, (int) sizeof(Digital_State_t)); 704 cm_event_alloc(2, select_size * (int) sizeof(Digital_State_t)); 705 706 707 /* allocate storage for ram memory */ 708 cm_event_alloc(3, num_of_ram_ints * (int) sizeof(short)); 709 710 /* declare load values */ 711 for (i=0; i<word_width; i++) { 712 LOAD(data_in[i]) = PARAM(data_load); 713 } 714 715 for (i=0; i<address_size; i++) { 716 LOAD(address[i]) = PARAM(address_load); 717 } 718 719 LOAD(write_en) = PARAM(enable_load); 720 721 for (i=0; i<select_size; i++) { 722 LOAD(select[i]) = PARAM(select_load); 723 } 724 725 /* retrieve storage for the outputs */ 726 address = address_old = (Digital_State_t *) cm_event_get_ptr(0,0); 727 write_en = write_en_old = (Digital_State_t *) cm_event_get_ptr(1,0); 728 select = select_old = (Digital_State_t *) cm_event_get_ptr(2,0); 729 730 /* retrieve ram base addresses */ 731 ram = ram_old = (short *) cm_event_get_ptr(3,0); 732 733 } 734 else { /* Retrieve previous values */ 735 736 /* retrieve storage for the outputs */ 737 address = (Digital_State_t *) cm_event_get_ptr(0,0); 738 address_old = (Digital_State_t *) cm_event_get_ptr(0,1); 739 write_en = (Digital_State_t *) cm_event_get_ptr(1,0); 740 write_en_old = (Digital_State_t *) cm_event_get_ptr(1,1); 741 select = (Digital_State_t *) cm_event_get_ptr(2,0); 742 select_old = (Digital_State_t *) cm_event_get_ptr(2,1); 743 744 /* retrieve ram base addresses */ 745 ram = (short *) cm_event_get_ptr(3,0); 746 ram_old = (short *) cm_event_get_ptr(3,1); 747 748 for(i=0;i<num_of_ram_ints;i++) 749 ram[i] = ram_old[i]; 750 } 751 752 753 754 755 756 /**** retrieve inputs ****/ 757 *write_en = INPUT_STATE(write_en); 758 759 address_changed = FALSE; 760 address_unknown = FALSE; 761 for (i=0; i<address_size; i++) { 762 address[i] = INPUT_STATE(address[i]); 763 if (UNKNOWN == address[i]) address_unknown = TRUE; 764 if (address[i] != address_old[i]) address_changed = TRUE; 765 } 766 767 768 /** Determine whether we are selected or not... **/ 769 770 /* retrieve the bit equivalents for the select lines */ 771 772 *select = ONE; 773 for (i=0; i<select_size; i++) { /* compare each bit in succession 774 with the value of each of the 775 select input lines. */ 776 if ( (d_test = INPUT_STATE(select[i])) != (int_test = (select_value & 0x0001)) ) { 777 *select = ZERO; 778 } 779 /* shift the values select_value bits for next compare... */ 780 select_value = select_value>>1; 781 } 782 783 784 785 786 787 788 789 /******* Determine analysis type and output appropriate values *******/ 790 791 if (0.0 == TIME) { /****** DC analysis...output w/o delays ******/ 792 793 /** initialize ram to ic value **/ 794 795 out = (Digital_State_t) PARAM(ic); 796 for (i=0; i<word_width; i++) { 797 for (j=0; j<ram_size; j++) { 798 cm_initialize_ram(out,word_width,i,j,ram); 799 } 800 } 801 802 if ( (ONE==*select) && (ZERO==*write_en) ) { 803 /* output STRONG initial conditions */ 804 for (i=0; i<word_width; i++) { 805 OUTPUT_STATE(data_out[i]) = (Digital_State_t) PARAM(ic); 806 OUTPUT_STRENGTH(data_out[i]) = STRONG; 807 } 808 } 809 else { /* change output to high impedance */ 810 for (i=0; i<word_width; i++) { 811 OUTPUT_STATE(data_out[i]) = UNKNOWN; 812 OUTPUT_STRENGTH(data_out[i]) = HI_IMPEDANCE; 813 } 814 } 815 } 816 817 else { /****** Transient Analysis ******/ 818 819 /***** Find input that has changed... *****/ 820 821 /**** Test select value for change ****/ 822 if ( *select != *select_old ) { /* either selected or de-selected */ 823 824 switch ( *select ) { 825 826 case ONE: /** chip is selected **/ 827 if ( ZERO == *write_en ) { /* need to retrieve new output */ 828 for (i=0; i<word_width; i++) { 829 /* for each output bit in the word, */ 830 /* retrieve the state value. */ 831 out = cm_get_ram_value(word_width,i,address,address_size,ram); 832 OUTPUT_STATE(data_out[i]) = out; 833 OUTPUT_STRENGTH(data_out[i]) = STRONG; 834 OUTPUT_DELAY(data_out[i]) = PARAM(read_delay); 835 } 836 } 837 else { /* store word & output current value */ 838 for (i=0; i<word_width; i++) { 839 if (address_unknown) { 840 /** entire ram goes unknown!!! **/ 841 for (j=0; j<ram_size; j++) { 842 cm_initialize_ram(UNKNOWN,word_width,i,j,ram); 843 } 844 OUTPUT_STATE(data_out[i]) = UNKNOWN; 845 } 846 else { 847 out = INPUT_STATE(data_in[i]); 848 cm_store_ram_value(out,word_width,i,address, 849 address_size,ram); 850 OUTPUT_STATE(data_out[i]) = out; 851 } 852 OUTPUT_STRENGTH(data_out[i]) = HI_IMPEDANCE; 853 OUTPUT_DELAY(data_out[i]) = PARAM(read_delay); 854 } 855 } 856 break; 857 858 859 case UNKNOWN: 860 case ZERO: /* output goes tristate unless already so... */ 861 if ( ZERO == *write_en ) { /* output needs tristating */ 862 for (i=0; i<word_width; i++) { 863 OUTPUT_STATE(data_out[i]) = UNKNOWN; 864 OUTPUT_STRENGTH(data_out[i]) = HI_IMPEDANCE; 865 OUTPUT_DELAY(data_out[i]) = PARAM(read_delay); 866 } 867 } 868 else { /* output will not change */ 869 for (i=0; i<word_width; i++) { 870 OUTPUT_CHANGED(data_out[i]) = FALSE; 871 } 872 } 873 break; 874 } 875 } 876 else { 877 878 /**** Either a change in write_en, a change in address 879 or a change in data values must have occurred... 880 all of these are treated similarly. ****/ 881 switch ( *write_en ) { 882 883 case ONE: 884 if ( (ONE == *select) ) { /* need to output tristates 885 & store current data word */ 886 for (i=0; i<word_width; i++) { 887 if (address_unknown) { 888 /** entire ram goes unknown!!! **/ 889 for (j=0; j<ram_size; j++) { 890 cm_initialize_ram(UNKNOWN,word_width,i,j,ram); 891 } 892 OUTPUT_STATE(data_out[i]) = UNKNOWN; 893 } 894 else { 895 out = INPUT_STATE(data_in[i]); 896 cm_store_ram_value(out,word_width,i,address, 897 address_size,ram); 898 OUTPUT_STATE(data_out[i]) = out; 899 } 900 OUTPUT_STRENGTH(data_out[i]) = HI_IMPEDANCE; 901 OUTPUT_DELAY(data_out[i]) = PARAM(read_delay); 902 } 903 } 904 else { /* output will not change */ 905 for (i=0; i<word_width; i++) { 906 OUTPUT_CHANGED(data_out[i]) = FALSE; 907 } 908 } 909 break; 910 911 case UNKNOWN: 912 case ZERO: /** output contents of current address if selected **/ 913 if ( ONE == *select) { /* store word & output current value */ 914 for (i=0; i<word_width; i++) { 915 if (address_unknown) { 916 /* output goes unknown */ 917 OUTPUT_STATE(data_out[i]) = UNKNOWN; 918 } 919 else { 920 /* for each output bit in the word, */ 921 /* retrieve the state value. */ 922 out = cm_get_ram_value(word_width,i,address, 923 address_size,ram); 924 OUTPUT_STATE(data_out[i]) = out; 925 } 926 OUTPUT_STRENGTH(data_out[i]) = STRONG; 927 OUTPUT_DELAY(data_out[i]) = PARAM(read_delay); 928 } 929 } 930 else { /* output will not change */ 931 for (i=0; i<word_width; i++) { 932 OUTPUT_CHANGED(data_out[i]) = FALSE; 933 } 934 } 935 break; 936 } 937 } 938 } 939} 940 941 942 943 944 945