OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k/tags/or1k-1_0/or1ksim/cpu
    from Rev 249 to Rev 1765
    Reverse comparison

Rev 249 → Rev 1765

/dlx/Makefile
0,0 → 1,33
# Makefile -- Makefile for DLX architecture dependent simulation
# Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
#
# This file is part of OpenRISC 1000 Architectural Simulator.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
ARCH_OBJS = execute.o
 
all: $(ARCH_OBJS) ../arch.a
 
../arch.a: $(ARCH_OBJS) Makefile
$(AR) $(ARFLAGS) $@ $(ARCH_OBJS)
 
execute.o: execute.c ../common/execute.h ../common/abstract.h ../common/trace.h ../common/stats.h Makefile
$(CC) $(CCFLAGS) -o $@ $<
 
clean:
rm -f *.o *.a
 
distclean: clean
/dlx/arch.h
0,0 → 1,28
/* arch.h -- DLX architecture specific macros
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
#define LINK_REG "r31"
#define STACK_REG "r29"
#define FRAME_REG "r30"
 
#define MAX_GPRS 32
typedef unsigned long machword;
 
/* Should args be passed on stack */
#define STACK_ARGS 1
/dlx/execute.c
0,0 → 1,730
/* execute.c -- DLX dependent simulation
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
/* Most of the DLX simulation is done in this file. */
 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
#include "arch.h"
 
#include "branch_predict.h"
#include "abstract.h"
#include "parse.h"
#include "trace.h"
#include "execute.h"
#include "stats.h"
 
/* General purpose registers. */
machword reg[MAX_GPRS];
 
/* Instruction queue */
struct iqueue_entry iqueue[20];
 
/* Benchmark multi issue execution */
int multissue[20];
int supercycles;
 
/* Completition queue */
struct icomplet_entry icomplet[20];
 
/* Program counter */
unsigned long pc;
 
/* Temporary program counter */
unsigned long pctemp;
 
/* Cycles counts fetch stages */
int cycles;
 
/* Implementation specific.
Get an actual value of a specific register. */
 
machword eval_reg(char *regstr)
{
int regno;
regno = atoi(regstr + 1);
 
if (regno < MAX_GPRS)
return reg[regno];
else {
printf("\nEXCEPTION: read out of registers\n");
cont_run = 0;
return 0;
}
}
 
/* Implementation specific.
Set a specific register with value. */
 
void set_reg32(char *regstr, unsigned long value)
{
int regno;
regno = atoi(regstr + 1);
 
if (regno == 0) /* gpr0 is always zero */
value = 0;
if (regno < MAX_GPRS)
reg[regno] = value;
else {
printf("\nEXCEPTION: write out of registers\n");
cont_run = 0;
}
 
return;
}
 
/* Does srcoperand depend on computation of dstoperand? Return
non-zero if yes.
 
Cycle t Cycle t+1
dst: irrelevant src: immediate always 0
dst: reg1 direct src: reg2 direct 0 if reg1 != reg2
dst: reg1 disp src: reg2 direct always 0
dst: reg1 direct src: reg2 disp 0 if reg1 != reg2
dst: reg1 disp src: reg2 disp always 1 (store must
finish before load)
*/
 
int depend_operands(char *dstoperand, char *srcoperand)
{
char dst[OPERANDNAME_LEN];
char src[OPERANDNAME_LEN];
if (!srcoperand)
return 0;
 
if (!dstoperand)
return 0;
strcpy(dst, dstoperand);
strcpy(src, srcoperand);
 
if (*src == '#') /* immediate */
return 0;
else
if (!strstr(src, "("))
if (*src == 'r') { /* src: reg direct */
if (!strstr(dst, "("))
if (*dst == 'r')
if (strcmp(dst, src) == 0)
return 1; /* dst: reg direct */
else
return 0; /* dst: reg direct */
else
return 0; /* dst: addr */
else
return 0; /* dst: reg disp */
} else
return 0; /* src: addr */
else { /* src: register disp */
char *regstr;
regstr = strstr(src, "(r") + 1; /* regstr == "rXX)" */
*strstr(regstr, ")") = '\0'; /* regstr == "rXX" */
 
if (!strstr(dst, "("))
if (*dst == 'r')
if (strcmp(dst, regstr) == 0)
return 1; /* dst: reg direct */
else
return 0; /* dst: reg direct */
else
return 0; /* dst: addr */
else
return 1; /* dst: reg disp */
}
 
return 0;
}
 
/* Implementation specific.
Get an actual value represented by operand (register direct, register
indirect (with displacement), immediate etc.).
#n - immediate n
rXX - register direct
XX - relative or absolute address (labels)
n(XX) - register indirect (with displacement) */
machword eval_operand(char *srcoperand)
{
char operand[OPERANDNAME_LEN];
strcpy(operand, srcoperand);
 
if (*operand == '#') /* immediate */
return strtoul(&operand[1], NULL, 0);
else
if (!strstr(operand, "(")) /* not indirect but ...*/
if (*operand == 'r') /* ... register direct */
return eval_reg(operand);
else /* ... rel. or abs. address */
return eval_label(operand);
else { /* register indirect */
int disp; /* with possible displacement */
char *regstr;
unsigned int memaddr;
disp = atoi(operand); /* operand == "nn(rXX)" */
regstr = strstr(operand, "(r") + 1; /* regstr == "rXX)" */
*strstr(regstr, ")") = '\0'; /* regstr == "rXX" */
memaddr = eval_reg(regstr) + disp;
return eval_mem32(memaddr);
}
return 0;
}
 
/* Implementation specific.
Set destination operand (register direct, register indirect
(with displacement) with value. */
void set_operand(char *dstoperand, unsigned long value)
{
char operand[OPERANDNAME_LEN];
strcpy(operand, dstoperand);
 
if (*operand == '#') /* immediate */
printf("INTERNAL ERROR: Can't set immediate operand.\n");
else
if (!strstr(operand, "(")) /* not indirect but ...*/
if (*operand == 'r') /* ... register direct */
set_reg32(operand, value);
else /* ... rel. or abs. address */
printf("INTERNAL ERROR: Can't set addr operand.\n");
else { /* register indirect */
int disp; /* with possible displacement */
char *regstr;
unsigned int memaddr;
disp = atoi(operand); /* operand == "nn(rXX)" */
regstr = strstr(operand, "(r") + 1; /* regstr == "rXX)" */
*strstr(regstr, ")") = '\0'; /* regstr == "rXX" */
memaddr = eval_reg(regstr) + disp;
set_mem32(memaddr, value);
}
return;
}
 
void reset()
{
cycles = 0;
supercycles = 0;
memset(reg, 0, sizeof(reg));
memset(iqueue, 0, sizeof(iqueue));
memset(icomplet, 0, sizeof(icomplet));
pctemp = eval_label("_main");
pc = pctemp;
set_reg32(STACK_REG , MEMORY_LEN - STACK_SIZE);
}
 
void fetch()
{
/* Cycles after reset. */
cycles++;
 
/* Fetch instruction. */
strcpy(iqueue[0].insn, mem[pc].insn);
strcpy(iqueue[0].op1, mem[pc].op1);
strcpy(iqueue[0].op2, mem[pc].op2);
strcpy(iqueue[0].op3, mem[pc].op3);
iqueue[0].insn_addr = pc;
iqueue[0].dependdst = NULL;
iqueue[0].dependsrc1 = NULL;
iqueue[0].dependsrc2 = NULL;
 
/* Increment program counter. */
pc = pctemp;
pctemp += 4;
/* Check for breakpoint. */
if (mem[pc].brk)
cont_run = 0; /* Breakpoint set. */
return;
}
 
void decode(struct iqueue_entry *cur)
{
 
cur->dependdst = cur->op1;
cur->dependsrc1 = cur->op2; /* for calculating register */
cur->dependsrc2 = cur->op3; /* dependency */
cur->func_unit = unknown;
if (strcmp(cur->insn, "sw") == 0) {
cur->func_unit = store;
set_operand(cur->op1, eval_operand(cur->op2));
} else
if (strcmp(cur->insn, "sb") == 0) {
cur->func_unit = store;
set_operand(cur->op1, (eval_operand(cur->op2) << 24) + (eval_operand(cur->op1) & 0xffffff));
} else
if (strcmp(cur->insn, "sh") == 0) {
cur->func_unit = store;
set_operand(cur->op1, (eval_operand(cur->op2) << 16) + (eval_operand(cur->op1) & 0xffff));
} else
if (strcmp(cur->insn, "lw") == 0) {
cur->func_unit = load;
set_operand(cur->op1, eval_operand(cur->op2));
} else
if (strcmp(cur->insn, "lb") == 0) {
signed char temp = (eval_operand(cur->op2) >> 24);
cur->func_unit = load;
set_operand(cur->op1, temp);
} else
if (strcmp(cur->insn, "lbu") == 0) {
unsigned char temp = (eval_operand(cur->op2) >> 24);
cur->func_unit = load;
set_operand(cur->op1, temp);
} else
if (strcmp(cur->insn, "lh") == 0) {
signed short temp = (eval_operand(cur->op2) >> 16);
cur->func_unit = load;
set_operand(cur->op1, temp);
} else
if (strcmp(cur->insn, "lhu") == 0) {
unsigned short temp = (eval_operand(cur->op2) >> 16);
cur->func_unit = load;
set_operand(cur->op1, temp);
} else
if (strcmp(cur->insn, "lwi") == 0) {
cur->func_unit = movimm;
set_operand(cur->op1, eval_operand(cur->op2));
} else
if (strcmp(cur->insn, "lhi") == 0) {
cur->func_unit = movimm;
set_operand(cur->op1, eval_operand(cur->op2) << 16);
} else
if (strcmp(cur->insn, "and") == 0) {
cur->func_unit = arith;
set_operand(cur->op1, eval_operand(cur->op2) & eval_operand(cur->op3));
} else
if (strcmp(cur->insn, "andi") == 0) {
cur->func_unit = arith;
set_operand(cur->op1, eval_operand(cur->op2) & eval_operand(cur->op3));
} else
if (strcmp(cur->insn, "or") == 0) {
cur->func_unit = arith;
set_operand(cur->op1, eval_operand(cur->op2) | eval_operand(cur->op3));
} else
if (strcmp(cur->insn, "ori") == 0) {
cur->func_unit = arith;
set_operand(cur->op1, eval_operand(cur->op2) | eval_operand(cur->op3));
} else
if (strcmp(cur->insn, "xor") == 0) {
cur->func_unit = arith;
set_operand(cur->op1, eval_operand(cur->op2) ^ eval_operand(cur->op3));
} else
if (strcmp(cur->insn, "add") == 0) {
signed long temp3, temp2, temp1;
signed char temp4;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3);
temp2 = eval_operand(cur->op2);
temp1 = temp2 + temp3;
set_operand(cur->op1, temp1);
temp4 = temp1;
if (temp4 == temp1)
mstats.byteadd++;
} else
if (strcmp(cur->insn, "addi") == 0) {
signed long temp3, temp2, temp1;
signed char temp4;
cur->func_unit = arith;
temp3 = eval_operand(cur->op3);
temp2 = eval_operand(cur->op2);
temp1 = temp2 + temp3;
set_operand(cur->op1, temp1);
temp4 = temp1;
if (temp4 == temp1)
mstats.byteadd++;
} else
if (strcmp(cur->insn, "addui") == 0) {
unsigned long temp3, temp2, temp1;
unsigned char temp4;
cur->func_unit = arith;
temp3 = eval_operand(cur->op3);
temp2 = eval_operand(cur->op2);
temp1 = temp2 + temp3;
set_operand(cur->op1, temp1);
temp4 = temp1;
if (temp4 == temp1)
mstats.byteadd++;
} else
if (strcmp(cur->insn, "sub") == 0) {
signed long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3);
temp2 = eval_operand(cur->op2);
temp1 = temp2 - temp3;
set_operand(cur->op1, temp1);
} else
if (strcmp(cur->insn, "subui") == 0) {
unsigned long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3);
temp2 = eval_operand(cur->op2);
temp1 = temp2 - temp3;
set_operand(cur->op1, temp1);
} else
if (strcmp(cur->insn, "subi") == 0) {
signed long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3);
temp2 = eval_operand(cur->op2);
temp1 = temp2 - temp3;
set_operand(cur->op1, temp1);
} else
if (strcmp(cur->insn, "mul") == 0) {
signed long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3);
temp2 = eval_operand(cur->op2);
temp1 = temp2 * temp3;
set_operand(cur->op1, temp1);
} else
if (strcmp(cur->insn, "div") == 0) {
signed long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3);
temp2 = eval_operand(cur->op2);
temp1 = temp2 / temp3;
set_operand(cur->op1, temp1);
} else
if (strcmp(cur->insn, "divu") == 0) {
unsigned long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3);
temp2 = eval_operand(cur->op2);
temp1 = temp2 / temp3;
set_operand(cur->op1, temp1);
} else
if (strcmp(cur->insn, "slli") == 0) {
cur->func_unit = shift;
set_operand(cur->op1, eval_operand(cur->op2) << eval_operand(cur->op3));
} else
if (strcmp(cur->insn, "sll") == 0) {
cur->func_unit = shift;
set_operand(cur->op1, eval_operand(cur->op2) << eval_operand(cur->op3));
} else
if (strcmp(cur->insn, "srl") == 0) {
cur->func_unit = shift;
set_operand(cur->op1, eval_operand(cur->op2) >> eval_operand(cur->op3));
} else
if (strcmp(cur->insn, "srai") == 0) {
cur->func_unit = shift;
set_operand(cur->op1, (signed)eval_operand(cur->op2) / (1 << eval_operand(cur->op3)));
} else
if (strcmp(cur->insn, "sra") == 0) {
cur->func_unit = shift;
set_operand(cur->op1, (signed)eval_operand(cur->op2) / (1 << eval_operand(cur->op3)));
} else
if (strcmp(cur->insn, "jal") == 0) {
cur->func_unit = jump;
pctemp = eval_operand(cur->op1);
set_reg32(LINK_REG, pc + 4);
} else
if (strcmp(cur->insn, "jr") == 0) {
cur->func_unit = jump;
cur->dependsrc1 = cur->op1;
pctemp = eval_operand(cur->op1);
} else
if (strcmp(cur->insn, "j") == 0) {
cur->func_unit = jump;
pctemp = eval_operand(cur->op1);
} else
if (strcmp(cur->insn, "nop") == 0) {
cur->func_unit = nop;
} else
if (strcmp(cur->insn, "beqz") == 0) {
cur->func_unit = branch;
cur->dependsrc1 = cur->op1;
if (eval_operand(cur->op1) == 0) {
pctemp = eval_operand(cur->op2);
mstats.beqz.taken++;
bpb_update(cur->insn_addr, 1);
btic_update(pctemp);
} else {
mstats.beqz.nottaken++;
bpb_update(cur->insn_addr, 0);
btic_update(pc);
}
} else
if (strcmp(cur->insn, "bnez") == 0) {
cur->func_unit = branch;
cur->dependsrc1 = cur->op1;
if (eval_operand(cur->op1) != 0) {
pctemp = eval_operand(cur->op2);
mstats.bnez.taken++;
bpb_update(cur->insn_addr, 1);
btic_update(pctemp);
} else {
mstats.bnez.nottaken++;
bpb_update(cur->insn_addr, 0);
btic_update(pc);
}
} else
if (strcmp(cur->insn, "seq") == 0) {
cur->func_unit = compare;
if (eval_operand(cur->op2) == eval_operand(cur->op3))
set_operand(cur->op1, 1);
else
set_operand(cur->op1, 0);
} else
if (strcmp(cur->insn, "snei") == 0) {
cur->func_unit = compare;
if (eval_operand(cur->op2) != eval_operand(cur->op3))
set_operand(cur->op1, 1);
else
set_operand(cur->op1, 0);
} else
if (strcmp(cur->insn, "sne") == 0) {
cur->func_unit = compare;
if (eval_operand(cur->op2) != eval_operand(cur->op3))
set_operand(cur->op1, 1);
else
set_operand(cur->op1, 0);
} else
if (strcmp(cur->insn, "seqi") == 0) {
cur->func_unit = compare;
if (eval_operand(cur->op2) == eval_operand(cur->op3))
set_operand(cur->op1, 1);
else
set_operand(cur->op1, 0);
} else
if (strcmp(cur->insn, "sgt") == 0) {
cur->func_unit = compare;
if ((signed)eval_operand(cur->op2) >
(signed)eval_operand(cur->op3))
set_operand(cur->op1, 1);
else
set_operand(cur->op1, 0);
} else
if (strcmp(cur->insn, "sgtui") == 0) {
cur->func_unit = compare;
if ((unsigned)eval_operand(cur->op2) >
(unsigned)eval_operand(cur->op3))
set_operand(cur->op1, 1);
else
set_operand(cur->op1, 0);
} else
if (strcmp(cur->insn, "sgeui") == 0) {
cur->func_unit = compare;
if ((unsigned)eval_operand(cur->op2) >=
(unsigned)eval_operand(cur->op3))
set_operand(cur->op1, 1);
else
set_operand(cur->op1, 0);
} else
if (strcmp(cur->insn, "sgei") == 0) {
cur->func_unit = compare;
if ((signed)eval_operand(cur->op2) >= (signed)eval_operand(cur->op3))
set_operand(cur->op1, 1);
else
set_operand(cur->op1, 0);
} else
if (strcmp(cur->insn, "sgti") == 0) {
cur->func_unit = compare;
if ((signed)eval_operand(cur->op2) >
(signed)eval_operand(cur->op3))
set_operand(cur->op1, 1);
else
set_operand(cur->op1, 0);
} else
if (strcmp(cur->insn, "slt") == 0) {
cur->func_unit = compare;
if ((signed)eval_operand(cur->op2) <
(signed)eval_operand(cur->op3))
set_operand(cur->op1, 1);
else
set_operand(cur->op1, 0);
} else
if (strcmp(cur->insn, "slti") == 0) {
cur->func_unit = compare;
if ((signed)eval_operand(cur->op2) <
(signed)eval_operand(cur->op3))
set_operand(cur->op1, 1);
else
set_operand(cur->op1, 0);
} else
if (strcmp(cur->insn, "sle") == 0) {
cur->func_unit = compare;
if ((signed)eval_operand(cur->op2) <=
(signed)eval_operand(cur->op3))
set_operand(cur->op1, 1);
else
set_operand(cur->op1, 0);
} else
if (strcmp(cur->insn, "slei") == 0) {
cur->func_unit = compare;
if ((signed)eval_operand(cur->op2) <=
(signed)eval_operand(cur->op3))
set_operand(cur->op1, 1);
else
set_operand(cur->op1, 0);
} else
if (strcmp(cur->insn, "sleui") == 0) {
cur->func_unit = compare;
if ((unsigned)eval_operand(cur->op2) <=
(unsigned)eval_operand(cur->op3))
set_operand(cur->op1, 1);
else
set_operand(cur->op1, 0);
} else
if (strcmp(cur->insn, "sleu") == 0) {
cur->func_unit = compare;
if ((unsigned)eval_operand(cur->op2) <=
(unsigned)eval_operand(cur->op3))
set_operand(cur->op1, 1);
else
set_operand(cur->op1, 0);
} else
if (strcmp(cur->insn, "simrdtsc") == 0) {
set_operand(cur->op1, supercycles);
} else
if (strcmp(cur->insn, "simprintf") == 0) {
unsigned long stackaddr;
stackaddr = eval_reg(FRAME_REG);
simprintf(stackaddr, 0);
/* printf("simprintf %x %x %x\n", stackaddr, fmtaddr, args); */
} else {
printf("\nEXCEPTION: illegal opcode %s ", cur->insn);
printf("at %.8lx\n", cur->insn_addr);
cont_run = 0;
}
 
