OpenCores
URL https://opencores.org/ocsvn/bluespec-h264/bluespec-h264/trunk

Subversion Repositories bluespec-h264

[/] [bluespec-h264/] [trunk/] [src_fpga/] [mkMemClient.bsv] - Rev 100

Compare with Previous | Blame | View Log


// The MIT License

// Copyright (c) 2006-2007 Massachusetts Institute of Technology

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.


package mkMemClient;


import MemControllerTypes::*;
import IMemClient::*;
import IMemClientBackend::*;
import FIFOF::*;
import FIFO::*;
import mkSatCounter::*;
import FIFO_2::*;

`define FIFO_SIZE 2

typedef enum {
  NORMAL,  
  WRITE_AFTER_READ
}
  MemClientState
    deriving(Bits, Eq);


module mkMemClient#(Integer client_num)  (IMemClientBackend#(addr_type, data_type))
  provisos
          (Bits#(addr_type, addr_p), 
           Bits#(data_type, data_p),
           Bits#(MemReq#(addr_type, data_type), mem_req_p)
);

  Reg#(PRIORITY_LEVEL) priority_level <- mkReg(0);
  FIFOF#(MemReq#(addr_type, data_type)) req_fifo <- mkFIFOF(); 
  FIFOF#(Maybe#(MemReq#(addr_type, data_type))) read_fifo <- mkFIFOF();
  FIFOF#(Maybe#(MemReq#(addr_type, data_type))) write_fifo <- mkFIFOF();
  RWire#(MemReq#(addr_type, data_type)) read_enqueue <- mkRWire();
  RWire#(MemReq#(addr_type, data_type)) write_enqueue <- mkRWire();
  FIFO#(data_type) load_responses <- mkSizedFIFO(`FIFO_SIZE);
  SatCounter#(TAdd#(1, TLog#(`FIFO_SIZE))) counter <- mkSatCounter(0);
  Reg#(Bool) read_has_priority <- mkReg(True); 
  Reg#(Bool) write_has_priority <- mkReg(False);
  Reg#(MemClientState) state <- mkReg(NORMAL);

  rule process_input; 
    Maybe#(MemReq#(addr_type, data_type)) r_enq = read_enqueue.wget;
    Maybe#(MemReq#(addr_type, data_type)) w_enq = write_enqueue.wget;
    if(r_enq matches tagged Valid .r)
      begin
        read_fifo.enq(r_enq);
        write_fifo.enq(w_enq);
      end
    else if(w_enq matches tagged Valid .w)
      begin
        read_fifo.enq(r_enq);
        write_fifo.enq(w_enq);
      end    
  endrule

  rule process_queues_normal ((state == NORMAL) && (counter.value() < `FIFO_SIZE));
    if(read_fifo.first() matches tagged Valid .r )
      begin
        if(write_fifo.first() matches tagged Valid .w )
          begin 
            req_fifo.enq(r);
            counter.up();
            state <= WRITE_AFTER_READ;
          end     
        else
          begin
            req_fifo.enq(r);
            counter.up();
            read_fifo.deq();
            write_fifo.deq();            
          end
      end 
    else
      begin
        if(write_fifo.first() matches tagged Valid .w )
           begin
             req_fifo.enq(w);
             read_fifo.deq();
             write_fifo.deq();
           end
      end
  endrule

  rule process_queues_war (state == WRITE_AFTER_READ);
    if(write_fifo.first() matches tagged Valid .w ) 
      begin
        req_fifo.enq(w);
      end
    else
      begin
        $display("MemClient error, attempting to enqueue invalid write instruction");
      end
    read_fifo.deq();
    write_fifo.deq();    
    state <= NORMAL;
  endrule

  interface IMemClient client_interface; 
    // comment about read_fifo/write_fifo....
    method Action read_req(addr_type addr_in) if(read_fifo.notFull() && write_fifo.notFull());
      //$display("MemClient%dReadReq: received read_req, addr:%x", fromInteger(client_num), addr_in);
      read_enqueue.wset(tagged LoadReq{addr:addr_in}); 
    endmethod

    method ActionValue#(data_type) read_resp();
      let resp = load_responses.first();
       //$display("MemClient%dReadResp: delivered read_resp, data:%x", fromInteger(client_num), resp);
      load_responses.deq();
      if(counter.value() != 0)
        begin
          counter.down(); 
        end
      return resp;
    endmethod

    method Action write(addr_type addr_in, data_type data_in) if(read_fifo.notFull() && write_fifo.notFull());
       //$display("MemClient%d: received write_req, addr:%x, data:%x", client_num , addr_in, data_in);
      write_enqueue.wset(tagged StoreReq{addr:addr_in, data:data_in});
    endmethod

    method Action set_priority(PRIORITY_LEVEL prio);
      priority_level <= prio;
    endmethod
  endinterface

  interface request_fifo = req_fifo;  // Does this compile?

  method PRIORITY_LEVEL get_priority(); 
    return priority_level;
  endmethod

  method Action enqueue_response(data_type data_in);  
    load_responses.enq(data_in); 
  endmethod
endmodule

endpackage

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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