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