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

Subversion Repositories cryptosorter

[/] [cryptosorter/] [trunk/] [memocodeDesignContest2008/] [sort/] [BRAMLevelFIFOAdders/] [BRAMVLevelFIFO.bsv] - Blame information for rev 6

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 kfleming
//----------------------------------------------------------------------//
2
// The MIT License
3
//
4
// Copyright (c) 2008 Alfred Man Cheuk Ng, mcn02@mit.edu
5
//
6
// Permission is hereby granted, free of charge, to any person
7
// obtaining a copy of this software and associated documentation
8
// files (the "Software"), to deal in the Software without
9
// restriction, including without limitation the rights to use,
10
// copy, modify, merge, publish, distribute, sublicense, and/or sell
11
// copies of the Software, and to permit persons to whom the
12
// Software is furnished to do so, subject to the following conditions:
13
//
14
// The above copyright notice and this permission notice shall be
15
// included in all copies or substantial portions of the Software.
16
//
17
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
// OTHER DEALINGS IN THE SOFTWARE.
25
//----------------------------------------------------------------------//
26
 
27
//////////////////////////////////////////////////////////////////////////
28
// Summary
29
//
30
// This file describes the implementation of VLevelFIFO which time multiplex
31
// a single memory instance with one write port and one read port between
32
// multiple logical fifos. The implementation is parameteric in the following
33
// ways: 1) the number of logical fifos, 2) the size of each logical fifo,
34
// 3) the data type stored in the fifo
35
//////////////////////////////////////////////////////////////////////////
36
 
37
// import standard library
38
import DReg::*;
39
import FIFO::*;
40
import RegFile::*;
41
import StmtFSM::*;
42
import Vector::*;
43
 
44
// import self-made library
45
import BRAM::*;
46
import EHRReg::*;
47
import VLevelFIFO::*;
48
 
49
`define Debug False
50
 
51
// try to update the new value of vec[idx] to f(vec[idx])
52
function Vector#(sz,a) parUpdate (Vector#(sz,a) vec, Bit#(isz) idx,
53
                                  function a f (a val));
54
   Vector#(sz,a) new_vec = newVector();
55
   for (Integer i = 0; i < valueOf(sz); i = i + 1)
56
      begin
57
         if (idx == fromInteger(i))
58
            new_vec[i] = f(vec[i]);
59
         else
60
            new_vec[i] = vec[i];
61
      end
62
   return new_vec;
63
endfunction
64
 
65
function Bit#(a) decrBy(Bit#(a) snd, Bit#(a) fst);
66
   return fst - snd;
67
endfunction
68
 
69
// implementation of VLevelFIFO with BRAM
70
module mkBRAMVLevelFIFO (VLevelFIFO#(no_fifo, fifo_sz, data_t))
71
   provisos (Bits#(data_t,data_sz),
72
             Add#(TLog#(no_fifo),TLog#(fifo_sz),bram_idx_sz));
73
 
74
   // instantiate an unguarded 1 cycle latency bram (i.e. the read response will only valid for 1 cycle)
75
   UGBRAM#(Bit#(bram_idx_sz), data_t)           ugbram <- mkBypassUGBRAM_Full();
76
 
77
   RegFile#(Bit#(TLog#(no_fifo)),Bit#(TLog#(fifo_sz)))  head <- mkRegFileFull();
78
   RegFile#(Bit#(TLog#(no_fifo)),Bit#(TLog#(fifo_sz)))  tail <- mkRegFileFull();
79
   Reg#(Bit#(TLog#(no_fifo))) i <- mkReg(0);
80
   Reg#(Bool) finishInit <- mkReg(False);
81
 
82
   EHRReg#(2,Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))))  usedReg;
83
   usedReg <- mkEHRReg(replicate(0));
84
   EHRReg#(2,Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))))  freeReg;
85
   freeReg <- mkEHRReg(replicate(fromInteger(valueOf(fifo_sz))));
86
 
87
   Wire#(Maybe#(Bit#(TLog#(no_fifo))))  enqIdx <- mkDWire(tagged Invalid);
88
   Wire#(data_t)                        enqVal <- mkDWire(?);
89
   Reg#(Maybe#(Bit#(TLog#(no_fifo))))   lastEnqIdx <- mkDReg(tagged Invalid);
90
 
91
   Wire#(Maybe#(Bit#(TLog#(no_fifo))))  deqIdx <- mkDWire(tagged Invalid);
92
   Reg#(Maybe#(Bit#(TLog#(no_fifo))))   lastDeqIdx <- mkDReg(tagged Invalid);
93
 
94
   Wire#(Maybe#(Bit#(TLog#(no_fifo))))  firstIdx <- mkDWire(tagged Invalid);
95
 
96
   Wire#(Maybe#(Bit#(TLog#(no_fifo))))  decrFreeIdx <- mkDWire(tagged Invalid);
97
   Wire#(Bit#(TLog#(TAdd#(fifo_sz,1)))) decrFreeAmnt <- mkDWire(?);
98
 
99
   let enqIdxVal         = fromMaybe(0,enqIdx);
100
   let deqIdxVal         = fromMaybe(0,deqIdx);
101
   let firstIdxVal       = fromMaybe(0,firstIdx);
102
   let decrFreeIdxVal    = fromMaybe(0,decrFreeIdx);
103
   let deqIdxNEQFirstIdx = deqIdxVal != firstIdxVal;
104
   let readResp          = ugbram.read_resp();
105
 
106
   // start the initialization processor
107
   rule initialization(!finishInit);
108
      head.upd(i,0);
109
      tail.upd(i,0);
110
      i <= i + 1;
111
      if (i == fromInteger(valueOf(no_fifo)-1))
112
         finishInit <= True;
113
   endrule
114
 
115
   rule processEnq(finishInit && isValid(enqIdx));
116
      let tailVal = tail.sub(enqIdxVal);
117
      tail.upd(enqIdxVal, (tailVal + 1));
118
      ugbram.write({enqIdxVal,tailVal},enqVal);
119
      lastEnqIdx <= enqIdx;
120
 
121
      if(`Debug) $display("%m enq data %d to fifo %d with tailVal %d",enqVal,enqIdxVal,tailVal);
122
   endrule
123
 
124
   // last cycle someone enq, we update the usedReg this cycle (conservative
125
   rule updateUsedReg (isValid(lastEnqIdx));
126
      let idx = fromMaybe(?,lastEnqIdx);
127
      usedReg[0] <= parUpdate(usedReg[0], idx, \+ (1));
128
 
129
      if(`Debug) $display("%m updateUsedReg idx %d old val %d new val %d",idx,usedReg[0][idx], usedReg[1][idx]);
130
   endrule
131
 
132
   // last cycle someone deq, we update the freeReg this cycle (conservative)
133
   rule updateFreeReg (isValid(lastDeqIdx));
134
      let idx = fromMaybe(?,lastDeqIdx);
135
      freeReg[0] <= parUpdate(freeReg[0], idx, \+ (1));
136
 
137
      if(`Debug) $display("%m updateFreeReg idx %d old val %d new val %d",idx,freeReg[0][idx], freeReg[1][idx]);
138
   endrule
139
 
140
   rule processDeq(finishInit && isValid(deqIdx));
141
      let headVal = head.sub(deqIdxVal);
142
      head.upd(deqIdxVal, (headVal + 1));
143
      usedReg[1] <= parUpdate(usedReg[1], deqIdxVal, decrBy(1));
144
      lastDeqIdx <= deqIdx;
145
 
146
      if(`Debug) $display("%m deq fifo %d",deqIdxVal);
147
   endrule
148
 
149
   rule processFirstReq(finishInit && isValid(firstIdx));
150
      let headVal = head.sub(firstIdxVal);
151
      ugbram.read_req({firstIdxVal,headVal});
152
//       if (deqIdxNEQFirstIdx || !isValid(deqIdx))
153
//          begin
154
//             ugbram.read_req({firstIdxVal,headVal});
155
 
156
//             if(`Debug) $display("%m first read idx %d headVal %d",firstIdxVal,headVal);
157
//          end
158
//       else // the fifo is dequeued at that cycle, we should read the next head
159
//          begin
160
//             ugbram.read_req({firstIdxVal,headVal+1});
161
 
162
//             if(`Debug) $display("%m first read idx %d headVal+1 %d",firstIdxVal,headVal+1);
163
//          end
164
   endrule
165
 
166
   rule processDecrFree(finishInit && isValid(decrFreeIdx));
167
      freeReg[1] <= parUpdate(freeReg[1], decrFreeIdxVal, decrBy(decrFreeAmnt));
168
 
