Appendix - code to size/shape the cache



next up previous
Next: About this document Up: DAN Processor Node: The Previous: Pcb and PALs

Appendix - code to size/shape the cache

This code uses ``debug'' accesses to the cache subsystem to work out the size and shape of the cache to pass in a cache reopen cell to the memory server.

    /* Figure out cache configuration */

    /* Check set 0 for 32 bit wide R/W memory */
    if ((set0 = probedata((volatile unsigned long *) 0xE0000000,
                          (volatile unsigned long *) 0xEFFFFFFF)) != 0)
    {
        outstr("Cache set 0 error. Data probe gives ");
        outhexnum(set0);
        outstr(".\n");
    }
    /* Check set 1 for 32 bit wide R/W memory */
    if ((set1 = probedata((volatile unsigned long *) 0xF0000000,
                          (volatile unsigned long *) 0xFFFFFFFF)) != 0)
    {
        outstr("Cache set 1 error. Data probe gives ");
        outhexnum(set1);
        outstr(".\n");
    }

    /* If neither set 0 nor 1 has 32 bit wide R/W then we can't go on */
    if (set0 && set1)
    {
        outstr("The cache has failed\n");
        return;
    }
    TRC(outstr("Check adr\n"));

    /* Now see how big the cache memory is by looking at *ACTUAL* RAM*/
    /* The idea is that since the lines will form a contiguous block */
    /* the result from the probe will have low bits valid == line    */
    /*                            next a block don't care == tag     */
    /*                              finally a block valid == region  */
    probeadr((volatile unsigned long *)0xE0000000, 
             0x1C, 0xffffffff, &aerr, &asame);
    /* lrbits is the valid bits - low valid is line, top valid is region */
    lrbits = aerr | asame | 0xf0000000;
    TRC(outhexnum(lrbits));
    
    /* zeros -> bit */
    TRC(outstr("find bits\n"));
    /* count line bits == the number of low valid bits */
    for(lcou=0, bit=32; ((lrbits & bit)==0);lcou++,bit<<=1);
    /* skip over tag bits which aren't real in the debug memory */
    for(tcou=0; (bit != 0) && ((lrbits & bit)!=0);tcou++,bit<<=1);
    /* the top valid bits are the region ones */
    for(rcou=0; (bit != 0) && ((lrbits & bit)==0);rcou++,bit<<=1);

    /* Having figured out the size work out associativity */
    if (set0 || set1)
        sa = 0x10; /* One set, direct mapped */
    else
    {
        /* Both valid, must work out if adr bit selects lru     */
        /* There are three cases:                               */
        /* a) Direct mapped, lru=0 only use set 0               */
        /* b) Direct mapped, lru=tag[4]=a17, set = a17          */
        /* c) 2way set assoc, lru=lru                           */
        volatile int *tag0 = (int *) 0xC0000000;
        volatile int *tag1 = (int *) 0xD0000000;
        volatile int *tag0a = (int *) 0xC0020000;
        volatile int *dat = (int *) 0x80000000;
        int x;
        
        /* First find out if it updates lru, which it only will */
        /* if it is two way assoc. The plan is to see which set */
        /* is marked as lru, set the tags to ensure a hit on it */
        /* and see if the lru bit has changed                   */
        *CCTRL_CMD = TAGR; /* NB this only resets the tag memory */
        if ((*tag0 & 0x200) == 0)
        {
            /* Now showing lru 0 */
            *tag0 = 0x80;
            x = *dat;
            if ((*tag0 & 0x200) == 0)
                /* No change -> direct map */
                sa = 0;
            else
                sa = 1;
        }
        else
        {
            /* Now showing lru 1 */
            *tag1 = 0x80;
            x = *dat;
            if ((*tag1 & 0x200) != 0)
                /* No change -> direct map */
                sa = 0;
            else
                sa = 1;
        }           
        /* Now we know if it is direct or set assoc */
        if (sa)
            sa = 0x21;  /* 2 sets, assoc */
        else
        {
            /* In the direct mapped case check for two sets     */
            /* by looking to see if the lru bit depends on A17  */
            if ((*tag0 & 0x200) == (*tag0a & 0x200))
                sa = 0x10; /* 1 set, not assoc */
            else
                sa = 0x20; /* 2 sets, not assoc */
        }
    }
    
    outstr("Cache has ");
    outdecnum(lcou);
    outstr(" bits line, ");
    outdecnum(tcou);
    outstr(" bits tag, ");
    outdecnum(rcou);
    outstr(" bits region, ");
    outhexnum(sa >> 4);
    if (sa & 1)
        outstr(" set associative");
    else
        outstr(" set direct map");
    outch('\n');

    /* Need to tell the memory server this */
    reopenCell[10] = lcou;
    reopenCell[11] = tcou;
    reopenCell[12] = rcou;
    reopenCell[13] = sa;


Mark Hayter