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