169
      if(`Debug) $display("%m decrFree fifo %d by %d",decrFreeIdxVal,decrFreeAmnt);
170
   endrule
171
 
172
   // enq is unguarded here, we expect the user to check it before they enq
173
   method Action enq(Bit#(TLog#(no_fifo)) idx, data_t data) if (finishInit);
174
      enqIdx <= tagged Valid idx;
175
      enqVal <= data;
176
   endmethod
177
 
178
   // deq is unguarded here, we expect the user to check it before they deq
179
   method Action deq(Bit#(TLog#(no_fifo)) idx)  if (finishInit);
180
      deqIdx <= tagged Valid idx;
181
   endmethod
182
 
183
   method Action firstReq(Bit#(TLog#(no_fifo)) idx)  if (finishInit);
184
      firstIdx <= tagged Valid idx;
185
   endmethod
186
 
187
   // first is unguarded here, we expecte the user to check it before they call first
188
   method data_t firstResp()  if (finishInit);
189
      return readResp;
190
   endmethod
191
 
192
   method Action clear()  if (finishInit);
193
      noAction;
194
   endmethod
195
 
196
   // return the usage of each fifo at the beginning of the cycle
197
   method Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))) used()  if (finishInit);
198
      return usedReg[0];
199
   endmethod
200
 
201
   // return enq credit token available for each fifo
202
   method Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))) free()  if (finishInit);
203
      return freeReg[0];
204
   endmethod
205
 
206
   // get credit token to enq fifo idx in the future
207
   // this method is unguarded (i.e. user need to call method free
208
   // and check for token availability before calling this action)
209
   method Action decrFree(Bit#(TLog#(no_fifo)) idx, Bit#(TLog#(TAdd#(fifo_sz,1))) amnt)  if (finishInit);
210
      decrFreeIdx  <= tagged Valid idx;
211
      decrFreeAmnt <= amnt;
212
   endmethod
213
 
214
endmodule
215
 
216
// implementation of VLevelFIFO with BRAM decrFree is always treated as deq one token
217
module mkDecrOneBRAMVLevelFIFO (VLevelFIFO#(no_fifo, fifo_sz, data_t))
218
   provisos (Bits#(data_t,data_sz),
219
             Add#(TLog#(no_fifo),TLog#(fifo_sz),bram_idx_sz));
220
 
221
   // instantiate an unguarded 1 cycle latency bram (i.e. the read response will only valid for 1 cycle)
222
   UGBRAM#(Bit#(bram_idx_sz), data_t)           ugbram <- mkBypassUGBRAM_Full();
223
 
224
   RegFile#(Bit#(TLog#(no_fifo)),Bit#(TLog#(fifo_sz)))  head <- mkRegFileFull();
225
   RegFile#(Bit#(TLog#(no_fifo)),Bit#(TLog#(fifo_sz)))  tail <- mkRegFileFull();
226
   Reg#(Bit#(TLog#(no_fifo))) i <- mkReg(0);
227
   Reg#(Bool) finishInit <- mkReg(False);
228
 
229
   Reg#(Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))))  usedReg <- mkReg(replicate(0));
230
 
231
   Reg#(Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))))  freeReg <- mkReg(replicate(fromInteger(valueOf(fifo_sz))));
232
 
233
   Wire#(Maybe#(Bit#(TLog#(no_fifo)))) enqIdx <- mkDWire(tagged Invalid);
234
   Wire#(data_t)                       enqVal <- mkDWire(?);
235
 
236
   Wire#(Maybe#(Bit#(TLog#(no_fifo)))) deqIdx <- mkDWire(tagged Invalid);
237
 
238
   Wire#(Maybe#(Bit#(TLog#(no_fifo)))) firstIdx <- mkDWire(tagged Invalid);
239
 
240
   Wire#(Maybe#(Bit#(TLog#(no_fifo)))) decrFreeIdx <- mkDWire(tagged Invalid);
241
 
242
   let enqIdxVal         = fromMaybe(0,enqIdx);
243
   let deqIdxVal         = fromMaybe(0,deqIdx);
244
   let firstIdxVal       = fromMaybe(0,firstIdx);
245
   let decrFreeIdxVal    = fromMaybe(0,decrFreeIdx);
246
   let deqIdxNEQFirstIdx = deqIdxVal != firstIdxVal;
247
   let readResp          = ugbram.read_resp();
248
 
249
   // start the initialization processor
250
   rule initialization(!finishInit);
251
      head.upd(i,0);
252
      tail.upd(i,0);
253
      i <= i + 1;
254
      if (i == fromInteger(valueOf(no_fifo)-1))
255
         finishInit <= True;
256
   endrule
257
 
258
   rule updateUsedReg(finishInit && (isValid(enqIdx) || isValid(deqIdx)));
259
      Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))) newUsedReg = newVector();
260
      for (Integer i = 0; i < valueOf(no_fifo); i = i + 1)
261
         begin
262
            Bit#(TLog#(no_fifo)) iVal = fromInteger(i);
263
            let checkEnqIdx = enqIdxVal == iVal;
264
            let checkDeqIdx = deqIdxVal == iVal;
265
            if (isValid(enqIdx) && checkEnqIdx && !(isValid(deqIdx) && checkDeqIdx))
266
               newUsedReg[i] = usedReg[i] + 1;
267
            else
268
               if (isValid(deqIdx) && checkDeqIdx && !(isValid(enqIdx) && checkEnqIdx))
269
                  newUsedReg[i] = usedReg[i] - 1;
270
               else
271
                  newUsedReg[i] = usedReg[i];
272
         end
273
      usedReg <= newUsedReg;
274
 
275
      if(`Debug) $display("%m updateUsedReg");
