rlm@8: // The MIT License rlm@8: rlm@8: // Copyright (c) 2009 Massachusetts Institute of Technology rlm@8: rlm@8: // Permission is hereby granted, free of charge, to any person obtaining a copy rlm@8: // of this software and associated documentation files (the "Software"), to deal rlm@8: // in the Software without restriction, including without limitation the rights rlm@8: // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell rlm@8: // copies of the Software, and to permit persons to whom the Software is rlm@8: // furnished to do so, subject to the following conditions: rlm@8: rlm@8: // The above copyright notice and this permission notice shall be included in rlm@8: // all copies or substantial portions of the Software. rlm@8: rlm@8: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR rlm@8: // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, rlm@8: // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE rlm@8: // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER rlm@8: // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, rlm@8: // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN rlm@8: // THE SOFTWARE. rlm@8: rlm@8: import Connectable::*; rlm@8: import GetPut::*; rlm@8: import ClientServer::*; rlm@8: import FIFOF::*; rlm@8: import FIFO::*; punk@28: import Trace::*; rlm@8: rlm@8: // Local includes rlm@8: `include "asim/provides/processor_library.bsh" rlm@8: rlm@8: interface MemArb; rlm@8: rlm@8: interface Server#(MainMemReq,MainMemResp) cache0_server; rlm@8: interface Server#(MainMemReq,MainMemResp) cache1_server; rlm@8: interface Client#(MainMemReq,MainMemResp) mmem_client; rlm@8: rlm@8: endinterface rlm@8: rlm@8: typedef enum { REQ0, REQ1 } ReqPtr deriving(Eq,Bits); rlm@8: rlm@8: module mkMemArb( MemArb ); rlm@8: rlm@8: //----------------------------------------------------------- rlm@8: // State rlm@8: rlm@8: FIFOF#(MainMemReq) req0Q <- mkBFIFOF1(); rlm@8: FIFO#(MainMemResp) resp0Q <- mkBFIFO1(); rlm@8: rlm@8: FIFOF#(MainMemReq) req1Q <- mkBFIFOF1(); rlm@8: FIFO#(MainMemResp) resp1Q <- mkBFIFO1(); rlm@8: rlm@8: FIFO#(MainMemReq) mreqQ <- mkBFIFO1(); rlm@8: FIFO#(MainMemResp) mrespQ <- mkBFIFO1(); rlm@8: rlm@8: Reg#(ReqPtr) nextReq <- mkReg(REQ0); rlm@8: rlm@8: //----------------------------------------------------------- rlm@8: // Some wires rlm@8: rlm@8: let req0avail = req0Q.notEmpty(); rlm@8: let req1avail = req1Q.notEmpty(); rlm@8: rlm@8: //----------------------------------------------------------- rlm@8: // Rules rlm@8: rlm@8: rule chooseReq0 ( req0avail && (!req1avail || (nextReq == REQ0)) ); rlm@8: traceTiny("mkMemArb", "memArb req0",req0Q.first()); rlm@8: rlm@8: // Rewrite tag field if this is a load ... rlm@8: MainMemReq mreq rlm@8: = case ( req0Q.first() ) matches rlm@8: tagged LoadReq .ld : return LoadReq { tag:0, addr:ld.addr }; rlm@8: tagged StoreReq .st : return req0Q.first(); rlm@8: endcase; rlm@8: rlm@8: // Send out the request rlm@8: mreqQ.enq(mreq); rlm@8: nextReq <= REQ1; rlm@8: req0Q.deq(); rlm@8: rlm@8: endrule rlm@8: rlm@8: rule chooseReq1 ( req1avail && (!req0avail || (nextReq == REQ1)) ); rlm@8: traceTiny("mkMemArb", "memArb req1",req1Q.first); rlm@8: rlm@8: // Rewrite tag field if this is a load ... rlm@8: MainMemReq mreq rlm@8: = case ( req1Q.first() ) matches rlm@8: tagged LoadReq .ld : return LoadReq { tag:1, addr:ld.addr }; rlm@8: tagged StoreReq .st : return req1Q.first(); rlm@8: endcase; rlm@8: rlm@8: // Send out the request rlm@8: mreqQ.enq(mreq); rlm@8: nextReq <= REQ0; rlm@8: req1Q.deq(); rlm@8: rlm@8: endrule rlm@8: rlm@8: rule returnResp; rlm@8: traceTiny("mkMemArb", "resp",mrespQ.first()); rlm@8: rlm@8: // Use tag to figure out where to send response rlm@8: mrespQ.deq(); rlm@8: let tag rlm@8: = case ( mrespQ.first() ) matches rlm@8: tagged LoadResp .ld : return ld.tag; rlm@8: tagged StoreResp .st : return st.tag; rlm@8: endcase; rlm@8: rlm@8: if ( tag == 0 ) rlm@8: resp0Q.enq(mrespQ.first()); rlm@8: else rlm@8: resp1Q.enq(mrespQ.first()); rlm@8: rlm@8: endrule rlm@8: rlm@8: //----------------------------------------------------------- rlm@8: // Methods rlm@8: rlm@8: interface Server cache0_server; rlm@8: interface Put request = fifofToPut(req0Q); rlm@8: interface Get response = fifoToGet(resp0Q); rlm@8: endinterface rlm@8: rlm@8: interface Server cache1_server; rlm@8: interface Put request = fifofToPut(req1Q); rlm@8: interface Get response = fifoToGet(resp1Q); rlm@8: endinterface rlm@8: rlm@8: interface Client mmem_client; rlm@8: interface Get request = fifoToGet(mreqQ); rlm@8: interface Put response = fifoToPut(mrespQ); rlm@8: endinterface rlm@8: rlm@8: endmodule rlm@8: rlm@8: