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", "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

#pcoprdqdimmed
100NOP00000
201NOP00000
302NOP00000
403NOP00000
504LW100110010
605SW200000014
706LI3007B007B
807LW422220014
908LI5FFCE00CE
1009LUI610660010

Registers

formatr1r2r3r4r5r6r7
hex00112222007B2222FFCE10667777
decimal1787381238738-50419830583

Memory

addr0123456789ABCDEF
000000AA00BB00CC00DD091012141B7B0C14 1DCE2610000000000000000000000000
001000110022003300442222006600770088 00F100F200F300F400F500F600F700D8


Maintained by John Loomis, updated Tue Mar 01 10:07:06 2011