/* \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", "LW", "SW", "LI", "LUI"};
const int NOP = 0, LW = 1, SW = 2, LI = 3, LUI = 4;
string opcode_memnomic(int opcode)
{
char str[64];
if (opcode<5) 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 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 = 0xFF00| immed&0xFF;
else immse = immed;
qa = reg(ra);
qb = reg(rb);
maddr = immed;
range_error = 0;
if (inst==HALT) break;
pc = nextpc;
nextpc++;
switch (opcode) {
case LI:
qd = immse;
break;
case LUI:
ra = rd;
qa = reg(ra);
qd = (immed<<8)|(qa&0xFF);
break;
case SW: // SW
ra = rd;
qa = reg(ra);
qd = 0;
range_error = mem_check(maddr);
if (!range_error) mem[maddr] = qa;
break;
case LW:
range_error = mem_check(maddr);
if (!range_error) qd = mem[maddr];
break;
default:
rd = 0;
break;
}
qd &= 0xFFFF;
if (rd && opcode!=SW) 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).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");
}
Sample Code
LW,1,16
SW,2,20
LI,3,123
LW,4,20
LI,5,-50
LUI,6,16
HALT,,
Simulation Results
# | pc | op | rd | qd | immed
|
---|
1 | 00 | NOP | 0 | 0000 |
|
2 | 01 | NOP | 0 | 0000 |
|
3 | 02 | NOP | 0 | 0000 |
|
4 | 03 | NOP | 0 | 0000 |
|
5 | 04 | LW | 1 | 0011 | 0010
|
6 | 05 | SW | 2 | 0000 | 0014
|
7 | 06 | LI | 3 | 007B | 007B
|
8 | 07 | LW | 4 | 2222 | 0014
|
9 | 08 | LI | 5 | FFCE | 00CE
|
10 | 09 | LUI | 6 | 1066 | 0010
|
Registers
format | r1 | r2 | r3 | r4 | r5 | r6 | r7
|
---|
hex | 0011 | 2222 | 007B | 2222 | FFCE | 1066 | 7777 |
---|
decimal | 17 | 8738 | 123 | 8738 | -50 | 4198 | 30583
|
---|
Memory
addr | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
|
---|
0000 | 00AA | 00BB | 00CC | 00DD | 0910 | 1214 | 1B7B | 0C14
| 1DCE | 2610 | 0000 | 0000 | 0000 | 0000 | 0000 | 0000 |
0010 | 0011 | 0022 | 0033 | 0044 | 2222 | 0066 | 0077 | 0088
| 00F1 | 00F2 | 00F3 | 00F4 | 00F5 | 00F6 | 00F7 | 00D8 |
Maintained by John Loomis,
updated Tue Mar 01 10:07:06 2011