C: Function working only in the first iteration

0

I am trying to design a pipelined cpu simulator. The code is fairly complex, atleast for me. There are multiple header and source files. The code compiles.

On running, it runs fine in the first iteration(clock cycle). But not so from the iteration. After spending hours on finding the fault, I found out what is wrong but don't know why. Following function:

MemoryAccess(ir, pc, ground, '0', instrMem); 

fetches an instruction at index "pc" in instrMem and store it in "ir". Following are the declarations of the variables in the function:

typedef char bit32[33];
bit8 instrMem[4096];    /* instruction memory */
bit32 pc, ir, ground;

The problem is that from the second iteration onwards, value of "ir" remains "00000000". I have checked instrMem, the values are not all 0s. I also checked the working of MemoryAccess() using driver function. It works fine.

I can't undertand why it works fine for the first iteration and not from then on.

Can someone please help. Is there a way of finding out what's wrong?

following is the relevant part of main() function:

   for(cycle=0; ; cycle++) 
{
    /* load IR with PC value */
    printf("I am at the beginning of the cycle loop");
    MemoryAccess(ir, pc, ground, '0', instrMem); 

    /* report fetched register values */
    printf("cycle: %d, PC: %.32s (%d), IR: %.32s\n\t", cycle, pc, bit32toint(pc), ir);

    /* halt check */
    if (bit32toint(ir) == 0x0000003F) {
        printf("\nmachine halted\n");
        break;
    }

    /* PC + 4 data path */
    RCAdder_32(pcPlus4, ground, pc, "00000000000000000000000000000100", '0');

    /* jump data path */
    shiftleftby2(jumpAddress, ir);
    jumpAddress[0] = pcPlus4[0];
    jumpAddress[1] = pcPlus4[1];
    jumpAddress[2] = pcPlus4[2];
    jumpAddress[3] = pcPlus4[3];

    /* sign extended / shifted immediate data path */
    signextend(immSignExt, &ir[16]); 
    shiftleftby2(immShifted, immSignExt); 

    /* control unit data path */
    ControlUnit(ir, &ir[26], &regWrite, &regDest,
                    &memRead, &memWrite, &memToReg, 
                    &jump, &branch, &aluSrc, aluOp);

    /* register memory data path - read */
    Mux2_5(regWriteAddr, &ir[11], &ir[16], regDest);
    registerAccess(&regOut1, &regOut2, &ir[6], &ir[11], regWriteAddr, regIn, '0');

    /* alu data path */
    Mux2_32(aluSrcVal, regOut2, immSignExt, aluSrc);
    zero = ALU(&aluOut, regOut1, aluSrcVal, aluOp);

    /* branch data path */
    RCAdder_32(branchAddress, ground, pcPlus4, immShifted, '0');
    Mux2_32(mbranchAddress, pcPlus4, branchAddress, AND2_1(zero, branch));
    Mux2_32(pc, mbranchAddress, jumpAddress, jump);

    /* main memory data path */
    MemoryAccess(memOut, aluOut, regOut2, memWrite, mainMem);
    Mux2_32(regIn, aluOut, memOut, memToReg);

    /* register memory data path - write */
    registerAccess(&regOut1, &regOut2, &ir[6], &ir[11], regWriteAddr, regIn, regWrite);

    /* dump register memory and signal information */
    for (i=0; i < 14; i++) {
        inttobitn(i, 5, tmp);
        registerAccess(&regOut1, &regOut2, tmp, &ir[11], regWriteAddr, regIn, '0');
        printf("R%d: %d, ", i, bit32toint(regOut1));
    }
    printf("\b\b\n\tbranchAddress = %.32s (%d) jumpAddress = %.32s (%d)\n",
        branchAddress, bit32toint(branchAddress), jumpAddress, bit32toint(jumpAddress));
    printf("\topcode = %.6s, immSignExt = %.32s (%d), immShifted = %.32s (%d), PC+4 = %.32s (%d)\n",
        ir, immSignExt, bit32toint(immSignExt), immShifted, bit32toint(immShifted), pcPlus4, bit32toint(pcPlus4));
    printf("\tregWrite = %c, regDest = %c, memRead = %c, memWrite = %c, memToReg = %c, jump = %c, branch = %c, aluSrc = %c, aluOp = %.3s, zero = %c\n",
        regWrite, regDest, memRead, memWrite, memToReg, jump, branch, aluSrc, aluOp, zero);
    getchar();
}

Following is the MemoryAccess() function:

void MemoryAccess(bit32 read_out, bit32 addr, bit32 write_in, signal write_enable, bit8 memory[4096]){

int address= bitntoint(12, addr);
setbit8(read_out, memory[address]);
setbit8(&read_out[8], memory[address+1]);
setbit8(&read_out[16], memory[address+2]);
setbit8(&read_out[24], memory[address+3]);

if (write_enable){
    setbit8(memory[address], write_in);
    setbit8(memory[address+1], &write_in[8]);
    setbit8(memory[address+2], &write_in[16]);
    setbit8(memory[address+3], &write_in[24]);
}

}

Setbit8(a, b) copies b into a and appends '\0'.

c
function
debugging
gdb
asked on Stack Overflow Jul 29, 2013 by nish • edited Jul 29, 2013 by nish

1 Answer

1

To long for a comment:

1 The code shown does not seem to be increasing pc.

2 Although you pass '0' as writabel flag, it is not used as intended. You might like to change

if (write_enable)

to be

if (write_enable && ('0' != (*write_enable)))

Due to the former version memory is overwritten with what is referenced by the pointer passed into as 3rd parameter (write_in), which propably are 0s.

answered on Stack Overflow Jul 29, 2013 by alk • edited Jul 29, 2013 by alk

User contributions licensed under CC BY-SA 3.0