// Parallel Computing // // Simulation applet // // Author Matthew Caryl // Created 2.2.97 package Parallel; import java.awt.Graphics; import java.awt.Color; import java.awt.Event; import java.applet.Applet; import java.lang.System; import java.io.*; import java.awt.*; import java.net.*; import ADT.Random; public final class Simulator extends Applet implements Runnable, Viewer { // // Private interface of simulator // private static final long CLOCK_SPEED = 1000000; private static final int TIME_STEP = 1000; public static final Color backgroundColor = Color.black; public static final Color outlineColor = Color.white; // display objects private Scrollbar horizontal_scroll; private Scrollbar verticle_scroll; private Panel base_panel; private Controls controls; // scrollable area private int window_width; private int window_height; private int window_x; private int window_y; private int scrollable_size; private int scroll_x; private int scroll_y; private Thread animation; private Graphics graphics; private Computer computer; private boolean enable; private int granularity = 1; private float desired_hertz = 1f; private boolean dragging; private int dragging_x, dragging_y; // adjust to this size of virtual synchronized private void setScrollable(int size) { horizontal_scroll.setValues(-scroll_x * computer.pixelWidth(size) / computer.pixelWidth(scrollable_size), window_width, 0, computer.pixelWidth(size) - window_width); verticle_scroll.setValues(-scroll_y * computer.pixelHeight(size) / computer.pixelHeight(scrollable_size), window_height, 0, computer.pixelHeight(size) - window_height); scrollable_size = size; scroll_x = -horizontal_scroll.getValue(); scroll_y = -verticle_scroll.getValue(); graphics.translate(-window_x, -window_y); window_x = Math.max(0, (window_width - computer.pixelWidth(scrollable_size)) / 2); window_y = Math.max(0, (window_height - computer.pixelHeight(scrollable_size)) / 2); graphics.translate(window_x, window_y); } // capture current window size synchronized private void setWindow() { int width = size().width; int height = size().height; window_width = width - verticle_scroll.size().width; window_height = height - base_panel.size().height; horizontal_scroll.setPageIncrement(width / 2); verticle_scroll.setPageIncrement(height / 2); setScrollable(scrollable_size); } // add power at corners of simulation private void supplyPower() { Processor processor; Power power; // top left corner processor = computer.processor(0, 0); processor.getPower(0).charge(); processor.getPower(3).charge(); // top right corner processor = computer.processor(computer.width() - 1, 0); processor.getPower(0).charge(); processor.getPower(1).charge(); // bottom left corner processor = computer.processor(0, computer.height() - 1); processor.getPower(2).charge(); processor.getPower(3).charge(); // bottom right corner processor = computer.processor(computer.width() - 1, computer.height() - 1); processor.getPower(1).charge(); processor.getPower(2).charge(); } // read integer from parameter list private int readIntParameter(String name, int minimumValue, int defaultValue) { try { int value = Integer.parseInt(this.getParameter(name)); if (value < minimumValue) throw new NumberFormatException("Simulation width must be greater than " + minimumValue); else return value; } catch (NumberFormatException e) { return defaultValue; } } // // Public simulator interface // public void init() { int width = readIntParameter("simulatorWidth", 1, 32); int height = readIntParameter("simulatorHeight", 1, 8); try { InputStream is = new URL(getCodeBase(), "rom.asm").openStream(); Assembler a = new Assembler(is); is.close(); if (a.check()) Processor.initialiseRom(a); else System.err.println(a.error()); } catch (IOException e) { System.err.println("Unable to create processor rom"); } Computer.registerComputer(this, getParameter("computerName"), width, height); setBackground(backgroundColor); horizontal_scroll = new Scrollbar(Scrollbar.HORIZONTAL); verticle_scroll = new Scrollbar(Scrollbar.VERTICAL); controls = new Controls(this, CLOCK_SPEED, TIME_STEP); base_panel = new Panel(); base_panel.setBackground(outlineColor); base_panel.setLayout(new BorderLayout(0, 0)); base_panel.add("North", horizontal_scroll); base_panel.add("South", controls); this.setLayout(new BorderLayout(0, 0)); this.add("East", verticle_scroll); this.add("South", base_panel); graphics = this.getGraphics(); } public void setComputer(Computer C) { System.out.println("set simulator"); computer = C; window_x = window_y = 0; for (scrollable_size = Math.max(computer.width(), computer.height()); scrollable_size < Math.min(size().width, size().height); scrollable_size *= 2) ; // do nothing scrollable_size /= 2; scroll_x = scroll_y = 0; start(); } public void destroy() { if (animation != null && animation.isAlive()) animation.stop(); if (graphics != null) graphics.dispose(); } public void start() { if (computer == null) return; if (animation == null) { animation = new Thread(this); animation.start(); } else animation.resume(); } public void stop() { if (animation != null && animation.isAlive()) animation.suspend(); } public void run() { setWindow(); enable = true; while (true) { controls.startTimer(); long end = System.currentTimeMillis() + TIME_STEP; long start = System.currentTimeMillis(); int count = 0; while (System.currentTimeMillis() < end) { synchronized (computer) { supplyPower(); computer.tick(granularity); computer.update(graphics, window_width, window_height, scroll_x, scroll_y, scrollable_size); } count += granularity; try { int s = (int) ((int) (1000f * (float) count / desired_hertz) - System.currentTimeMillis() + start); Thread.sleep(Math.max(0, s)); } catch (InterruptedException e) { // do nothing } } controls.stopTimer(count); } } public void paint(Graphics g) { if (!enable) return; synchronized (computer) { g.setColor(backgroundColor); g.fillRect(-window_x, -window_y, window_width, window_height); computer.draw(graphics, window_width, window_height, scroll_x, scroll_y, scrollable_size); } } public boolean handleEvent(Event e) { if (e.target == horizontal_scroll) { switch (e.id) { case Event.SCROLL_LINE_UP: case Event.SCROLL_LINE_DOWN: case Event.SCROLL_PAGE_UP: case Event.SCROLL_PAGE_DOWN: case Event.SCROLL_ABSOLUTE: int sx = -((Integer) e.arg).intValue(); if (sx != scroll_x) { scroll_x = sx; paint(graphics); } return true; } return false; } else if (e.target == verticle_scroll) { switch (e.id) { case Event.SCROLL_LINE_UP: case Event.SCROLL_LINE_DOWN: case Event.SCROLL_PAGE_UP: case Event.SCROLL_PAGE_DOWN: case Event.SCROLL_ABSOLUTE: int sy = -((Integer) e.arg).intValue(); if (sy != scroll_y) { scroll_y = sy; paint(graphics); } return true; } return false; } else if (e.target == this) { switch (e.id) { case Event.MOUSE_DOWN: if (!computer.mouseDown(window_width, window_height, scroll_x, scroll_y, scrollable_size, e.x - window_x, e.y - window_y)) { dragging = true; dragging_x = e.x; dragging_y = e.y; synchronized (computer) { stop(); } } return true; case Event.MOUSE_UP: case Event.MOUSE_EXIT: dragging = false; start(); return true; case Event.MOUSE_DRAG: int sx = scroll_x; int sy = scroll_y; horizontal_scroll.setValues(-scroll_x - e.x + dragging_x, horizontal_scroll.getVisible(), 0, horizontal_scroll.getMaximum()); verticle_scroll.setValues(-scroll_y - e.y + dragging_y, verticle_scroll.getVisible(), 0, verticle_scroll.getMaximum()); scroll_x = -horizontal_scroll.getValue(); scroll_y = -verticle_scroll.getValue(); dragging_x = e.x; dragging_y = e.y; if (sx != scroll_x || sy != scroll_y) paint(graphics); return true; default: break; } } return super.handleEvent(e); } public synchronized void reshape(int x, int y, int width, int height) { super.reshape(x, y, width, height); if (horizontal_scroll == null) return; setWindow(); } public void rescale(int scale) { if (scale > 0) { if ((scrollable_size << 1) <= computer.maxSize()) { setScrollable(scrollable_size << 1); paint(graphics); } } else if (scale < 0) { if ((scrollable_size >> 1) >= computer.minSize()) { setScrollable(scrollable_size >> 1); paint(graphics); } } } public String[][] getParameterInfo() { String[][] info = { {"simulationWidth ", "positive integer ", "width of simulator in processors"}, {"simulationHeight ", "positive integer ", "height of simulator in processors"}}; return info; } public Computer computer() { return computer; } public int granularity() { return granularity; } public void granularity(int G) { synchronized (computer) { if (G > 0) granularity = G; } } public float desiredHertz() { return desired_hertz; } public void desiredHertz(float H) { synchronized (computer) { if (H > 0f) desired_hertz = H; } } }