final pass to update instruction encoding; should now match the spec
[fleet.git] / src / edu / berkeley / fleet / interpreter / Outbox.java
1 package edu.berkeley.fleet.interpreter;
2 import edu.berkeley.sbp.util.ANSI;
3 import edu.berkeley.fleet.api.*;
4 import edu.berkeley.fleet.ies44.*;
5 import edu.berkeley.fleet.util.*;
6 import edu.berkeley.fleet.api.Instruction;
7
8 public class Outbox extends InstructionPump {
9
10     /** are we ready to accept another item from the ship? */
11     private boolean readyForDataFromShip = false;
12     private boolean haveDataFromShip     = false;
13
14     /** data which has been presented by the ship and is waiting to depart */
15     private long    itemPresentedByShip;
16
17     /** number of tokens queued on the trigger input */
18     private int     triggersReceived = 0;
19
20     /** the latched value */
21     private long register;
22
23     public boolean isInbox() { return false; }
24     public boolean isOutbox() { return true; }
25     public Outbox(InterpreterShip ship, String name) { this(ship, name, new String[] { "" }); }
26     public Outbox(InterpreterShip ship, String name, String[] ports) { super(ship, name, ports); }
27
28     protected final boolean service(Instruction.Executable instruction) {
29
30         // if no instruction waiting, do nothing
31         if (instruction == null) return false;
32
33         // check firing conditions
34         if (instruction.tokenIn && triggersReceived <= 0) return false;
35         if (instruction.dataIn) {
36             if (!haveDataFromShip) { readyForDataFromShip = true; return false; }
37         }
38         
39         // consume trigger
40         if (instruction.tokenIn) triggersReceived--;
41
42         // consume item
43         if (instruction.dataIn) {
44             haveDataFromShip = false;
45             if (instruction.latch) 
46                 register = itemPresentedByShip;
47         }
48
49         if (instruction.dataOut) {
50
51             // if item to be transmitted, send it
52             InterpreterDestination dest = (InterpreterDestination)instruction.dest;
53             if (instruction.dataOutDest) {
54                 // FIXME
55                 long bits = BitManipulations.getField(InstructionEncoder.WIDTH_WORD-1,
56                                                       InstructionEncoder.WIDTH_WORD-InstructionEncoder.WIDTH_DEST_ADDR,
57                                                       register);
58                 dest = (InterpreterDestination)(((Interpreter)getInterpreter()).iie.getDestByAddr(bits));
59                 throw new RuntimeException();
60             }
61             new Packet(getInterpreter(), this, register, dest).send();
62             if (instruction.tokenOut)
63                 throw new RuntimeException("outboxes may not send acks!");
64
65         } else if (instruction.tokenOut) {
66
67             // if no item was sent, we might still send an ack
68             new Packet(getInterpreter(), this, 0, (InterpreterDestination)instruction.dest).send();
69         }
70
71         return true;
72     }
73
74     public final boolean readyForDataFromShip() { return readyForDataFromShip; }
75     public       void addDataFromShip(long data) { addItemFromShip(data); }
76     public       void addDataFromFabric(Packet packet) { triggersReceived++; }
77
78     /** subclass invokes this to add an item from the ship */
79     protected final void addItemFromShip(long data) {
80         if (!readyForDataFromShip)
81             throw new RuntimeException("tried to add an item to an outbox which was not ready!  you have a buggy ship!");
82         readyForDataFromShip = false;
83         haveDataFromShip = true;
84         itemPresentedByShip = data;
85     }
86
87     void shutdown() {
88         if (haveDataFromShip)
89             Log.println(ANSI.red(" WARNING: you left a value ("+itemPresentedByShip+") on outbox port " + this));
90         if (triggersReceived > 0)
91             Log.println(ANSI.red(" WARNING: you left a token on the trigger input to port " + this));
92         super.shutdown(false);
93     }
94
95 }