/* Dynamic, dependency stats. */
adddstats(icomplet[0].insn, iqueue[0].insn, 1, check_depend());
 
/* Dynamic, functional units stats. */
addfstats(icomplet[0].func_unit, iqueue[0].func_unit, 1, check_depend());
 
/* Dynamic, single stats. */
addsstats(iqueue[0].insn, 1, 0);
 
/* Pseudo multiple issue benchmark */
if ((multissue[cur->func_unit] == 0) || (check_depend())) {
int i;
for (i = 0; i < 20; i++)
multissue[i] = 1;
supercycles++;
multissue[arith] = 2;
multissue[store] = 2;
multissue[load] = 2;
}
multissue[cur->func_unit]--;
return;
}
 
void execute()
{
int i;
/* Here comes real execution someday... */
/* Instruction waits in completition buffer until retired. */
strcpy(icomplet[0].insn, iqueue[0].insn);
strcpy(icomplet[0].op1, iqueue[0].op1);
strcpy(icomplet[0].op2, iqueue[0].op2);
strcpy(icomplet[0].op3, iqueue[0].op3);
icomplet[0].func_unit = iqueue[0].func_unit;
icomplet[0].insn_addr = iqueue[0].insn_addr;
 
if (iqueue[0].dependdst == iqueue[0].op1)
icomplet[0].dependdst = icomplet[0].op1;
else
if (iqueue[0].dependdst == iqueue[0].op2)
icomplet[0].dependdst = icomplet[0].op2;
else
if (iqueue[0].dependdst == iqueue[0].op3)
icomplet[0].dependdst = icomplet[0].op3;
else
icomplet[0].dependdst = NULL;
 
if (iqueue[0].dependsrc1 == iqueue[0].op1)
icomplet[0].dependsrc1 = icomplet[0].op1;
else
if (iqueue[0].dependsrc1 == iqueue[0].op2)
icomplet[0].dependsrc1 = icomplet[0].op2;
else
if (iqueue[0].dependsrc1 == iqueue[0].op3)
icomplet[0].dependsrc1 = icomplet[0].op3;
else
icomplet[0].dependsrc1 = NULL;
 
if (iqueue[0].dependsrc2 == iqueue[0].op1)
icomplet[0].dependsrc2 = icomplet[0].op1;
else
if (iqueue[0].dependsrc2 == iqueue[0].op2)
icomplet[0].dependsrc2 = icomplet[0].op2;
else
if (iqueue[0].dependsrc2 == iqueue[0].op3)
icomplet[0].dependsrc2 = icomplet[0].op3;
else
icomplet[0].dependsrc2 = NULL;
/* History of execution */
for (i = HISTEXEC_LEN - 1; i; i--)
histexec[i] = histexec[i - 1];
histexec[0] = icomplet[0].insn_addr; /* add last insn */
return;
}
 
void dumpreg()
{
int i;
printf("\n\nIQ[0]:");
dumpmemory(iqueue[0].insn_addr, iqueue[0].insn_addr + 4);
printf(" (just executed)\tCYCLE: %u \tSUPERCYCLE: %u\nPC:", cycles, supercycles);
dumpmemory(pc, pc + 4);
printf(" (next insn)");
for(i = 0; i < MAX_GPRS; i++) {
if (i % 4 == 0)
printf("\n");
printf("GPR%.2u: %.8lx ", i, reg[i]);
}
}
/or32/execute.c
0,0 → 1,756
/* execute.c -- OR1K architecture dependent simulation
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
/* Most of the OR1K simulation is done in here. */
 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
 
#include "arch.h"
 
#include "branch_predict.h"
#include "abstract.h"
#include "parse.h"
#include "trace.h"
#include "execute.h"
#include "stats.h"
 
/* General purpose registers. */
machword reg[MAX_GPRS];
 
/* Instruction queue */
struct iqueue_entry iqueue[20];
 
/* Benchmark multi issue execution */
int multissue[20];
int supercycles;
 
/* Completition queue */
struct icomplet_entry icomplet[20];
 
/* Program counter */
unsigned long pc;
 
/* Temporary program counter */
unsigned long pctemp;
 
/* CCR */
int flag;
 
/* CCR (for dependency calculation) */
char ccr_flag[10] = "flag";
 
/* Cycles counts fetch stages */
int cycles;
 
/* Implementation specific.
Get an actual value of a specific register. */
 
machword eval_reg(char *regstr)
{
int regno;
regno = atoi(regstr + 1);
 
if (regno < MAX_GPRS)
return reg[regno];
else {
printf("\nEXCEPTION: read out of registers\n");
cont_run = 0;
return 0;
}
}
 
/* Implementation specific.
Set a specific register with value. */
 
void set_reg32(char *regstr, unsigned long value)
{
int regno;
 
#if 0
if (strcmp(regstr, FRAME_REG) == 0) {
printf("FP (%s) modified by insn at %x. ", FRAME_REG, pc);
printf("Old:%.8lx New:%.8lx\n", eval_reg(regstr), value);
}
 
if (strcmp(regstr, STACK_REG) == 0) {
printf("SP (%s) modified by insn at %x. ", STACK_REG, pc);
printf("Old:%.8lx New:%.8lx\n", eval_reg(regstr), value);
}
#endif
regno = atoi(regstr + 1);
 
if (regno == 0) /* gpr0 is always zero */
value = 0;
if (regno < MAX_GPRS)
reg[regno] = value;
else {
printf("\nEXCEPTION: write out of registers\n");
cont_run = 0;
}
return;
}
 
/* Does srcoperand depend on computation of dstoperand? Return
non-zero if yes.
 
Cycle t Cycle t+1
dst: irrelevant src: immediate always 0
dst: reg1 direct src: reg2 direct 0 if reg1 != reg2
dst: reg1 disp src: reg2 direct always 0
dst: reg1 direct src: reg2 disp 0 if reg1 != reg2
dst: reg1 disp src: reg2 disp always 1 (store must
finish before load)
*/
 
int depend_operands(char *dstoperand, char *srcoperand)
{
char dst[OPERANDNAME_LEN];
char src[OPERANDNAME_LEN];
if (!srcoperand)
return 0;
 
if (!dstoperand)
return 0;
strcpy(dst, dstoperand);
strcpy(src, srcoperand);
 
if (*src == '#') /* immediate */
return 0;
else
if (strstr(src, "lo(") || strstr(src, "hi("))
return 0;
else
if (!strstr(src, "("))
if (*src == 'r') { /* src: reg direct */
if (!strstr(dst, "("))
if (*dst == 'r')
if (strcmp(dst, src) == 0)
return 1; /* dst: reg direct */
else
return 0; /* dst: reg direct */
else
return 0; /* dst: addr */
else
return 0; /* dst: reg disp */
} else
return 0; /* src: addr */
else { /* src: register disp */
char *regstr;
regstr = strstr(src, "(r") + 1; /* regstr == "rXX)" */
*strstr(regstr, ")") = '\0'; /* regstr == "rXX" */
 
if (!strstr(dst, "("))
if (*dst == 'r')
if (strcmp(dst, regstr) == 0)
return 1; /* dst: reg direct */
else
return 0; /* dst: reg direct */
else
return 0; /* dst: addr */
else
return 1; /* dst: reg disp */
}
 
return 0;
}
 
