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");
}


Results




Maintained by John Loomis, updated Wed Apr 06 22:45:07 2011