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

Subversion Repositories leros

[/] [leros/] [trunk/] [java/] [tools/] [src/] [leros/] [sim/] [LerosSim.java] - Rev 4

Compare with Previous | Blame | View Log

/*
   Copyright 2011 Martin Schoeberl <masca@imm.dtu.dk>,
                  Technical University of Denmark, DTU Informatics. 
   All rights reserved.
 
   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
 
      1. Redistributions of source code must retain the above copyright notice,
         this list of conditions and the following disclaimer.
 
      2. Redistributions in binary form must reproduce the above copyright
         notice, this list of conditions and the following disclaimer in the
         documentation and/or other materials provided with the distribution.
 
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
   NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
   The views and conclusions contained in the software and documentation are
   those of the authors and should not be interpreted as representing official
   policies, either expressed or implied, of the copyright holder.
 */
 
package leros.sim;
 
import java.io.*;
 
/**
 * A crude simulation of Leros. Pipeline effects (branch delay slots) are
 * currently ignored.
 * 
 * @author Martin Schoeberl
 * 
 */
public class LerosSim {
 
	String fname;
	// no real use of dstDir
	String dstDir = "./";
	String srcDir = "./";
	boolean log;
 
	ILerosIO io;
 
	final static int IM_SIZE = 1024;
	final static int DM_SIZE = 1024;
	char im[] = new char[IM_SIZE];
	char dm[] = new char[DM_SIZE];
	int progSize = 0;
 
	int executedInstructions;
 
	public LerosSim(LerosIO io, String[] args) {
 
		this.io = io;
 
		String s = System.getProperty("log");
		if (s != null) {
			log = s.equals("true");
		}
		log=false;
		srcDir = System.getProperty("user.dir");
		dstDir = System.getProperty("user.dir");
		processOptions(args);
		if (!srcDir.endsWith(File.separator))
			srcDir += File.separator;
		if (!dstDir.endsWith(File.separator))
			dstDir += File.separator;
 
		BufferedReader instr = null;
		try {
			instr = new BufferedReader(new FileReader(srcDir + fname));
			String l;
			while ((l = instr.readLine()) != null) {
				im[progSize] = (char) Integer.parseInt(l);
				++progSize;
			}
			System.out.println("Instruction memory " + (progSize * 2)
					+ " bytes");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (instr != null) {
				try {
					instr.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
 
		}
	}
 
	private boolean processOptions(String clist[]) {
		boolean success = true;
 
		for (int i = 0; i < clist.length; i++) {
			if (clist[i].equals("-s")) {
				srcDir = clist[++i];
			} else if (clist[i].equals("-d")) {
				dstDir = clist[++i];
			} else if (clist[i].equals("-qio")) {
				QuickIO qio = new QuickIO();
				qio.setVisible(true);
				io = qio;
 
			} else {
				fname = clist[i];
			}
		}
 
		return success;
	}
 
	/**
	 * Run the simulation. First instruction is not executed as in the hardware.
	 */
	public void simulate() {
 
		int ar, pc, accu;
		int accu_dly, accu_dly1;
 
		pc = 1;
		accu = 0;
		ar = 0;
		accu_dly = accu_dly1 = 0;
 
		for (;;) {
 
			// two cycles delay for branch
			// condition modeling
			// We should model the 'real' pipeline in the simulator...
			accu_dly = accu_dly1;
			accu_dly1 = accu;
 
			int next_pc = pc + 1;
			if (pc >= progSize) {
			    System.out.println("Excuted = " + executedInstructions );
				return;
			}
			int instr = im[pc];
			int val;
			// immediate value
			if ((instr & 0x0100) != 0) {
				// take o bit from the instruction
				val = instr & 0xff;
				// sign extension to 16 bit
				if ((val & 0x80)!=0) { val |= 0xff00; }
			} else {
				val = dm[instr & 0xff];
			}
			executedInstructions++;
 
			switch (instr & 0xfe00) {
			case 0x0000: // nop
				break;
			case 0x0800: // add
				accu += val;
				break;
			case 0x0c00: // sub
				accu -= val;
				break;
			case 0x1000: // shr
				accu >>>= 1;
				break;
			case 0x2000: // load
				accu = val;
				break;
			case 0x2200: // and
				accu &= val;
				break;
			case 0x2400: // or
				accu |= val;
				break;
			case 0x2600: // xor
				accu ^= val;
				break;
			case 0x2800: // loadh
				accu = (accu & 0xff) + (val << 8);
				break;
			case 0x3000: // store
				dm[instr & 0x00ff] = (char) accu;
				break;
			case 0x3800: // out
				io.write(instr & 0xff, accu);
				break;
			case 0x3c00: // in
				accu = io.read(instr & 0xff);
				break;
			case 0x4000: // jal
				dm[instr & 0xff] = (char) (pc+1);
				next_pc = accu_dly;
				break;
			case 0x5000: // loadaddr
				// nop, as it is only available one cycle later
				break;
			case 0x6000: // load indirect
				accu = dm[ar + (instr & 0xff)];
				break;
			case 0x7000: // store indirect
				dm[ar + (instr & 0xff)] = (char) accu;
				break;
			// case 7: // I/O (ld/st indirect)
			// break;
			// case 8: // brl
			// break;
			// case 9: // br conditional
			// break;
			default:
				// branches use the immediate bit for decode
				// TODO: we could change the encoding so it
				// does not 'consume' the immediate bit - would
				// this be simpler (and lead to less HW?)
				switch (instr & 0xff00) {
				case 0x4800: // branch
					// at the moment just 8 bits offset (sign extension)
					next_pc = pc + ((instr << 24) >> 24);
					break;
				case 0x4900: // brz
					if (accu_dly == 0) {
						// at the moment just 8 bits offset (sign extension)
						next_pc = pc + ((instr << 24) >> 24);
					}
					break;
				case 0x4a00: // brnz
					if (accu_dly != 0) {
						// at the moment just 8 bits offset (sign extension)
						next_pc = pc + ((instr << 24) >> 24);
					}
					break;
				case 0x4b00: // brp
					if ((accu_dly & 0x8000) == 0) {
						// at the moment just 8 bits offset (sign extension)
						next_pc = pc + ((instr << 24) >> 24);
					}
					break;
				case 0x4c00: // brn
					if ((accu_dly & 0x8000) != 0) {
						// at the moment just 8 bits offset (sign extension)
						next_pc = pc + ((instr << 24) >> 24);
					}
					break;
 
				default:
					throw new Error("Instruction " + instr + " at address " + pc
							+ " not implemented");
				}
			}
 
 
			// keep it in 16 bit
			accu &= 0xffff;
			// the address register is only available for one
			// cycle later
			ar = dm[instr & 0xff];
 
			if (log) {
				System.out.print("PC: " + pc + " accu: " + accu + " "
						+ accu_dly + " ar: " + ar + " Mem: ");
				for (int i = 0; i < 16; ++i) {
					System.out.print(((int) dm[i]) + " ");
				}
				System.out.println();
			}
			pc = next_pc;
 
		}
 
 
	}
 
	/**
	 * @param args
	 */
	public static void main(String[] args) {
 
		if (args.length < 1) {
			System.out.println("usage: java LerosSim [-s srcDir] [-qio] filename");
			System.exit(-1);
		}
		LerosSim ls = new LerosSim(new LerosIO(), args);
		ls.simulate();
	}
 
}

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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