/* Implementation specific.
Get an actual value represented by operand (register direct, register
indirect (with displacement), immediate etc.).
#n - immediate n
rXX - register direct
XX - relative or absolute address (labels)
n(XX) - register indirect (with displacement) */
machword eval_operand(char *srcoperand)
{
char operand[OPERANDNAME_LEN];
strcpy(operand, srcoperand);
 
if (*operand == '#') /* immediate */
return strtoul(&operand[1], NULL, 0);
else
if (((*operand == '-') || isdigit(*operand)) && !strstr(operand, "(")) {
/* immediate */
return strtoul(operand, NULL, 0);
} else
if (strncmp(operand, "lo(", 3) == 0) {
*strchr(operand, ')') = '\0';
if ((operand[3] == '-') || isdigit(operand[3]))
return (unsigned long)strtol(&operand[3], NULL, 0) & 0xffff;
else
return eval_operand(&operand[3]) & 0xffff;
} else
if (strncmp(operand, "hi(", 3) == 0) {
*strchr(operand, ')') = '\0';
if ((operand[3] == '-') || isdigit(operand[3]))
return (unsigned long)strtol(&operand[3], NULL, 0) >> 16;
else
return eval_operand(&operand[3]) >> 16;
} else
if (!strstr(operand, "(")) /* not indirect but ...*/
if (*operand == 'r') /* ... register direct */
return eval_reg(operand);
else /* ... rel. or abs. address */
return eval_label(operand);
else { /* register indirect */
int disp; /* with possible displacement */
char *regstr;
unsigned int memaddr;
disp = atoi(operand); /* operand == "nn(rXX)" */
debug("eval_operand: disp=%u");
regstr = strstr(operand, "(r") + 1; /* regstr == "rXX)" */
*strstr(regstr, ")") = '\0'; /* regstr == "rXX" */
debug("eval_operand: regstr=%s", regstr);
memaddr = eval_reg(regstr) + disp;
return eval_mem32(memaddr);
}
return 0;
}
 
/* Implementation specific.
Set destination operand (register direct, register indirect
(with displacement) with value. */
void set_operand(char *dstoperand, unsigned long value)
{
char operand[OPERANDNAME_LEN];
debug("set_operand %s <= %u\n", dstoperand, value);
strcpy(operand, dstoperand);
 
if (*operand == '#') { /* immediate */
printf("INTERNAL ERROR: Can't set immediate operand.\n");
cont_run = 0;
}
else
if (!strstr(operand, "(")) /* not indirect but ...*/
if (*operand == 'r') /* ... register direct */
set_reg32(operand, value);
else { /* ... rel. or abs. address */
/* printf("INTERNAL ERROR: Can't set addr operand.\n");
cont_run = 0; */
set_mem32(eval_label(operand), value);
}
else { /* register indirect */
int disp; /* with possible displacement */
char *regstr;
unsigned int memaddr;
disp = atoi(operand); /* operand == "nn(rXX)" */
regstr = strstr(operand, "(r") + 1; /* regstr == "rXX)" */
*strstr(regstr, ")") = '\0'; /* regstr == "rXX" */
memaddr = eval_reg(regstr) + disp;
set_mem32(memaddr, value);
}
 
return;
}
 
void reset()
{
cycles = 0;
supercycles = 0;
memset(reg, 0, sizeof(reg));
memset(iqueue, 0, sizeof(iqueue));
memset(icomplet, 0, sizeof(icomplet));
pctemp = eval_label("_main");
pc = pctemp;
debug("reset ...");
set_reg32(STACK_REG, MEMORY_LEN - STACK_SIZE);
}
 
void fetch()
{
/* Cycles after reset. */
cycles++;
 
/* Fetch instruction. */
strcpy(iqueue[0].insn, mem[pc].insn);
strcpy(iqueue[0].op1, mem[pc].op1);
strcpy(iqueue[0].op2, mem[pc].op2);
strcpy(iqueue[0].op3, mem[pc].op3);
strcpy(iqueue[0].op4, mem[pc].op4);
iqueue[0].insn_addr = pc;
iqueue[0].dependdst = NULL;
iqueue[0].dependsrc1 = NULL;
iqueue[0].dependsrc2 = NULL;
 
/* Increment program counter. */
pc = pctemp;
pctemp += 4;
/* Check for breakpoint. */
if (mem[pc].brk)
cont_run = 0; /* Breakpoint set. */
return;
}
 