276
   endrule
277
 
278
   rule updateFreeReg(finishInit && (isValid(decrFreeIdx) || isValid(deqIdx)));
279
      Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))) newFreeReg = newVector();
280
      for (Integer i = 0; i < valueOf(no_fifo); i = i + 1)
281
         begin
282
            Bit#(TLog#(no_fifo)) iVal = fromInteger(i);
283
            let checkDecrFreeIdx      = decrFreeIdxVal == iVal;
284
            let checkDeqIdx           = deqIdxVal == iVal;
285
            if (isValid(decrFreeIdx) && checkDecrFreeIdx && !(isValid(deqIdx) && checkDeqIdx))
286
               newFreeReg[i] = freeReg[i] - 1;
287
            else
288
               if (isValid(deqIdx) && checkDeqIdx && !(isValid(decrFreeIdx) && checkDecrFreeIdx))
289
                  newFreeReg[i] = freeReg[i] + 1;
290
               else
291
                  newFreeReg[i] = freeReg[i];
292
         end
293
      freeReg <= newFreeReg;
294
 
295
      if(`Debug) $display("%m updateFreeReg");
296
   endrule
297
 
298
   rule processEnq(finishInit && isValid(enqIdx));
299
      let tailVal = tail.sub(enqIdxVal);
300
      tail.upd(enqIdxVal, (tailVal + 1));
301
      ugbram.write({enqIdxVal,tailVal},enqVal);
302
 
303
      if(`Debug) $display("%m enq data %d to fifo %d with tailVal %d",enqVal,enqIdxVal,tailVal);
304
   endrule
305
 
306
   rule processFirstReq(finishInit && isValid(firstIdx));
307
      let headVal = head.sub(firstIdxVal);
308
      ugbram.read_req({firstIdxVal,headVal});
309
 
310
//       if (deqIdxNEQFirstIdx || !isValid(deqIdx))
311
//          begin
312
//             ugbram.read_req({firstIdxVal,headVal});
313
//             if(`Debug) $display("%m first read idx %d headVal %d",firstIdxVal,headVal);
314
//          end
315
//       else // the fifo is dequeued at that cycle, we should read the next head
316
//          begin
317
//             ugbram.read_req({firstIdxVal,headVal+1});
318
//             if(`Debug) $display("%m first read idx %d headVal+1 %d",firstIdxVal,headVal+1);
319
//          end
320
   endrule
321
 
322
   rule processDeq(finishInit && isValid(deqIdx));
323
      let headVal = head.sub(deqIdxVal);
324
      head.upd(deqIdxVal, (headVal + 1));
325
   endrule
326
 
327
   // enq is unguarded here, we expect the user to check it before they enq
328
   method Action enq(Bit#(TLog#(no_fifo)) idx, data_t data) if (finishInit);
329
      enqIdx <= tagged Valid idx;
330
      enqVal <= data;
331
   endmethod
332
 
333
   // deq is unguarded here, we expect the user to check it before they deq
334
   method Action deq(Bit#(TLog#(no_fifo)) idx)  if (finishInit);
335
      deqIdx <= tagged Valid idx;
336
 
337
      if(`Debug) $display("%m deq fifo %d",idx);
338
   endmethod
339
 
340
   method Action firstReq(Bit#(TLog#(no_fifo)) idx)  if (finishInit);
341
      firstIdx <= tagged Valid idx;
342
   endmethod
343
 
344
   // first is unguarded here, we expecte the user to check it before they call first
345
   method data_t firstResp()  if (finishInit);
346
      return readResp;
347
   endmethod
348
 
349
   method Action clear()  if (finishInit);
350
      noAction;
351
   endmethod
352
 
353
   // return the usage of each fifo at the beginning of the cycle
354
   method Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))) used()  if (finishInit);
355
      return usedReg;
356
   endmethod
357
 
358
   // return enq credit token available for each fifo
359
   method Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))) free()  if (finishInit);
360
      return freeReg;
361
   endmethod
362
 
363
   // get credit token to enq fifo idx in the future
364
   // this method is unguarded (i.e. user need to call method free
365
   // and check for token availability before calling this action)
366
   method Action decrFree(Bit#(TLog#(no_fifo)) idx, Bit#(TLog#(TAdd#(fifo_sz,1))) amnt)  if (finishInit);
367
      decrFreeIdx <= tagged Valid idx;
368
   endmethod
369
 
370
endmodule

powered by: WebSVN 2.1.0

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