StreamFIFONew.bsv
上传用户:aoptech
上传日期:2014-09-22
资源大小:784k
文件大小:9k
源码类别:

3G开发

开发平台:

Others

  1. //----------------------------------------------------------------------//
  2. // The MIT License 
  3. // 
  4. // Copyright (c) 2007 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. // Definition and Implementation of StreamFIFO
  28. // Description: StreamFIFO is a fifo that can enq and deq 
  29. // arbitrary no. elements
  30. /////////////////////////////////////////////////////////////
  31. import EHRReg::*;
  32. import Vector::*;
  33. /////////////////////////////////////////////////////////////
  34. // Interface
  35. // Name: StreamFIFO
  36. // Ptrs: sz     : FIFO size
  37. //       s_sz   : no. bits representing no. elements allowed to be enq/deq in one cycle
  38. //       data_t : data element type
  39. // Dscr: A fifo that can enq and deq arbitrary no. of 
  40. //       elements
  41. /////////////////////////////////////////////////////////////
  42. interface StreamFIFO#(numeric type sz,     // buffer sz
  43.       numeric type s_sz,  
  44.       type data_t);        // basic data unit
  45.       method Action enq(Bit#(s_sz) i_s_sz, 
  46. Vector#(sz, data_t) i_msg);
  47.       method Vector#(sz, data_t) first();
  48.       method Action deq(Bit#(s_sz) o_s_sz); 
  49.       method Action clear();
  50.       method Bool notEmpty(Bit#(s_sz) o_s_sz); // canDeq?
  51.       method Bool notFull(Bit#(s_sz) i_s_sz);  // canEnq?
  52.       method Bit#(s_sz) usage(); // no of slots used
  53.       method Bit#(s_sz) free(); // no of slots unused
  54. endinterface
  55. //////////////////////////////////////////////////////////////
  56. // Auxiliary Functions
  57. /////////////////////////////////////////////////////////////
  58. // turn Bit#(sz) to vector of 1 bit
  59. function Vector#(sz,Bit#(1)) bit2Vec(Bit#(sz) val);
  60.    return unpack(pack(val));
  61. endfunction
  62. // dynamic left shifter using barrel shifter
  63. function Vector#(sz,data_t) shiftLeftBy(Vector#(sz,data_t) inVec,
  64. Bit#(s_sz) shiftBy)
  65.    provisos (Bits#(data_t,data_sz));
  66.    
  67.    function Vector#(sz,data_t) stageFunc(Vector#(sz,data_t) iVec,
  68.                                          Tuple2#(Bit#(1),Nat) ctrl);
  69.       Nat shftAmnt = (tpl_1(ctrl) == 1) ? tpl_2(ctrl) : 0;
  70.       return unpack(pack(iVec) << shftAmnt);
  71.    endfunction
  72.    
  73.    Nat dataSz = fromInteger(valueOf(data_sz));
  74.    Vector#(s_sz,Bit#(1)) shiftVec = unpack(shiftBy);
  75.    Vector#(s_sz,Nat) natVec0 = genWith(fromInteger());
  76.    Vector#(s_sz,Nat) natVec1 = map(<< (1),natVec0);
  77.    Vector#(s_sz,Nat) natVec2 = map(* (dataSz),natVec1);
  78.    let ctrlVec = zip(shiftVec, natVec2);
  79.    return foldl(stageFunc,inVec,ctrlVec);
  80.    
  81. endfunction
  82. // dynamic right shifter using barrel shifter
  83. function Vector#(sz,data_t) shiftRightBy(Vector#(sz,data_t) inVec,
  84.  Bit#(s_sz) shiftBy)
  85.    provisos (Bits#(data_t,data_sz));
  86.    
  87.    function Vector#(sz,data_t) stageFunc(Vector#(sz,data_t) iVec,
  88.  Tuple2#(Bit#(1),Nat) ctrl);
  89.       Nat shftAmnt = (tpl_1(ctrl) == 1) ? tpl_2(ctrl) : 0;
  90.       return unpack(pack(iVec) >> shftAmnt);
  91.    endfunction
  92.    
  93.    Nat dataSz = fromInteger(valueOf(data_sz));
  94.    Vector#(s_sz,Bit#(1)) shiftVec = unpack(shiftBy);
  95.    Vector#(s_sz,Nat) natVec0 = genWith(fromInteger());
  96.    Vector#(s_sz,Nat) natVec1 = map(<< (1),natVec0);
  97.    Vector#(s_sz,Nat) natVec2 = map(* (dataSz),natVec1);
  98.    let ctrlVec = zip(shiftVec, natVec2);
  99.    return foldl(stageFunc,inVec,ctrlVec);
  100.    
  101. endfunction
  102. ////////////////////////////////////////////////////////////////////
  103. // Module
  104. // Name: mkStreamFIFO
  105. // Ptrs: 
  106. // Dscr: Create an instance of StreamFIFO which is implemented with
  107. //       shifting approach
  108. // Notes: To enq/deq, caller needs to check notFull/notEmpty 
  109. //        explicitly (unguarded) 
  110. ///////////////////////////////////////////////////////////////////
  111. module mkStreamFIFO(StreamFIFO#(sz, s_sz, data_t))
  112.    provisos (Add#(sz,1,szp1),  
  113.              Log#(szp1,ssz), // calculate ssz so that Bit#(ssz) can store values 0 - sz
  114.              Add#(xxA,s_sz,ssz), // s_sz <= ssz
  115.              Bits#(data_t,data_sz));
  116.    Bit#(ssz) maxS   = fromInteger(valueOf(TSub#(TExp#(s_sz),1)));
  117.    Bit#(ssz) maxIdx = fromInteger(valueOf(sz));          // buffer size
  118.    Reg#(Vector#(sz,data_t)) buffers <- mkReg(newVector); // data storage
  119.    EHRReg#(2,Bit#(ssz)) freeReg <- mkEHRReg(maxIdx);     // no. free slots
  120.    let usedNo = maxIdx - freeReg[0];                     // no. used slots
  121.    
  122.    method Action enq(Bit#(s_sz) i_s_sz, 
  123.                      Vector#(sz, data_t) i_msg);
  124.       let extBuffers = append(buffers, i_msg);           // append i_msg at the end of buffers
  125.       let shfBuffers = shiftRightBy(extBuffers, i_s_sz); // shift the extended buffers    
  126.       Vector#(sz, data_t) newBuffers = take(shfBuffers); // new buffers equals to first half of the buffer
  127.       buffers <= newBuffers;
  128.       freeReg[1] <= freeReg[1] - zeroExtend(i_s_sz);
  129.    endmethod
  130.    
  131.    method Vector#(sz, data_t) first(); 
  132.       // shift the data so that first data appeared at the beginning of the fifo
  133.       return shiftRightBy(buffers,freeReg[0]);
  134.    endmethod
  135.    
  136.    method Action deq(Bit#(s_sz) o_s_sz);
  137.       // adjust the no. free slots
  138.       freeReg[0] <= freeReg[0] + zeroExtend(o_s_sz);
  139.    endmethod
  140.    
  141.    method Action clear();
  142.       freeReg[1] <= maxIdx;
  143.    endmethod
  144.    
  145.    method Bool notEmpty(Bit#(s_sz) o_s_sz);
  146.       return usedNo >= zeroExtend(o_s_sz);
  147.    endmethod
  148.    
  149.    method Bool notFull(Bit#(s_sz) i_s_sz);
  150.       return freeReg[0] >= zeroExtend(i_s_sz);
  151.    endmethod
  152.    method Bit#(s_sz) usage() = (usedNo >= maxS) ? truncate(maxS) : truncate(usedNo) ; // no of slots used
  153.    method Bit#(s_sz) free()  = (freeReg[0] >= maxS) ? truncate(maxS) : truncate(usedNo) ; // no of slots unused
  154.        
  155. endmodule
  156. ////////////////////////////////////////////////////////////////////
  157. // Module
  158. // Name: mkStreamLFIFO
  159. // Ptrs: 
  160. // Dscr: Create an instance of StreamFIFO which is implemented with
  161. //       shifting approach, can deq and enq parallelly when it is full
  162. // Notes: To enq/deq, caller needs to check notFull/notEmpty 
  163. //        explicitly  
  164. ///////////////////////////////////////////////////////////////////
  165. module mkStreamLFIFO(StreamFIFO#(sz, s_sz, data_t))
  166.    provisos (Add#(sz,1,szp1),  
  167.              Log#(szp1,ssz), // calculate ssz so that Bit#(ssz) can store values 0 - sz
  168.              Add#(xxA,s_sz,ssz), // s_sz <= ssz
  169.              Bits#(data_t,data_sz));
  170.    
  171.    Bit#(ssz) maxS   = fromInteger(valueOf(TSub#(TExp#(s_sz),1)));
  172.    Bit#(ssz) maxIdx = fromInteger(valueOf(sz));          // buffer size
  173.    Reg#(Vector#(sz,data_t)) buffers <- mkReg(newVector); // data storage
  174.    EHRReg#(2,Bit#(ssz)) freeReg <- mkEHRReg(maxIdx);     // no. free slots
  175.    let usedNo = maxIdx - freeReg[0];                     // no. used slots
  176.    
  177.    method Action enq(Bit#(s_sz) i_s_sz, 
  178.                      Vector#(sz, data_t) i_msg);
  179.       let extBuffers = append(buffers, i_msg);           // append i_msg at the end of buffers
  180.       let shfBuffers = shiftRightBy(extBuffers, i_s_sz); // shift the extended buffers    
  181.       Vector#(sz, data_t) newBuffers = take(shfBuffers); // new buffers equals to first half of the buffer
  182.       buffers <= newBuffers;
  183.       freeReg[1] <= freeReg[1] - zeroExtend(i_s_sz);
  184.    endmethod
  185.    
  186.    method Vector#(sz, data_t) first(); 
  187.       return shiftRightBy(buffers,freeReg[0]);
  188.    endmethod
  189.    
  190.    method Action deq(Bit#(s_sz) o_s_sz); 
  191.       freeReg[0] <= freeReg[0] + zeroExtend(o_s_sz);
  192.    endmethod
  193.    
  194.    method Action clear();
  195.       freeReg[1] <= maxIdx;
  196.    endmethod
  197.    
  198.    method Bool notEmpty(Bit#(s_sz) o_s_sz);
  199.       return usedNo >= zeroExtend(o_s_sz);
  200.    endmethod
  201.    
  202.    method Bool notFull(Bit#(s_sz) i_s_sz);
  203.       return freeReg[0] >= zeroExtend(i_s_sz);
  204.    endmethod
  205.    method Bit#(s_sz) usage() = (usedNo >= maxS) ? truncate(maxS) : truncate(usedNo) ; // no of slots used
  206.    method Bit#(s_sz) free()  = (freeReg[0] >= maxS) ? truncate(maxS) : truncate(usedNo) ; // no of slots unused
  207.    
  208. endmodule