void decode(struct iqueue_entry *cur)
{
 
cur->dependdst = cur->op1;
cur->dependsrc1 = cur->op2; /* for calculating register */
cur->dependsrc2 = cur->op3; /* dependency */
cur->func_unit = unknown;
if (strcmp(cur->insn, "l.stor32") == 0) {
cur->func_unit = store;
set_operand(cur->op1, eval_operand(cur->op2));
} else
if (strcmp(cur->insn, "h.stor32") == 0) {
cur->func_unit = store;
set_operand(cur->op1, eval_operand(cur->op2));
} else
if (strcmp(cur->insn, "l.stor8") == 0) {
cur->func_unit = store;
set_operand(cur->op1, (eval_operand(cur->op2) << 24) + (eval_operand(cur->op1) & 0xffffff));
} else
if (strcmp(cur->insn, "l.stor16") == 0) {
cur->func_unit = store;
set_operand(cur->op1, (eval_operand(cur->op2) << 16) + (eval_operand(cur->op1) & 0xffff));
} else
if (strcmp(cur->insn, "l.load32u") == 0) {
cur->func_unit = load;
set_operand(cur->op1, eval_operand(cur->op2));
} else
if (strcmp(cur->insn, "h.load32u") == 0) {
cur->func_unit = load;
set_operand(cur->op1, eval_operand(cur->op2));
} else
if (strcmp(cur->insn, "l.load8s") == 0) {
signed char temp = (eval_operand(cur->op2) >> 24);
cur->func_unit = load;
set_operand(cur->op1, temp);
} else
if (strcmp(cur->insn, "l.load8u") == 0) {
unsigned char temp = (eval_operand(cur->op2) >> 24);
cur->func_unit = load;
set_operand(cur->op1, temp);
} else
if (strcmp(cur->insn, "l.load16s") == 0) {
signed short temp = (eval_operand(cur->op2) >> 16);
cur->func_unit = load;
set_operand(cur->op1, temp);
} else
if (strcmp(cur->insn, "l.load16u") == 0) {
unsigned short temp = (eval_operand(cur->op2) >> 16);
cur->func_unit = load;
set_operand(cur->op1, temp);
} else
if (strcmp(cur->insn, "l.immlo16u") == 0) {
cur->func_unit = movimm;
set_operand(cur->op1, (eval_operand(cur->op1) & 0xffff0000) | eval_operand(cur->op2));
} else
if (strcmp(cur->insn, "l.immhi16u") == 0) {
cur->func_unit = movimm;
set_operand(cur->op1, (eval_operand(cur->op1) & 0xffff) | (eval_operand(cur->op2) << 16));
} else
if (strcmp(cur->insn, "h.immch32s") == 0) {
cur->func_unit = movimm;
set_operand(cur->op1, (signed)eval_operand(cur->op2));
} else
if (strcmp(cur->insn, "h.mov32") == 0) {
cur->func_unit = move;
set_operand(cur->op1, eval_operand(cur->op2));
} else
if (strcmp(cur->insn, "l.and32") == 0) {
cur->func_unit = arith;
set_operand(cur->op1, eval_operand(cur->op2) & eval_operand(cur->op3));
} else
if (strcmp(cur->insn, "l.or32") == 0) {
cur->func_unit = arith;
set_operand(cur->op1, eval_operand(cur->op2) | eval_operand(cur->op3));
} else
if (strcmp(cur->insn, "l.xor32") == 0) {
cur->func_unit = arith;
set_operand(cur->op1, eval_operand(cur->op2) ^ eval_operand(cur->op3));
} else
if (strcmp(cur->insn, "l.xori16") == 0) {
cur->func_unit = arith;
set_operand(cur->op1, eval_operand(cur->op2) ^ (eval_operand(cur->op3) & 0xffff));
} else
if (strcmp(cur->insn, "h.ext16s") == 0) {
cur->func_unit = extend;
if ((eval_operand(cur->op1) & 0x8000) == 0x8000)
set_operand(cur->op1, eval_operand(cur->op1) | 0xffff0000);
else
set_operand(cur->op1, eval_operand(cur->op1) & 0x0000ffff);
} else
if (strcmp(cur->insn, "h.ext8s") == 0) {
cur->func_unit = extend;
if ((eval_operand(cur->op1) & 0x80) == 0x80)
set_operand(cur->op1, eval_operand(cur->op1) | 0xffffff00);
else
set_operand(cur->op1, eval_operand(cur->op1) & 0x000000ff);
} else
if (strcmp(cur->insn, "h.ext16z") == 0) {
cur->func_unit = extend;
set_operand(cur->op1, eval_operand(cur->op1) & 0x0000ffff);
} else
if (strcmp(cur->insn, "h.ext8z") == 0) {
cur->func_unit = extend;
set_operand(cur->op1, eval_operand(cur->op1) & 0x000000ff);
} else
if (strcmp(cur->insn, "h.add32s") == 0) {
signed long temp3, temp2, temp1;
signed char temp4;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3);
temp2 = eval_operand(cur->op2);
temp1 = temp2 + temp3;
set_operand(cur->op1, temp1);
temp4 = temp1;
if (temp4 == temp1)
mstats.byteadd++;
} else
if (strcmp(cur->insn, "l.addi32s") == 0) {
signed long temp3, temp2, temp1;
signed char temp4;
cur->func_unit = arith;
temp3 = eval_operand(cur->op3);
temp2 = eval_operand(cur->op2);
temp1 = temp2 + temp3;
set_operand(cur->op1, temp1);
temp4 = temp1;
if (temp4 == temp1)
mstats.byteadd++;
} else
if (strcmp(cur->insn, "l.sub32s") == 0) {
signed long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3);
temp2 = eval_operand(cur->op2);
temp1 = temp2 - temp3;
set_operand(cur->op1, temp1);
} else
if (strcmp(cur->insn, "l.subi32s") == 0) {
signed long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3);
temp2 = eval_operand(cur->op2);
temp1 = temp2 - temp3;
set_operand(cur->op1, temp1);
} else
if (strcmp(cur->insn, "l.mul32s") == 0) {
signed long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3);
temp2 = eval_operand(cur->op2);
temp1 = temp2 * temp3;
set_operand(cur->op1, temp1);
} else
if (strcmp(cur->insn, "l.div32s") == 0) {
signed long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3);
temp2 = eval_operand(cur->op2);
temp1 = temp2 / temp3;
set_operand(cur->op1, temp1);
} else
if (strcmp(cur->insn, "l.div32u") == 0) {
unsigned long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3);
temp2 = eval_operand(cur->op2);
temp1 = temp2 / temp3;
set_operand(cur->op1, temp1);
} else
if (strcmp(cur->insn, "l.shla32") == 0) {
int sign = 1;
cur->func_unit = shift;
debug("shla: op3:%d op4:%d", eval_operand(cur->op3), eval_operand(cur->op4));
debug("shla: op4=%s", cur->op4);
if ((signed)eval_operand(cur->op2) < 0)
sign = -1;
set_operand(cur->op1, eval_operand(cur->op2) << (eval_operand(cur->op3) | eval_operand(cur->op4)));
set_operand(cur->op1, eval_operand(cur->op1) * sign);
} else
if (strcmp(cur->insn, "l.shra32") == 0) {
int sign = 1;
cur->func_unit = shift;
if ((signed)eval_operand(cur->op2) < 0)
sign = -1;
set_operand(cur->op1, eval_operand(cur->op2) >> (eval_operand(cur->op3) | eval_operand(cur->op4)));
set_operand(cur->op1, eval_operand(cur->op1) * sign);
} else
if (strcmp(cur->insn, "l.shrl32") == 0) {
cur->func_unit = shift;
set_operand(cur->op1, eval_operand(cur->op2) >> eval_operand(cur->op3));
} else
if (strcmp(cur->insn, "l.jmp") == 0) {
cur->func_unit = jump;
pctemp = eval_operand(cur->op1);
} else
if (strcmp(cur->insn, "l.jal") == 0) {
cur->func_unit = jump;
pctemp = eval_operand(cur->op1);
set_reg32(LINK_REG, pc + 4);
} else
if (strcmp(cur->insn, "h.jalr") == 0) {
cur->func_unit = jump;
pctemp = eval_operand(cur->op1);
set_reg32(LINK_REG, pc + 4);
} else
if (strcmp(cur->insn, "jr") == 0) {
cur->func_unit = jump;
cur->dependsrc1 = cur->op1;
pctemp = eval_operand(cur->op1);
} else
if (strcmp(cur->insn, "h.nop") == 0) {
cur->func_unit = nop;
} else
if (strcmp(cur->insn, "l.bfeqz") == 0) {
cur->func_unit = branch;
cur->dependsrc1 = ccr_flag;
if (flag == 0) {
pctemp = eval_operand(cur->op1);
mstats.beqz.taken++;
bpb_update(cur->insn_addr, 1);
btic_update(pctemp);
} else {
mstats.beqz.nottaken++;
bpb_update(cur->insn_addr, 0);
btic_update(pc);
}
} else
if (strcmp(cur->insn, "l.bfnez") == 0) {
cur->func_unit = branch;
cur->dependsrc1 = ccr_flag;
if (flag) {
pctemp = eval_operand(cur->op1);
mstats.bnez.taken++;
bpb_update(cur->insn_addr, 1);
btic_update(pctemp);
} else {
mstats.bnez.nottaken++;
bpb_update(cur->insn_addr, 0);
btic_update(pc);
}
} else
if (strcmp(cur->insn, "h.sfeq32") == 0) {
cur->func_unit = compare;
cur->dependsrc2 = cur->op1;
cur->dependdst = ccr_flag;
flag = eval_operand(cur->op1) == eval_operand(cur->op2);
} else
if (strcmp(cur->insn, "h.sfne32") == 0) {
cur->func_unit = compare;
cur->dependsrc2 = cur->op1;
cur->dependdst = ccr_flag;
flag = eval_operand(cur->op1) != eval_operand(cur->op2);
} else
if (strcmp(cur->insn, "h.sfgt32s") == 0) {
cur->func_unit = compare;
cur->dependsrc2 = cur->op1;
cur->dependdst = ccr_flag;
flag = (signed)eval_operand(cur->op1) >
(signed)eval_operand(cur->op2);
} else
if (strcmp(cur->insn, "h.sfge32s") == 0) {
cur->func_unit = compare;
cur->dependsrc2 = cur->op1;
cur->dependdst = ccr_flag;
flag = (signed)eval_operand(cur->op1) >=
(signed)eval_operand(cur->op2);
} else
if (strcmp(cur->insn, "h.sflt32s") == 0) {
cur->func_unit = compare;
cur->dependsrc2 = cur->op1;
cur->dependdst = ccr_flag;
flag = (signed)eval_operand(cur->op1) <
(signed)eval_operand(cur->op2);
} else
if (strcmp(cur->insn, "h.sfle32s") == 0) {
cur->func_unit = compare;
cur->dependsrc2 = cur->op1;
cur->dependdst = ccr_flag;
flag = (signed)eval_operand(cur->op1) <=
(signed)eval_operand(cur->op2);
} else
if (strcmp(cur->insn, "h.sfgt32u") == 0) {
cur->func_unit = compare;
cur->dependsrc2 = cur->op1;
cur->dependdst = ccr_flag;
flag = (unsigned)eval_operand(cur->op1) >
(unsigned)eval_operand(cur->op2);
} else
if (strcmp(cur->insn, "h.sfge32u") == 0) {
cur->func_unit = compare;
cur->dependsrc2 = cur->op1;
cur->dependdst = ccr_flag;
flag = (unsigned)eval_operand(cur->op1) >=
(unsigned) eval_operand(cur->op2);
} else
if (strcmp(cur->insn, "h.sflt32u") == 0) {
cur->func_unit = compare;
cur->dependsrc2 = cur->op1;
cur->dependdst = ccr_flag;
flag = (unsigned)eval_operand(cur->op1) <
(unsigned)eval_operand(cur->op2);
} else
if (strcmp(cur->insn, "h.sfle32u") == 0) {
cur->func_unit = compare;
cur->dependsrc2 = cur->op1;
cur->dependdst = ccr_flag;
flag = (unsigned)eval_operand(cur->op1) <=
(unsigned)eval_operand(cur->op2);
} else
if (strcmp(cur->insn, "simrdtsc") == 0) {
set_operand(cur->op1, supercycles);
} else
if (strcmp(cur->insn, "simprintf") == 0) {
unsigned long stackaddr, fmtaddr, args;
stackaddr = eval_reg(FRAME_REG);
simprintf(stackaddr, eval_reg("r3"));
debug("simprintf %x %x %x\n", stackaddr, fmtaddr, args);
} else {
printf("\nEXCEPTION: illegal opcode %s ", cur->insn);
printf("at %.8lx\n", cur->insn_addr);
cont_run = 0;
}
 
/* Dynamic, dependency stats. */
adddstats(icomplet[0].insn, iqueue[0].insn, 1, check_depend());
 
/* Dynamic, functional units stats. */
addfstats(icomplet[0].func_unit, iqueue[0].func_unit, 1, check_depend());
 
/* Dynamic, single stats. */
addsstats(iqueue[0].insn, 1, 0);
 
/* Pseudo multiple issue benchmark */
if ((multissue[cur->func_unit] == 0) || (check_depend())) {
int i;
for (i = 0; i < 20; i++)
multissue[i] = 1;
supercycles++;
/* if (check_depend())
supercycles++; */
multissue[move] = 2;
multissue[movimm] = 2;
multissue[arith] = 3;
multissue[store] = 4;
multissue[load] = 2;
}
multissue[cur->func_unit]--;
return;
}
 
