3 == Ports ===========================================================
11 == TeX ==============================================================
13 The {\tt Memory} ship represents an interface to a storage space,
14 which can be used to read from it or write to it. This storage space
15 might be a fast on-chip cache, off chip DRAM, or perhaps even a disk
18 Generally, distinct {\tt Memory} ships do not access the same backing
19 storage, although this is not strictly prohibited.
21 Each {\tt Memory} ship may have multiple {\it interfaces}, numbered
22 starting with {\tt 0}. Each interface may have any subset of the
23 following docks: {\tt inCBD}, {\tt inAddrRead}, {\tt inAddrWrite},
24 {\tt inDataWrite}, and {\tt out}. If {\tt inCBD} or {\tt inAddrRead}
25 is present on an interface, then {\tt out} must be present as well.
26 If {\tt inAddrWrite} is present then {\tt inDataWrite} must be present
29 Each interface serializes the operations presented to it; this means
30 that an interface with both read and write capabilities will not be
31 able to read and write concurrently. Instead, a {\tt Memory} ship
32 with the ability to read and write concurrently should have two
33 interfaces, one which is read-only and one which is write-only.
35 There may be multiple {\tt Memory} ships which interface to the same
36 physical storage space. An implementation of Fleet must provide
37 additional documentation to the programmer indicating which {\tt
38 Memory} ships correspond to which storage spaces. A single {\tt
39 Memory} ship may also access a ``virtual storage space'' formed by
40 concatenating multiple physical storage spaces.
42 \subsection*{Code Bag Fetch}
44 When a word appears at the {\tt inCBD} port, it is treated as a {\it
45 code bag descriptor}, as shown below:
48 \setlength{\bitwidth}{3mm}
51 \bitheader[b]{36,6,5,0}\\
58 When a word arrives at the {\tt inCBD} port, it is treated as a memory
59 read with {\tt inAddrRead=Address}, {\tt inStride=1}, and {\tt
64 When a word is delivered to {\tt inAddrRead}, the word residing in
65 memory at that address is provided at {\tt out}. The {\tt c-flag} at
66 the {\tt out} port is set to zero.
70 When a word is delivered to {\tt inAddrWrite} and {\tt inDataWrite},
71 the word at {\tt inDataWrite} is written to the address specified by
72 {\tt inAddrWrite}. Once the word is successfully committed to memory,
73 the value {\tt inAddr+inStride} is provided at {\tt out} (that is, the
74 address of the next word to be written). The {\tt c-flag} at
75 the {\tt out} port is set to one.
79 Stride and count are not implemented.
81 We need a way to do an ``unordered fetch'' -- a way to tell the memory
82 unit to retrieve some block of words in any order it likes. This can
83 considerably accelerate fetches when the first word of the region is
84 not cached, but other parts are cached. This can also be used for
85 dispatching codebags efficiently -- but how will we make sure that
86 instructions destined for a given pump are dispatched in the correct
87 order (source sequence guarantee)?
89 A more advanced form would be ``unordered fetch of ordered records''
90 -- the ability to specify a record size (in words), the offset of the
91 first record, and the number of records to be fetched. The memory
92 unit would then fetch the records in any order it likes, but would be
93 sure to return the words comprising a record in the order in which
94 they appear in memory. This feature could be used to solve the source
95 sequence guarantee problem mentioned in the previous paragraph.
97 == Fleeterpreter ====================================================
98 private long[] mem = new long[0];
99 public long readMem(int addr) { return addr >= mem.length ? 0 : mem[addr]; }
100 public void writeMem(int addr, long val) {
101 if (addr >= mem.length) {
102 long[] newmem = new long[addr * 2 + 1];
103 System.arraycopy(mem, 0, newmem, 0, mem.length);
109 private long stride = 0;
110 private long count = 0;
111 private long addr = 0;
112 private boolean writing = false;
114 private Queue<Long> toDispatch = new LinkedList<Long>();
115 public void service() {
117 if (toDispatch.size() > 0) {
118 //if (!box_out.readyForDataFromShip()) return;
119 //box_out.addDataFromShip(toDispatch.remove());
120 getInterpreter().dispatch(getInterpreter().readInstruction(toDispatch.remove(), getDock("out")));
123 if (box_inCBD.dataReadyForShip() && box_out.readyForDataFromShip()) {
124 long val = box_inCBD.removeDataForShip();
125 long addr = val >> 6;
126 long size = val & 0x3f;
127 for(int i=0; i<size; i++)
128 toDispatch.add(readMem((int)(addr+i)));
132 if (box_inDataWrite.dataReadyForShip() && box_out.readyForDataFromShip()) {
133 writeMem((int)addr, box_inDataWrite.removeDataForShip());
134 box_out.addDataFromShip(0);
139 if (box_out.readyForDataFromShip()) {
140 box_out.addDataFromShip(readMem((int)addr));
146 } else if (box_inAddrRead.dataReadyForShip()) {
147 addr = box_inAddrRead.removeDataForShip();
152 } else if (box_inAddrWrite.dataReadyForShip()) {
153 addr = box_inAddrWrite.removeDataForShip();
160 == FleetSim ==============================================================
162 == FPGA ==============================================================
164 wire [(`DATAWIDTH-1):0] out1;
165 wire [(`DATAWIDTH-1):0] out2;
167 reg [(`CODEBAG_SIZE_BITS-1):0] counter;
168 reg [(`BRAM_ADDR_WIDTH-1):0] cursor;
174 initial write_flag = 0;
175 initial dispatching_cbd = 0;
177 wire [(`BRAM_ADDR_WIDTH-1):0] addr1;
178 assign addr1 = write_flag ? inAddrWrite_d[(`DATAWIDTH-1):0] : inAddrRead_d[(`DATAWIDTH-1):0];
179 bram14 mybram(clk, rst, write_flag, addr1, cursor, inDataWrite_d, out1, out2);
181 assign out_d_ = dispatching_cbd ? out2 : out1;
183 always @(posedge clk) begin
192 dispatching_cbd <= 0;
197 if (!inAddrRead_r_ && inAddrRead_a) inAddrRead_a <= 0;
198 if (!inDataWrite_r_ && inDataWrite_a) inDataWrite_a <= 0;
199 if (!inAddrWrite_r_ && inAddrWrite_a) inAddrWrite_a <= 0;
200 if (!inCBD_r_ && inCBD_a) inCBD_a <= 0;
202 // assumes we never want a zero-length codebag
203 if ( inCBD_r && !inCBD_a && !out_r && !out_a) begin
204 if (!dispatching_cbd) begin
205 cursor <= inCBD_d[(`INSTRUCTION_WIDTH-1):(`CODEBAG_SIZE_BITS)];
207 dispatching_cbd <= 1;
210 end else if (inCBD_r && out_r && out_a) begin
212 if (counter != inCBD_d[(`CODEBAG_SIZE_BITS-1):0]) begin
213 cursor <= cursor + 1;
214 counter <= counter + 1;
218 dispatching_cbd <= 0;
220 end else if (!dispatching_cbd && out_r && out_a) begin out_r <= 0;
221 end else if (!dispatching_cbd && !out_r && !out_a && inAddrRead_r && !inAddrRead_a) begin
225 end else if (!dispatching_cbd && !out_r && !out_a && inAddrWrite_r && inDataWrite_r) begin
226 // timing note: it's okay to set the *_a flags here because *_d will still
227 // be valid on the *next* cycle, which is all we care about
239 == Test ==============================================================
240 // FIXME: test c-flag at out dock
241 // FIXME: rename to inCBD0, inAddrWrite0, etc
248 // ships required in order to run this code
250 #ship memory : Memory
252 // instructions not in any codebag are part of the "root codebag"
253 // which is dispatched when the code is loaded
256 set ilc=*; collect packet, send;
264 set word= 12; deliver;
265 set word= 13; deliver;
266 set word= 14; deliver;
270 == Constants ========================================================
272 == Contributors =========================================================
273 Adam Megacz <megacz@cs.berkeley.edu>