8d862088884727ce3c20a9ef6f011f8f00c80b46
[fleet.git] / ships / Memory.ship
1 ship: Memory
2
3 == Ports ===========================================================
4 data  in:    inCBD
5 data  in:    inAddrRead
6 data  in:    inAddrWrite
7 data  in:    inDataWrite
8 data  in:    inStride
9 data  in:    inCount
10
11 data  out:   out
12 data  out:   outIhorn
13
14 == TeX ==============================================================
15
16 The {\tt Memory} ship represents an interface to a storage space,
17 which can be used to read from it or write to it.  This storage space
18 might be a fast on-chip cache, off chip DRAM, or perhaps even a disk drive.
19
20 There may be multiple {\tt Memory} ships which interface to the same
21 physical storage space.  An implementation of Fleet must provide
22 additional documentation to the programmer indicating which {\tt
23 Memory} ships correspond to which storage spaces.  A single {\tt
24 Memory} ship may also access a ``virtual storage space'' formed by
25 concatenating multiple physical storage spaces.
26
27 \subsection*{Code Bag Fetch}
28
29 When a word appears at the {\tt inCBD} port, it is treated as a {\it
30 code bag descriptor}, as shown below:
31
32 \begin{center}
33 \setlength{\bitwidth}{3mm}
34 {\tt
35 \begin{bytefield}{37}
36   \bitheader[b]{36,6,5,0}\\
37   \bitbox{31}{Address} 
38   \bitbox{6}{size} 
39 \end{bytefield}
40 }
41 \end{center}
42
43 When a word arrives at the {\tt inCBD} port, it is treated as a memory
44 read with {\tt inAddrRead=Address}, {\tt inStride=1}, and {\tt
45 inCount=size}.
46
47 \subsection*{Reading}
48
49 When a word is delivered to {\tt inAddrRead}, the word residing in
50 memory at that address is provided at {\tt out}.
51
52 \subsection*{Writing}
53
54 When a word is delivered to {\tt inAddrWrite} and {\tt inDataWrite},
55 the word at {\tt inDataWrite} is written to the address specified by
56 {\tt inAddrWrite}.  Once the word is successfully committed to memory,
57 the value {\tt inAddr+inStride} is provided at {\tt out} (that is, the
58 address of the next word to be written).
59
60 \subsection*{To Do}
61
62 Stride and count are not implemented.
63
64 We need a way to do an ``unordered fetch'' -- a way to tell the memory
65 unit to retrieve some block of words in any order it likes.  This can
66 considerably accelerate fetches when the first word of the region is
67 not cached, but other parts are cached.  This can also be used for
68 dispatching codebags efficiently -- but how will we make sure that
69 instructions destined for a given pump are dispatched in the correct
70 order (source sequence guarantee)?
71
72 A more advanced form would be ``unordered fetch of ordered records''
73 -- the ability to specify a record size (in words), the offset of the
74 first record, and the number of records to be fetched.  The memory
75 unit would then fetch the records in any order it likes, but would be
76 sure to return the words comprising a record in the order in which
77 they appear in memory.  This feature could be used to solve the source
78 sequence guarantee problem mentioned in the previous paragraph.
79
80 == Fleeterpreter ====================================================
81     private long[] mem = new long[0];
82     public long readMem(int addr) { return addr >= mem.length ? 0 : mem[addr]; }
83     public void writeMem(int addr, long val) {
84         if (addr >= mem.length) {
85             long[] newmem = new long[addr * 2 + 1];
86             System.arraycopy(mem, 0, newmem, 0, mem.length);
87             mem = newmem;
88         }
89         mem[addr] = val;
90     }
91
92     private long stride = 0;
93     private long count = 0;
94     private long addr = 0;
95     private boolean writing = false;
96
97     public void service() {
98 /*
99         if (box_inCBD.dataReadyForShip()) {
100             long val = box_inCBD.removeDataForShip();
101             long addr = val >> 6;
102             long size = val & 0x3f;
103             dispatch((int)addr, (int)size);
104         }
105 */
106         if (count > 0) {
107             if (writing) {
108               if (box_inDataWrite.dataReadyForShip() && box_out.readyForDataFromShip()) {
109                  writeMem((int)addr, box_inDataWrite.removeDataForShip());
110                  box_out.addDataFromShip(0);
111                  count--;
112                  addr += stride;
113               }
114             } else {
115               if (box_out.readyForDataFromShip()) {
116                  box_out.addDataFromShip(readMem((int)addr));
117                  count--;
118                  addr += stride;
119               }
120             }
121
122         } else if (box_inAddrRead.dataReadyForShip()) {
123             addr = box_inAddrRead.removeDataForShip();
124             stride = 0;
125             count = 1;
126             writing = false;
127
128         } else if (box_inAddrWrite.dataReadyForShip()) {
129 //            addr = box_inAddrWrite.peekPacketForShip().value;
130             box_inAddrWrite.removeDataForShip();
131             stride = 0;
132             count = 1;
133             writing = true;
134         }
135     }
136
137 == FleetSim ==============================================================
138
139 == FPGA ==============================================================
140
141   reg [(`CODEBAG_SIZE_BITS-1):0]  cursor;
142   reg                             write_flag;
143
144   wire [(`BRAM_ADDR_WIDTH-1):0]   addr1;
145   wire [(`BRAM_ADDR_WIDTH-1):0]   addr2;
146   wire [(`BRAM_DATA_WIDTH-1):0]   val2;
147   assign addr1 = write_flag ? inAddrWrite_d[(`DATAWIDTH-1):0] : inAddrRead_d[(`DATAWIDTH-1):0];
148   assign addr2 = (inCBD_d[(`INSTRUCTION_WIDTH-1):(`CODEBAG_SIZE_BITS)])+cursor;
149
150   bram14 mybram(clk, rst, write_flag, addr1, addr2, inDataWrite_d, out_d_, val2);
151
152   always @(posedge clk) begin
153
154     write_flag <= 0;
155
156     if (!rst) begin
157       `reset
158       cursor <= 0;
159     end else begin
160       write_flag <= 0;
161
162       if (!inAddrRead_r  && inAddrRead_a)  inAddrRead_a    <= 0;
163       if (!inDataWrite_r && inDataWrite_a) inDataWrite_a <= 0;
164       if (!inAddrWrite_r && inAddrWrite_a) inAddrWrite_a <= 0;
165
166       if ( out_r && !out_a) begin
167       end else if ( out_r &&  out_a) begin out_r <= 0;
168       end else if (!out_r && !out_a && inAddrRead_r && !inAddrRead_a) begin
169         inAddrRead_a    <= 1;
170         out_r           <= 1;
171   
172       end else if (!out_r && !out_a && inAddrWrite_r && inDataWrite_r) begin
173         // timing note: it's okay to set the *_a flags here because *_d will still
174         // be valid on the *next* cycle, which is all we care about
175         inAddrWrite_a   <= 1;
176         inDataWrite_a   <= 1;
177         out_r           <= 1;
178         write_flag      <= 1;
179   
180       end else if ( outIhorn_r &&  outIhorn_a)                       begin outIhorn_r         <= 0;
181       end else if (!inCBD_r &&  inCBD_a) begin inCBD_a <= 0;
182       end else if ( inCBD_r && !inCBD_a && !outIhorn_r && !outIhorn_a) begin
183         if (cursor < inCBD_d[(`CODEBAG_SIZE_BITS-1):0]) begin
184           outIhorn_d    <= val2;
185           outIhorn_r    <= 1;
186           cursor        <= cursor + 1;
187         end else begin
188           inCBD_a       <= 1;
189           cursor        <= 0;
190         end
191       end
192     end
193   end
194     
195
196
197
198 == Test ==============================================================
199 // expected output
200 #expect 12
201 #expect 13
202 #expect 14
203
204 // ships required in order to run this code
205 #ship debug          : Debug
206 #ship memory         : Memory
207
208 // instructions not in any codebag are part of the "root codebag"
209 // which is dispatched when the code is loaded
210
211 memory.inCBD:
212   literal BOB;
213   deliver;
214
215 BOB: {
216   debug.in:
217     literal 12; deliver;
218     literal 13; deliver;
219     literal 14; deliver;
220 }
221
222
223 == Constants ========================================================
224
225 == Contributors =========================================================
226 Adam Megacz <megacz@cs.berkeley.edu>