void execute()
{
int i;
/* Here comes real execution someday... */
/* Instruction waits in completition buffer until retired. */
strcpy(icomplet[0].insn, iqueue[0].insn);
strcpy(icomplet[0].op1, iqueue[0].op1);
strcpy(icomplet[0].op2, iqueue[0].op2);
strcpy(icomplet[0].op3, iqueue[0].op3);
strcpy(icomplet[0].op4, iqueue[0].op4);
icomplet[0].func_unit = iqueue[0].func_unit;
icomplet[0].insn_addr = iqueue[0].insn_addr;
 
if (iqueue[0].dependdst == iqueue[0].op1)
icomplet[0].dependdst = icomplet[0].op1;
else
if (iqueue[0].dependdst == iqueue[0].op2)
icomplet[0].dependdst = icomplet[0].op2;
else
if (iqueue[0].dependdst == iqueue[0].op3)
icomplet[0].dependdst = icomplet[0].op3;
else
icomplet[0].dependdst = NULL;
 
if (iqueue[0].dependsrc1 == iqueue[0].op1)
icomplet[0].dependsrc1 = icomplet[0].op1;
else
if (iqueue[0].dependsrc1 == iqueue[0].op2)
icomplet[0].dependsrc1 = icomplet[0].op2;
else
if (iqueue[0].dependsrc1 == iqueue[0].op3)
icomplet[0].dependsrc1 = icomplet[0].op3;
else
icomplet[0].dependsrc1 = NULL;
 
if (iqueue[0].dependsrc2 == iqueue[0].op1)
icomplet[0].dependsrc2 = icomplet[0].op1;
else
if (iqueue[0].dependsrc2 == iqueue[0].op2)
icomplet[0].dependsrc2 = icomplet[0].op2;
else
if (iqueue[0].dependsrc2 == iqueue[0].op3)
icomplet[0].dependsrc2 = icomplet[0].op3;
else
icomplet[0].dependsrc2 = NULL;
/* History of execution */
for (i = HISTEXEC_LEN - 1; i; i--)
histexec[i] = histexec[i - 1];
histexec[0] = icomplet[0].insn_addr; /* add last insn */
return;
}
 
void dumpreg()
{
int i;
printf("\n\nIQ[0]:");
dumpmemory(iqueue[0].insn_addr, iqueue[0].insn_addr + 4);
printf(" (just executed)\tCYCLE: %u \tSUPERCYCLE: %u\nPC:", cycles, supercycles);
dumpmemory(pc, pc + 4);
printf(" (next insn)");
for(i = 0; i < MAX_GPRS; i++) {
if (i % 4 == 0)
printf("\n");
printf("GPR%.2u: %.8lx ", i, reg[i]);
}
printf("flag: %u\n", flag);
}
/common/stats.c
0,0 → 1,188
/* stats.c -- Various statistics about instruction scheduling etc.
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
#include <stdio.h>
#include <ctype.h>
#include <string.h>
 
#include "abstract.h"
#include "stats.h"
const char func_unit_str[30][30] = { "unknown", "arith", "shift", "compare",
"branch", "jump", "load", "store", "movimm", "move", "extend", "nop" };
 
struct dstats_entry dstats[DSTATS_LEN]; /* dependency stats */
struct sstats_entry sstats[SSTATS_LEN]; /* single stats */
struct fstats_entry fstats[FSTATS_LEN]; /* functional units stats */
struct mstats_entry mstats; /* misc units stats */
 
/* Dependency */
 
int check_depend()
{
debug("check_depend");
if (depend_operands(icomplet[0].dependdst, iqueue[0].dependsrc1) +
depend_operands(icomplet[0].dependdst, iqueue[0].dependsrc2))
return 1;
else
return 0;
}
 
void addsstats(char *item, int cnt_dynamic, int cnt_static)
{
int i = 0;
while(strcmp(sstats[i].insn, item) && (sstats[i].cnt_static > 0) &&
(sstats[i].cnt_static > 0) && (i < SSTATS_LEN))
i++;
 
if (i >= SSTATS_LEN - 1) return;
if (strcmp(sstats[i].insn, item) == 0) {
sstats[i].cnt_dynamic += cnt_dynamic;
sstats[i].cnt_static += cnt_static;
}
else {
strcpy(sstats[i].insn, item);
sstats[i].cnt_dynamic = cnt_dynamic;
sstats[i].cnt_static = cnt_static;
}
}
 
void adddstats(char *item1, char *item2, int cnt_dynamic, int depend)
{
int i = 0;
debug("adddstats start\n");
 
while((strcmp(dstats[i].insn1, item1) || strcmp(dstats[i].insn2, item2)) &&
(strlen(dstats[i].insn1)) &&
(i < DSTATS_LEN))
i++;
 
if (i >= DSTATS_LEN - 1) return;
if ((strcmp(dstats[i].insn1, item1) == 0) &&
(strcmp(dstats[i].insn2, item2) == 0)) {
dstats[i].cnt_dynamic += cnt_dynamic;
dstats[i].depend += depend;
}
else {
strcpy(dstats[i].insn1, item1);
strcpy(dstats[i].insn2, item2);
dstats[i].cnt_dynamic = cnt_dynamic;
dstats[i].depend = depend;
}
}
 
void addfstats(enum insn_type item1, enum insn_type item2, int cnt_dynamic, int depend)
{
int i = 0;
while(((fstats[i].insn1 != item1) || (fstats[i].insn2 != item2)) &&
(fstats[i].insn1 != unknown) &&
(i < FSTATS_LEN))
i++;
 
if (i >= FSTATS_LEN - 1) return;
if ((fstats[i].insn1 == item1) &&
(fstats[i].insn2 == item2)) {
fstats[i].cnt_dynamic += cnt_dynamic;
fstats[i].depend += depend;
}
else {
fstats[i].insn1 = item1;
fstats[i].insn2 = item2;
fstats[i].cnt_dynamic = cnt_dynamic;
fstats[i].depend = depend;
}
}
 
void initstats()
{
memset(sstats, 0, sizeof(sstats));
memset(dstats, 0, sizeof(dstats));
memset(fstats, 0, sizeof(fstats));
memset(&mstats, 0, sizeof(mstats));
}
 
void printstats()
{
int i, all = 0, dependall = 0;
for(i = 0; i < SSTATS_LEN; i++)
all += sstats[i].cnt_static;
 
for(i = 0; i < SSTATS_LEN; i++)
if (sstats[i].cnt_static)
printf(" %s\t\tused %6dx (%2d%%)\n", sstats[i].insn, sstats[i].cnt_static, (sstats[i].cnt_static * 100)/all);
printf("SUM: %d instructions (static, single stats)\n", all);
 
all = 0;
for(i = 0; i < SSTATS_LEN; i++)
all += sstats[i].cnt_dynamic;
 
for(i = 0; i < SSTATS_LEN; i++)
if (sstats[i].cnt_dynamic)
printf(" %s\t\tused %6dx (%2d%%)\n", sstats[i].insn, sstats[i].cnt_dynamic, (sstats[i].cnt_dynamic * 100)/all);
 
printf("SUM: %d instructions (dynamic, single stats)\n", all);
 
all = 0;
dependall = 0;
for(i = 0; i < DSTATS_LEN; i++) {
all += dstats[i].cnt_dynamic;
dependall += dstats[i].depend;
}
 
for(i = 0; i < DSTATS_LEN; i++)
if (dstats[i].cnt_dynamic) {
printf(" %s, %s ", dstats[i].insn1, dstats[i].insn2);
printf("\t\t\t%6dx (%2d%%)", dstats[i].cnt_dynamic, (dstats[i].cnt_dynamic * 100)/all);
printf(" depend: %3d%%\n", (dstats[i].depend * 100) / dstats[i].cnt_dynamic);
}
 
printf("SUM: %d instructions (dynamic, dependency stats) depend: %d%%\n", all, (dependall * 100) / all);
 
all = 0;
dependall = 0;
for(i = 0; i < FSTATS_LEN; i++) {
all += fstats[i].cnt_dynamic;
dependall += fstats[i].depend;
}
 
for(i = 0; i < FSTATS_LEN; i++)
if (fstats[i].cnt_dynamic) {
printf(" %s,", func_unit_str[fstats[i].insn1]);
printf(" %s", func_unit_str[fstats[i].insn2]);
printf("\t\t\t%6dx (%2d%%)", fstats[i].cnt_dynamic, (fstats[i].cnt_dynamic * 100)/all);
printf(" depend: %3d%%\n", (fstats[i].depend * 100) / fstats[i].cnt_dynamic);
}
 
printf("SUM: %d instructions (dynamic, functional units stats) depend: %d%%\n", all, (dependall * 100) / all);
printf("Byte ADD: %d instructions\n", mstats.byteadd);
printf("BEQZ: %d (%d%%) taken,", mstats.beqz.taken, (mstats.beqz.taken * 100) / (mstats.beqz.taken + mstats.beqz.nottaken));
printf(" %d (%d%%) not taken\n", mstats.beqz.nottaken, (mstats.beqz.nottaken * 100) / (mstats.beqz.taken + mstats.beqz.nottaken));
printf("BNEZ: %d (%d%%) taken,", mstats.bnez.taken, (mstats.bnez.taken * 100) / (mstats.bnez.taken + mstats.bnez.nottaken));
printf(" %d (%d%%) not taken\n", mstats.bnez.nottaken, (mstats.bnez.nottaken * 100) / (mstats.bnez.taken + mstats.bnez.nottaken));
printf("BPB: hit %d (correct %d%%), miss %d\n", mstats.bpb.hit, (mstats.bpb.correct * 100) / mstats.bpb.hit, mstats.bpb.miss);
printf("BTIC: hit %d(%d%%), miss %d\n", mstats.btic.hit, (mstats.btic.hit * 100) / (mstats.btic.hit + mstats.btic.miss), mstats.btic.miss);
}
/common/trace.c
0,0 → 1,52
/* trace.c -- Simulator breakpoints
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <stdarg.h>
 
#include "arch.h"
#include "parse.h"
#include "abstract.h"
#include "trace.h"
#include "execute.h"
 
/* Set instruction execution breakpoint. */
 
