drisc.cpp/* \file drisc.cpp
*
* RiSC-16 Simulator
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <string>
using namespace std;
#include "strtoken.h"
int mem[512];
int nwords = 0;
int mem_check(int addr);
void read_memory(FILE *in);
void show_memory(FILE *out);
void show_registers(FILE *out);
void simulate(FILE *out);
int main(int argc, char *argv[])
{
FILE *in, *out;
string filename;
errno_t nerr;
if (argc<2) {
cout << "usage: drisc hexfile\n";
return EXIT_FAILURE;
}
filename = argv[1];
nerr = fopen_s(&in,filename.c_str(),"r");
if (nerr) {
cout << "file: " << filename << " not found\n";
return EXIT_FAILURE; }
read_memory(in);
fclose(in);
out = stdout;
fprintf(out,"<html>\n");
simulate(out);
fprintf(out,"<h3>Registers</h3>\n");
show_registers(out);
fprintf(out,"<h3>Memory</h3>\n");
show_memory(out);
fprintf(out,"</html>\n");
return EXIT_SUCCESS;
}
int mem_check(int addr)
{
if (addr<0 || addr>=nwords) {
return 1;
}
return 0;
}
void show_memory(FILE *out)
{
int i,flag=0;
fprintf(out,"<p><table border>\n");
fprintf(out,"<p><tr bgcolor=CCCCFF><th>addr");
for (i=0; i<16; i++) fprintf(out,"<th>%X",i);
fprintf(out,"\n");
for (i=0; i<nwords; i++) {
flag = i%16;
if (flag==0) fprintf(out,"<tr align=center><td bgcolor=FFFFCC>%04X",i);
fprintf(out,"<td>%04X",mem[i]);
if (flag==7) fprintf(out,"\n");
}
while (flag++ < 15) fprintf(out,"<td><br>");
fprintf(out,"</table>\n");
}
void read_memory(FILE *in)
{
char buf[512];
char *inp, *next;
int field;
bool done = false;
nwords = 0;
while (!done) {
fgets(buf,511,in);
if (feof(in)) break;
next = buf;
while (*next==' ') next++;
while (next) {
inp = next;
while (*inp==' ') inp++; // eat blanks
if (*inp=='\n') break;
next = strqtrm(inp,' ');
sscanf_s(inp,"%x",&field);
//if (field>0) printf("%04X\n",field);
mem[nwords++] = field;
}
}
}
int regs[] = {0xBAD0,0x1111,0x2222,0x3333,0x4444,0x5555,0x6666,0x7777};
int reg(int n) {
if (n>0) return regs[n];
return 0;
}
void show_registers(FILE *out)
{
int i;
fprintf(out,"<p><table border>\n");
fprintf(out,"<p><tr bgcolor=CCCCFF><th>format");
for (i=1; i<8; i++) fprintf(out,"<th>r%d",i);
fprintf(out,"\n");
fprintf(out,"<tr align=center><th>hex");
for (i=1; i<8; i++) {
fprintf(out,"<td>%04X",reg(i));
}
fprintf(out,"<tr align=center><th>decimal");
for (i=1; i<8; i++) {
fprintf(out,"<td>%d",(short)reg(i));
}
fprintf(out,"\n</table>\n");
}
string cmd[] = { "NOP", "LWI", "SWI", "LI", "LUI",
"LW", "SW", "ADDI", "ALU1", "ALU2", "BNE", "JALR"};
string cmd_alu1[] = { "ADD", "SUB" };
string cmd_alu2[] = { "AND", "OR", "XOR", "NOR" };
const int NOP = 0, LWI = 1, SWI = 2, LI = 3, LUI = 4,
LW = 5, SW=6, ADDI = 7, ALU1 = 8, ALU2 = 9, BNE = 10, JALR = 11;
string opcode_memnomic(int opcode,int opx)
{
char str[64];
if (opcode==ALU1) return cmd_alu1[opx];
if (opcode==ALU2) return cmd_alu2[opx];
if (opcode<12) return cmd[opcode];
sprintf_s(str,63,"NOP: %0X",opcode);
return str;
}
const int HALT = 0x0000;
void simulate(FILE *out)
{
int pc, nextpc;
int inst, immed, immse, maddr;
int opx, imm5;
int range_error;
int opcode, rd=0, ra=0, rb=0;
int qa, qb, qd=0, ncycle=0;
bool done = false;
fprintf(out,"<h3>Simulation Results</h3>\n");
fprintf(out,"<p><table border>\n");
fprintf(out,"<tr bgcolor=CCCCFF><th>#<th>pc<th>op<th>rd<th>qd<th>immed\n");
nextpc = 0;
while (!done) {
inst = mem[nextpc];
opcode = inst>>11;
rd = (inst>>8)&0x7;
ra = (inst>>5)&0x7;
rb = (inst>>2)&0x7;
immed = inst&0xFF;
if (immed>>7) immse = 0xFFFFFF00| immed;
else immse = immed;
imm5 = inst&0x1F;
if (imm5>>4) imm5 = 0xFFFFFFE0 | imm5;
qa = reg(ra);
qb = reg(rb);
maddr = immed;
range_error = 0;
if (inst==HALT) break;
pc = nextpc;
nextpc++;
opx = immed&0x3;
switch (opcode) {
case LI:
qd = immse;
break;
case LUI:
ra = rd;
qa = reg(ra);
qd = (immed<<8)|(qa&0xFF);
break;
case SWI: // SW
rb = rd;
rd = 0;
qb = reg(rb);
maddr = immed;
qd = maddr;
range_error = mem_check(maddr);
if (!range_error) mem[maddr] = qb;
break;
case SW:
rb = rd;
rd = 0;
qb = reg(rb);
maddr = qa+imm5;
qd = maddr;
range_error = mem_check(maddr);
if (!range_error) mem[maddr] = qb;
break;
case LWI:
maddr = immed;
range_error = mem_check(maddr);
if (!range_error) qd = mem[maddr];
break;
case LW:
maddr = reg(ra)+imm5;
range_error = mem_check(maddr);
if (!range_error) qd = mem[maddr];
break;
case ADDI:
qd = qa + imm5;
break;
case ALU1:
switch (opx) {
case 0:
qd = qa+qb; // add
break;
case 1:
qd = qa-qb; // subtract
break;
}
break;
case ALU2:
switch (opx) {
case 0:
qd = qa & qb;
break;
case 1:
qd = qa | qb;
break;
case 2:
qd = qa ^ qb;
break;
case 3:
qd = !(qa|qb);
break;
}
break;
case BNE:
rb = rd;
rd = 0;
qd = reg(rb)!=qa;
if (qd) nextpc = nextpc + imm5;
break;
case JALR:
qd = nextpc;
nextpc = qa;
break;
default:
rd = 0;
break;
}
qd &= 0xFFFF;
bool we = opcode!=SW && opcode!=SWI;
if (rd && we) regs[rd] = qd;
fprintf(out,"<tr><td bgcolor=FFFFCC>%d<td>%02X",++ncycle,pc);
fprintf(out,"<td>%s<td>%d<td>%04X",
opcode_memnomic(opcode,opx).c_str(),rd,qd);
if (opcode>0) {
fprintf(out,"<td>%04X\n",immed);
if (range_error) printf("address %x out of range\n",maddr);
}
else fprintf(out,"<td><br>\n");
if (ncycle>60) break;
}
fprintf(out,"</table>\n");
}
void parse(FILE *in, FILE *out)
{
char buf[512];
char *inp, *next;
int opcode, ra, rb, rc, field;
int count, code, n;
string token;
bool done = false;
/*
* Go through input file, line by line
*/
n = 0;
while (!done) {
fgets(buf,511,in);
if (feof(in)) break;
//fprintf(out,"%s",buf);
if (*buf=='#') continue;
next = buf;
/*
* parse current line
*/
count = 0;
opcode = ra = rb = rc = 0;
while (next) {
/*
* search for '<', and copy prior text to
* output stream
*/
inp = next;
next = strqtrm(inp,',');
sscanf_s(inp,"%d",&field);
//fprintf(out,"count %d field %d\n",count,field);
switch (count) {
case 0:
token = inp;
//fprintf(out,"%s %d\n",token.c_str(),opcode);
count = 1;
break;
case 1:
ra = field;
count = 2;
break;
case 2:
rb = field;
count = 3;
break;
case 3:
rc = field;
count = 4;
break;
default:
break;
}
}
code = ((opcode&0x7)<<13) | ((ra&0x7)<<10) | ((rb&0x7)<<7) | (rc&0x7F);;
fprintf(out,"%04X\n",code);
n++;
}
while (n++ < 32) fprintf(out,"0000\n");
}
Maintained by John Loomis, updated Wed Apr 06 22:45:07 2011