void set_insnbrkpoint(unsigned long addr)
{
addr &= 0xfffffffc; /* 32-bit aligned */
if (addr < MEMORY_LEN)
if (mem[addr].brk) {
mem[addr].brk = 0;
printf("\nBreakpoint at 0x%.8lx cleared.\n", addr);
} else {
mem[addr].brk = 1;
printf("\nBreakpoint at 0x%.8lx set.\n", addr);
}
else
printf("ERROR: Can't set this breakpoint out of memory.\n");
return;
}
 
/common/parse.h
0,0 → 1,28
/* parse.h -- Header file for parse.c
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
/* Here we define some often used caharcters in assembly files.
This wil probably go into architecture dependent directory. */
 
#define COMMENT_CHAR ';'
#define DIRECTIVE_CHAR '.'
#define LABELEND_CHAR ":"
#define OPERAND_DELIM ","
 
extern int nonempty(char *line);
/common/trace.h
0,0 → 1,26
/* trace.h -- Header file for trace.c
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
/* Continuos run versus single step tracing. */
extern int cont_run;
 
/* History of execution */
#define HISTEXEC_LEN 200
extern int histexec[HISTEXEC_LEN];
 
/common/abstract.c
0,0 → 1,190
/* abstract.c -- Abstract entities
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
/* Abstract memory and routines that goes with this. I need to
add all sorts of other abstract entities. Currently we have
only memory. */
 
#include <stdio.h>
#include <ctype.h>
#include <string.h>
 
#include "parse.h"
#include "abstract.h"
#include "arch.h"
#include "trace.h"
#include "execute.h"
 
extern unsigned long reg[];
 
/* This is an abstract memory array rather than physical memory array */
struct mem_entry mem[MEMORY_LEN];
 
void dumpmemory(unsigned int from, unsigned int to)
{
unsigned int i;
for(i = from; i < to; i++)
if (strlen(mem[i].insn)) {
printf("\n%.4x: ", i);
if (strlen(mem[i].label))
printf("%s%s\n", mem[i].label, LABELEND_CHAR);
printf("\t\t%s\t%s", mem[i].insn, mem[i].op1);
if (strlen(mem[i].op2))
printf("%s%s", OPERAND_DELIM, mem[i].op2);
if (strlen(mem[i].op3))
printf("%s%s", OPERAND_DELIM, mem[i].op3);
if (strlen(mem[i].op4))
printf("%s%s", OPERAND_DELIM, mem[i].op4);
i += 3; /* insn long 4 bytes */
} else
{
if (i % 8 == 0)
printf("\n%.4x: ", i);
/* don't print ascii chars below 0x20. */
if (mem[i].data < 0x20)
printf("0x%.2x ", (unsigned char)mem[i].data);
else
printf("0x%.2x'%c' ", (unsigned char)mem[i].data, mem[i].data);
}
}
 
/* Searches mem array for a particular label and returns label's address.
If label does not exist, returns 0. */
unsigned long eval_label(char *label)
{
int i;
for(i = 0; i < MEMORY_LEN; i++)
if (strcmp(label, mem[i].label) == 0)
return i;
printf("\nINTERNAL ERROR: undefined label %s\n", label);
cont_run = 0;
return 0;
}
 
/* Returns 32-bit values from mem array. Big endian version. */
 
unsigned long eval_mem32(unsigned long memaddr)
{
unsigned long temp;
if (memaddr < MEMORY_LEN) {
/* temp = ((unsigned long)(mem[memaddr].data << 24) & 0xff000000);
temp += ((unsigned long)(mem[memaddr + 1].data << 16) & 0x00ff0000);
temp += ((unsigned long)(mem[memaddr + 2].data << 8) & 0x0000ff00);
temp += ((unsigned long)mem[memaddr + 3].data & 0x000000ff); */
temp = mem[memaddr].data << 24;
temp += mem[memaddr + 1].data << 16;
temp += mem[memaddr + 2].data << 8;
temp += mem[memaddr + 3].data;
} else {
printf("EXCEPTION: read out of memory (32-bit access to %.8lx)\n", memaddr);
cont_run = 0;
temp = ((unsigned long)(mem[0].data << 24) & 0xff000000);
temp += ((unsigned long)(mem[1].data << 16) & 0x00ff0000);
temp += ((unsigned long)(mem[2].data << 8) & 0x0000ff00);
temp += ((unsigned long)mem[3].data & 0x000000ff);
}
return temp;
}
 
/* Returns 16-bit values from mem array. Big endian version. */
 
unsigned short eval_mem16(unsigned long memaddr)
{
unsigned short temp;
if (memaddr < MEMORY_LEN) {
temp = ((unsigned short)(mem[memaddr].data << 8) & 0xff00);
temp += ((unsigned short)mem[memaddr + 1].data & 0x00ff);
} else {
printf("EXCEPTION: read out of memory (16-bit access to %.8lx)\n", memaddr);
cont_run = 0;
temp = ((unsigned short)(mem[0].data << 8) & 0xff00);
temp += ((unsigned short)mem[1].data & 0x00ff);
}
return temp;
}
 
 
/* Returns 8-bit values from mem array. Big endian version. */
 
unsigned char eval_mem8(unsigned long memaddr)
{
if (memaddr < MEMORY_LEN) {
return (unsigned char)mem[memaddr].data;
} else {
printf("EXCEPTION: read out of memory (16-bit access to %.8lx)\n", memaddr);
cont_run = 0;
return (unsigned char)mem[0].data;
}
}
 
/* Set mem, 32-bit. Big endian version. */
 
void set_mem32(unsigned long memaddr, unsigned long value)
{
if (memaddr < MEMORY_LEN) {
mem[memaddr].data = (value >> 24);
mem[memaddr + 1].data = (char)(value >> 16);
mem[memaddr + 2].data = (char)(value >> 8);
mem[memaddr + 3].data = (char)(value);
} else {
printf("EXCEPTION: write out of memory (32-bit access to %.8lx)\n", memaddr);
cont_run = 0;
}
 
return;
}
 
/* Set mem, 16-bit. Big endian version. */
 
void set_mem16(unsigned long memaddr, unsigned short value)
{
if (memaddr < MEMORY_LEN) {
mem[memaddr].data = (value >> 8);
mem[memaddr + 1].data = (char)(value);
} else {
printf("EXCEPTION: write out of memory (16-bit access to %.8lx)\n", memaddr);
cont_run = 0;
}
 
return;
}
 
/* Set mem, 8-bit. Big endian version. */
 
void set_mem8(unsigned long memaddr, unsigned char value)
{
if (memaddr < MEMORY_LEN) {
mem[memaddr].data = value;
} else {
printf("EXCEPTION: write out of memory (8-bit access to %.8lx)\n", memaddr);
cont_run = 0;
}
 
return;
}
/common/stats.h
0,0 → 1,79
/* stats.h -- Header file for stats.c
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
#define DSTATS_LEN 3000
#define SSTATS_LEN 300
#define FSTATS_LEN 200
 
struct dstats_entry {
char insn1[OPERANDNAME_LEN];
char insn2[OPERANDNAME_LEN];
int cnt_dynamic;
int depend;
};
 
struct sstats_entry {
char insn[OPERANDNAME_LEN];
int cnt_static;
int cnt_dynamic;
}; /* single stats */
 
struct fstats_entry {
enum insn_type insn1;
enum insn_type insn2;
int cnt_dynamic;
int depend;
}; /* functional units stats */
 
struct branchstat {
int taken;
int nottaken;
};
 
struct bpbstat {
int hit;
int miss;
int correct;
int incorrect;
};
 
struct bticstat {
int hit;
int miss;
};
 
struct mstats_entry {
int byteadd;
struct branchstat beqz;
struct branchstat bnez;
struct bpbstat bpb;
struct bticstat btic;
}; /* misc units stats */
 
extern struct mstats_entry mstats;
extern struct sstats_entry sstats[SSTATS_LEN];
extern struct dstats_entry dstats[DSTATS_LEN];
extern struct fstats_entry fstats[FSTATS_LEN];
 
extern int check_depend();
extern void addsstats(char *item, int cnt_dynamic, int cnt_static);
extern void adddstats(char *item1, char *item2, int cnt_dynamic, int depend);
extern void addfstats(enum insn_type item1, enum insn_type item2, int cnt_dynamic, int depend);
extern void initstats();
extern void printstats();
/common/execute.h
0,0 → 1,27
/* execute.h -- Header file for architecture dependent execute.c
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
/* This needs a lot of work. */
 
extern machword eval_operand(char *srcoperand);
extern void set_operand(char *dstoperand, unsigned long value);
extern void dumpreg();
extern void set_reg32(char *regstr, unsigned long value);
extern unsigned long pctemp;
/common/abstract.h
0,0 → 1,81
/* abstract.c -- Abstract entities header file
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
#define MEMORY_LEN 100000
#define STACK_SIZE 10000
#define LABELNAME_LEN 30
#define INSNAME_LEN 13
#define OPERANDNAME_LEN 30
 
/* This is an abstract memory type rather than physical memory type */
struct mem_entry {
unsigned char data;
unsigned char brk;
char label[LABELNAME_LEN]; /* label name (optinal) */
char insn[INSNAME_LEN];
char op1[OPERANDNAME_LEN];
char op2[OPERANDNAME_LEN];
char op3[OPERANDNAME_LEN];
char op4[OPERANDNAME_LEN];
};
 
enum insn_type { unknown, arith, shift, compare, branch,
jump, load, store, movimm, move, extend, nop };
 
/* Instruction queue */
struct iqueue_entry {
char insn[INSNAME_LEN];
enum insn_type func_unit;
char op1[OPERANDNAME_LEN];
char op2[OPERANDNAME_LEN];
char op3[OPERANDNAME_LEN];
char op4[OPERANDNAME_LEN];
char *dependdst;
char *dependsrc1;
char *dependsrc2;
unsigned long insn_addr;
};
 
/* Completition queue */
struct icomplet_entry {
char insn[INSNAME_LEN];
enum insn_type func_unit;
char op1[OPERANDNAME_LEN];
char op2[OPERANDNAME_LEN];
char op3[OPERANDNAME_LEN];
char op4[OPERANDNAME_LEN];
char *dependdst;
char *dependsrc1;
char *dependsrc2;
unsigned long insn_addr;
};
 
extern struct iqueue_entry iqueue[20];
extern struct icomplet_entry icomplet[20];
extern unsigned long pc;
 
extern struct mem_entry mem[MEMORY_LEN];
extern void dumpmemory(unsigned int from, unsigned int to);
extern unsigned long eval_label(char *label);
extern unsigned long eval_mem32(unsigned long memaddr);
extern unsigned short eval_mem16(unsigned long memaddr);
extern unsigned char eval_mem8(unsigned long memaddr);
extern void set_mem32(unsigned long memaddr, unsigned long value);
extern void set_mem16(unsigned long memaddr, unsigned short value);
extern void set_mem8(unsigned long memaddr, unsigned char value);
/common/parse.c
0,0 → 1,299
/* parce.c -- Architecture independent load and parsing of assembly
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
 
#include "parse.h"
#include "abstract.h"
 
#define MAXLINE_LEN 18000
 
/* Unused mem memory marker. It is used when allocating program and data memory
during parsing */
unsigned int freemem;
 
int nonempty(char *line)
{
int i;
for(i = 0; i < strlen(line); i++)
if (!isspace(line[i]))
return(1);
return(0);
}
 
int nondigit(char *line)
{
int i;
for(i = 0; i < strlen(line); i++)
if (!isdigit(line[i]))
return(1);
return(0);
}
 
char *strtoken(char *in, char *out, int which)
{
char *super;
char *sub;
char *newline;
super = strdup(in);
sub = strtok(super, " \t");
while (sub && --which)
sub = strtok(NULL, " \t");
if (sub && !which) {
if ((newline = strchr(sub, '\n')))
newline[0] = '\0';
strcpy(out, sub);
} else
out[0] = '\0';
free(super);
if ((newline = strchr(out, '\r'))) /* get rid of CR */
newline[0] = '\0';
return(out);
}
 
void adddatastr(char *str)
{
if (str)
str++;
else
return;
 
for(; *str && *str != '\"'; str++, freemem++)
if (*str == '\\')
switch (*++str) {
case 'n': mem[freemem].data = '\n';
break;
case 't': mem[freemem].data = '\t';
break;
case 'r': mem[freemem].data = '\r';
break;
case '0': mem[freemem].data = '\0';
break;
default: break;
}
else
mem[freemem].data = *str;
}
 
void adddataword(char *num)
{
mem[freemem].data = (char) (atol(num) >> 24);
mem[freemem + 1].data = (char) (atol(num) >> 16);
mem[freemem + 2].data = (char) (atol(num) >> 8);
mem[freemem + 3].data = (char) (atol(num));
freemem += 4;
}
 
void adddatahalf(char *num)
{
mem[freemem].data = (char) (atol(num) >> 8);
mem[freemem + 1].data = (char) (atol(num));
freemem += 2;
}
 
void adddatabyte(char *num)
{
mem[freemem].data = (char) (atol(num));
freemem++;
}
 
void adddataspace(char *num)
{
freemem += atol(num);
}
 
void addlabel(char *label)
{
if (strstr(label, LABELEND_CHAR)) {
*strstr(label, LABELEND_CHAR) = '\0';
strcpy(mem[freemem].label, label);
}
return;
}
 
void addprogram(char *insn, char *operands)
{
strcpy(mem[freemem].insn, insn);
 
/* op1 */
if (*operands)
strcpy(mem[freemem].op1, operands);
if (strstr(mem[freemem].op1, OPERAND_DELIM)) {
operands = strstr(mem[freemem].op1, OPERAND_DELIM);
*operands = '\0';
operands++;
} else {
freemem += 4;
return;
}
 
/* op2 */
if (*operands)
strcpy(mem[freemem].op2, operands);
if (strstr(mem[freemem].op2, OPERAND_DELIM)) {
operands = strstr(mem[freemem].op2, OPERAND_DELIM);
*operands = '\0';
operands++;
} else {
freemem += 4;
return;
}
 
/* op3 */
if (*operands)
strcpy(mem[freemem].op3, operands);
if (strstr(mem[freemem].op3, OPERAND_DELIM)) {
operands = strstr(mem[freemem].op3, OPERAND_DELIM);
*operands = '\0';
operands++;
} else {
freemem += 4;
return;
}
/* op4 */
if (*operands)
strcpy(mem[freemem].op4, operands);
if (strstr(mem[freemem].op4, OPERAND_DELIM)) {
operands = strstr(mem[freemem].op4, OPERAND_DELIM);
*operands = '\0';
operands++;
}
 
freemem += 4;
return;
}
 
/* Non-architecture dependent parsing: stripping comments, filling
abstract memory */
void parseline(char *inputline)
{
char item[MAXLINE_LEN];
char item2[MAXLINE_LEN];
int i = 0;
/* Strip comments: simply terminate line where
the first comment character appears. */
debug("PARSING: %s", inputline);
while (inputline[i] != '\0')
if (inputline[i] == COMMENT_CHAR) {
inputline[i] = '\0';
break;
} else
i++;
/* Get the first item from this line */
strtoken(inputline, item, 1);
strtoken(inputline, item2, 2);
/* Is this item empty? Nothing to process, so return. */
if (strlen(item) == 0)
return;
/* Is this item a label? If yes, add it to the label
table and return immediately. */
if (strstr(item, LABELEND_CHAR)) {
addlabel(item);
return;
}
/* Is this item a .directive? If yes, check for some supported
and then return (even if unsupported found). */
if (item[0] == DIRECTIVE_CHAR) {
if ((strcmp(item, ".align") == 0) && (freemem % 4)) {
freemem &= -4; /* e.g. 0xfffffffc */
freemem += 4; /* always align to word */
return;
} else
if (strcmp(item, ".ascii") == 0) {
adddatastr(strstr(inputline, "\""));
return;
} else
if (strcmp(item, ".word") == 0) {
adddataword(item2);
return;
} else
if (strcmp(item, ".half") == 0) {
adddatahalf(item2);
return;
} else
if (strcmp(item, ".byte") == 0) {
adddatabyte(item2);
return;
} else
if (strcmp(item, ".space") == 0) {
adddataspace(item2);
return;
} else /* .directive but not one of the supported */
return;
}
 
/* This item can only be an instruction. Get all operands
and add everything to mem array but as a program. */
addprogram(item, item2);
/* Also do static, single stats. */
addsstats(item, 0, 1);
return;
}
 
/* Load file and hand over every line to parse routine. */
 
void readfile(char *filename)
{
FILE *inputfs;
char inputbuf[MAXLINE_LEN];
char *status;
if ((inputfs = fopen(filename, "r"))) {
while ((status = fgets(inputbuf, sizeof(inputbuf), inputfs))) {
if (nonempty(inputbuf))
parseline(inputbuf);
}
fclose(inputfs);
}
else
perror("readfile");
 
return;
}
 
 
void loadcode(char *filename)
{
freemem = 0;
memset(mem, 0, sizeof(mem));
readfile(filename);
return;
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.