message header should not include padding length

// Copyright (c) 2014 Quanta Research Cambridge, Inc.

// 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.

import Vector::*;
import GetPut::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;
import ClientServer::*;
import CtrlMux::*;
import Gearbox::*;
import Clocks::*;

import MIFO::*;
import Pipe::*;
import Portal::*;
import MemTypes::*;
import AddressGenerator::*;
import MemTypes::*;
import MemreadEngine::*;
import MemwriteEngine::*;
import ConnectalMemory::*;

typedef enum {
   Idle,
   HeadRequested,
   TailRequested,
   RequestMessage,
   MessageHeaderRequested,
   MessageRequested,
   Drain,
   UpdateTail,
   UpdateHead,
   UpdateHead2,
   Waiting,
   SendHeader,
   SendMessage,
   SendPadding,
   Stop
   } SharedMemoryPortalState deriving (Bits,Eq);

module mkSharedMemoryRequestPortal#(PipePortal#(numRequests, numIndications, 32) portal,
				    MemreadServer#(64) readEngine,
				    MemwriteServer#(64) writeEngine,
				    Reg#(Bit#(32)) sglIdReg,
				    Reg#(Bool)     readyReg)(SharedMemoryPortal#(64));
      // read the head and tail pointers, if they are different, then read a request
      Reg#(Bit#(32)) reqLimitReg <- mkReg(0);
      Reg#(Bit#(32)) reqHeadReg <- mkReg(0);
      Reg#(Bit#(32)) reqTailReg <- mkReg(0);
      Reg#(Bit#(16)) wordCountReg <- mkReg(0);
      Reg#(Bit#(16)) messageWordsReg <- mkReg(0);
      Reg#(Bit#(16)) methodIdReg <- mkReg(0);
      Reg#(SharedMemoryPortalState) reqState <- mkReg(Idle);

   let verbose = False;

      rule updateReqHeadTail if (reqState == Idle && readyReg);
	 readEngine.cmdServer.request.put(MemengineCmd { sglId: sglIdReg,
							base: 0,
							burstLen: 16,
							len: 16
							});
	 reqState <= HeadRequested;
      endrule

      rule receiveReqHeadTail if (reqState == HeadRequested || reqState == TailRequested);
	 let data <- toGet(readEngine.dataPipe).get();
	 let w0 = data[31:0];
	 let w1 = data[63:32];
	 let head = reqHeadReg;
	 let tail = reqTailReg;
	 if (reqState == HeadRequested) begin
	    reqLimitReg <= w0;
	    reqHeadReg <= w1;
	    head = w1;
	    reqState <= TailRequested;
	 end
	 else begin
	    if (reqTailReg == 0) begin
	       tail = w0;
	       reqTailReg <= tail;
	    end
	    if (tail != reqHeadReg)
	       reqState <= RequestMessage;
	    else
	       reqState <= Idle;
	 end
	 if (verbose)
	    $display("receiveReqHeadTail state=%d w0=%x w1=%x head=%d tail=%d limit=%d", reqState, w0, w1, head, tail, reqLimitReg);
      endrule

      rule requestMessage if (reqState == RequestMessage);
	 Bit#(32) wordCount = reqHeadReg - reqTailReg;
	 if ((reqTailReg & 1) == 1) begin
	    $display("WARNING requestMessage: reqTail=%d is odd.", reqTailReg);
	 end
	 let tail = reqTailReg + wordCount;
	 if (reqHeadReg < reqTailReg) begin
	    $display("requestMessage wrapped: head=%d tail=%d", reqHeadReg, reqTailReg);
	    wordCount = reqLimitReg - reqTailReg;
	    tail = 4;
	 end
	 if (verbose) $display("requestMessage id=%d tail=%h head=%h wordCount=%d", sglIdReg, reqTailReg, reqHeadReg, wordCount);

	 reqTailReg <= tail;
	 wordCountReg <= truncate(wordCount);
	 readEngine.cmdServer.request.put(MemengineCmd {sglId: sglIdReg,
							base: extend(reqTailReg << 2),
							burstLen: 16,
							len: wordCount << 2
							});
	 reqState <= MessageHeaderRequested;
      endrule

      MIFO#(4,1,4,Bit#(32)) readMifo <- mkMIFO();
      rule demuxwords if (readMifo.enqReady());
	 let data <- toGet(readEngine.dataPipe).get();
	 Vector#(2,Bit#(32)) dvec = unpack(data);
	 let enqCount = 2;
	 Vector#(4,Bit#(32)) dvec4;
	 dvec4[0] = dvec[0];
	 dvec4[1] = dvec[1];
	 dvec4[2] = 0;
	 dvec4[3] = 0;
	 readMifo.enq(enqCount, dvec4);
      endrule

      rule receiveMessageHeader if (reqState == MessageHeaderRequested);
	 let vec <- toGet(readMifo).get();
	 let hdr = vec[0];
	 let methodId = hdr[31:16];
	 let messageWords = hdr[15:0];
	 methodIdReg <= methodId;
	 if (verbose)
	    $display("receiveMessageHeader hdr=%x methodId=%x messageWords=%d wordCount=%d", hdr, methodId, messageWords, wordCountReg);
	 wordCountReg <= wordCountReg - 1;
	 messageWordsReg <= messageWords - 1;
	 if (hdr == 0) begin
	    if (wordCountReg == 1)
	       reqState <= UpdateTail;
	    else
	       reqState <= Drain;
	 end
	 else if (wordCountReg == 1)
	    reqState <= UpdateTail;
	 else if (messageWords == 1)
	    reqState <= MessageHeaderRequested;
	 else
	    reqState <= MessageRequested;
      endrule

      rule drain if (reqState == Drain);
	 let vec <- toGet(readMifo).get();
	 if (wordCountReg == 1)
	    reqState <= UpdateTail;
	 wordCountReg <= wordCountReg - 1;
      endrule

      rule receiveMessage if (reqState == MessageRequested);
	 let vec <- toGet(readMifo).get();
	 let data = vec[0];
	 if (verbose)
	    $display("receiveMessage data=%x messageWords=%d wordCount=%d", data, messageWordsReg, wordCountReg);
	 if (methodIdReg != 16'hFFFF)
	    portal.requests[methodIdReg].enq(data);

	 messageWordsReg <= messageWordsReg - 1;
	 wordCountReg <= wordCountReg - 1;
	 if (messageWordsReg == 1)
	    reqState <= MessageHeaderRequested;
	 else if (wordCountReg <= 1)
	    reqState <= UpdateTail;
      endrule

      rule updateTail if (reqState == UpdateTail);
	 if (verbose)
	    $display("updateTail: tail=%d", reqTailReg);
	 // update the tail pointer
	 writeEngine.cmdServer.request.put(MemengineCmd {sglId: sglIdReg,
							 base: 8,
							 len: 8,
							 burstLen: 8
							 });
	 writeEngine.dataPipe.enq(extend(reqTailReg));
	 reqState <= Waiting;
      endrule
      rule waiting if (reqState == Waiting);
	 let done <- writeEngine.cmdServer.response.get();
	 reqState <= Idle;
      endrule

      rule consumeResponse;
	 let response <- readEngine.cmdServer.response.get();
      endrule
endmodule

module mkSharedMemoryIndicationPortal#(PipePortal#(numRequests, numIndications, 32) portal,
				       MemreadServer#(64) readEngine,
				       MemwriteServer#(64) writeEngine,
				       Reg#(Bit#(32)) sglIdReg,
				       Reg#(Bool)     readyReg)(SharedMemoryPortal#(64));
      // read the head and tail pointers, if they are different, then read a request
      Reg#(Bit#(16)) indLimitReg <- mkReg(0);
      Reg#(Bit#(16)) indHeadReg <- mkReg(0);
      Reg#(Bit#(16)) indTailReg <- mkReg(0);
      Reg#(Bit#(16)) wordCountReg <- mkReg(0);
      Reg#(Bit#(16)) messageWordsReg <- mkReg(0);
      Reg#(Bit#(16)) methodIdReg <- mkReg(0);
      Reg#(Bool) paddingReg <- mkReg(False);
      Reg#(SharedMemoryPortalState) indState <- mkReg(Idle);

   let verbose = True;

   function Bool pipeOutNotEmpty(PipeOut#(a) po); return po.notEmpty(); endfunction
   Vector#(numIndications, Bool) readyBits = map(pipeOutNotEmpty, portal.indications);
   Bool      interruptStatus = False;
   Bit#(16)  readyChannel = -1;
   for (Integer i = valueOf(numIndications) - 1; i >= 0; i = i - 1) begin
      if (readyBits[i]) begin
         interruptStatus = True;
         readyChannel = fromInteger(i);
      end
   end

      rule updateIndHeadTail if (indState == Idle && readyReg);
	 readEngine.cmdServer.request.put(MemengineCmd { sglId: sglIdReg,
							base: 0,
							burstLen: 16,
							len: 16
							});
	 indState <= HeadRequested;
      endrule

      rule receiveIndHeadTail if (indState == HeadRequested || indState == TailRequested);
	 let data <- toGet(readEngine.dataPipe).get();
	 let w0 = data[31:0];
	 let w1 = data[63:32];
	 let head = indHeadReg;
	 let tail = indTailReg;
	 if (indState == HeadRequested) begin
	    indLimitReg <= truncate(w0);
	    indHeadReg <= truncate(w1);
	    head = truncate(w1);
	    indState <= TailRequested;
	 end
	 else begin
	    if (indTailReg == 0) begin
	       tail = truncate(w0);
	       indTailReg <= tail;
	    end
	    //if (tail != indHeadReg)
	       indState <= SendHeader;
	    //else
	       //indState <= Idle;
	 end
	 if (verbose)
	    $display("receiveIndHeadTail state=%d w0=%x w1=%x head=%d tail=%d limit=%d", indState, w0, w1, head, tail, indLimitReg);
      endrule

   let defaultClock <- exposeCurrentClock;
   let defaultReset <- exposeCurrentReset;
   Gearbox#(1,2,Bit#(32)) gb <- mk1toNGearbox(defaultClock, defaultReset, defaultClock, defaultReset);
   rule send64bits;
      let v = gb.first;
      gb.deq();
      writeEngine.dataPipe.enq(pack(v));
   endrule
   rule sendHeader if (indState == SendHeader && interruptStatus);
      Bit#(16) messageBits = portal.messageSize(readyChannel);
      Bit#(16) roundup = messageBits[4:0] == 0 ? 0 : 1;
      Bit#(16) numWords = (messageBits >> 5) + roundup;
      Bit#(16) totalWords = numWords + 1;
      if (numWords[0] == 0)
	 totalWords = numWords + 2;
      paddingReg <= numWords[0] == 0;
      Bit#(32) hdr = extend(readyChannel) << 16 | extend(numWords + 1);
      $display("sendHeader hdr=%h messageBits=%d numWords=%d totalWords=%d paddingReg=%d indHeadReg=%h", hdr, messageBits, numWords, totalWords, paddingReg, indHeadReg);

      indHeadReg <= indHeadReg + totalWords;
      messageWordsReg <= numWords;
      methodIdReg <= readyChannel;
      gb.enq(replicate(hdr));
      writeEngine.cmdServer.request.put(MemengineCmd { sglId: sglIdReg,
						      base: extend(indHeadReg) << 2,
						      burstLen: 8,
						      len: extend(totalWords) << 2 });
      indState <= SendMessage;
   endrule
   rule sendMessage if (indState == SendMessage);
      messageWordsReg <= messageWordsReg - 1;
      let v = portal.indications[methodIdReg].first;
      portal.indications[methodIdReg].deq();
      gb.enq(replicate(v));
      $display("sendMessage v=%h messageWords=%d", v, messageWordsReg);

      if (messageWordsReg == 1) begin
	 if (paddingReg)
	    indState <= SendPadding;
	 else
	    indState <= UpdateHead;
      end
   endrule
   rule sendPadding if (indState == SendPadding);
      $display("sendPadding");
      gb.enq(replicate(32'hffff0001));
      indState <= UpdateHead;
   endrule
   rule updateHead if (indState == UpdateHead);
      $display("updateIndHead limit=%d head=%d", indLimitReg, indHeadReg);
      gb.enq(replicate(extend(indLimitReg)));
      writeEngine.cmdServer.request.put(MemengineCmd { sglId: sglIdReg,
						      base: 0 << 2,
						      burstLen: 8,
						      len: 2 << 2 });
      indState <= UpdateHead2;
   endrule
   rule updateHead2 if (indState == UpdateHead2);
      $display("updateIndHead2");
      gb.enq(replicate(extend(indHeadReg)));
      indState <= SendHeader;
   endrule
   rule done;
      let done <- writeEngine.cmdServer.response.get();
   endrule

endmodule

module mkSharedMemoryPortal#(PipePortal#(numRequests, numIndications, 32) portal)(SharedMemoryPortal#(64));

   MemreadEngineV#(64,2,1) readEngine <- mkMemreadEngine();
   MemwriteEngineV#(64,2,1) writeEngine <- mkMemwriteEngine();

   Bool verbose = False;

   Reg#(Bit#(32)) sglIdReg <- mkReg(0);
   Reg#(Bool)     readyReg   <- mkReg(False);

   if (valueOf(numRequests) > 0) begin
      let readPortal <- mkSharedMemoryRequestPortal(portal, readEngine.read_servers[0], writeEngine.write_servers[0], sglIdReg, readyReg);
   end
   else if (valueOf(numIndications) > 0) begin
      let writePortal <- mkSharedMemoryIndicationPortal(portal, readEngine.read_servers[0], writeEngine.write_servers[0], sglIdReg, readyReg);
   end
   interface SharedMemoryPortalConfig cfg;
      method Action setSglId(Bit#(32) id);
	 sglIdReg <= id;
	 readyReg <= True;
      endmethod
   endinterface
   interface MemReadClient  readClient = readEngine.dmaClient;
   interface MemWriteClient writeClient = writeEngine.dmaClient;
   interface ReadOnly interrupt;
   endinterface
endmodule

// Copyright (c) 2014 Quanta Research Cambridge, Inc.

// 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.

import Vector::*;
import GetPut::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;
import ClientServer::*;
import CtrlMux::*;
import Gearbox::*;
import Clocks::*;

import MIFO::*;
import Pipe::*;
import Portal::*;
import MemTypes::*;
import AddressGenerator::*;
import MemTypes::*;
import MemreadEngine::*;
import MemwriteEngine::*;
import ConnectalMemory::*;

typedef enum {
   Idle,
   HeadRequested,
   TailRequested,
   RequestMessage,
   MessageHeaderRequested,
   MessageRequested,
   Drain,
   UpdateTail,
   UpdateHead,
   UpdateHead2,
   Waiting,
   SendHeader,
   SendMessage,
   SendPadding,
   Stop
   } SharedMemoryPortalState deriving (Bits,Eq);

module mkSharedMemoryRequestPortal#(PipePortal#(numRequests, numIndications, 32) portal,
				    MemreadServer#(64) readEngine,
				    MemwriteServer#(64) writeEngine,
				    Reg#(Bit#(32)) sglIdReg,
				    Reg#(Bool)     readyReg)(SharedMemoryPortal#(64));
      // read the head and tail pointers, if they are different, then read a request
      Reg#(Bit#(32)) reqLimitReg <- mkReg(0);
      Reg#(Bit#(32)) reqHeadReg <- mkReg(0);
      Reg#(Bit#(32)) reqTailReg <- mkReg(0);
      Reg#(Bit#(16)) wordCountReg <- mkReg(0);
      Reg#(Bit#(16)) messageWordsReg <- mkReg(0);
      Reg#(Bit#(16)) methodIdReg <- mkReg(0);
      Reg#(SharedMemoryPortalState) reqState <- mkReg(Idle);

   let verbose = False;

      rule updateReqHeadTail if (reqState == Idle && readyReg);
	 readEngine.cmdServer.request.put(MemengineCmd { sglId: sglIdReg,
							base: 0,
							burstLen: 16,
							len: 16
							});
	 reqState <= HeadRequested;
      endrule

      rule receiveReqHeadTail if (reqState == HeadRequested || reqState == TailRequested);
	 let data <- toGet(readEngine.dataPipe).get();
	 let w0 = data[31:0];
	 let w1 = data[63:32];
	 let head = reqHeadReg;
	 let tail = reqTailReg;
	 if (reqState == HeadRequested) begin
	    reqLimitReg <= w0;
	    reqHeadReg <= w1;
	    head = w1;
	    reqState <= TailRequested;
	 end
	 else begin
	    if (reqTailReg == 0) begin
	       tail = w0;
	       reqTailReg <= tail;
	    end
	    if (tail != reqHeadReg)
	       reqState <= RequestMessage;
	    else
	       reqState <= Idle;
	 end
	 if (verbose)
	    $display("receiveReqHeadTail state=%d w0=%x w1=%x head=%d tail=%d limit=%d", reqState, w0, w1, head, tail, reqLimitReg);
      endrule

      rule requestMessage if (reqState == RequestMessage);
	 Bit#(32) wordCount = reqHeadReg - reqTailReg;
	 if ((reqTailReg & 1) == 1) begin
	    $display("WARNING requestMessage: reqTail=%d is odd.", reqTailReg);
	 end
	 let tail = reqTailReg + wordCount;
	 if (reqHeadReg < reqTailReg) begin
	    $display("requestMessage wrapped: head=%d tail=%d", reqHeadReg, reqTailReg);
	    wordCount = reqLimitReg - reqTailReg;
	    tail = 4;
	 end
	 if (verbose) $display("requestMessage id=%d tail=%h head=%h wordCount=%d", sglIdReg, reqTailReg, reqHeadReg, wordCount);

	 reqTailReg <= tail;
	 wordCountReg <= truncate(wordCount);
	 readEngine.cmdServer.request.put(MemengineCmd {sglId: sglIdReg,
							base: extend(reqTailReg << 2),
							burstLen: 16,
							len: wordCount << 2
							});
	 reqState <= MessageHeaderRequested;
      endrule

      MIFO#(4,1,4,Bit#(32)) readMifo <- mkMIFO();
      rule demuxwords if (readMifo.enqReady());
	 let data <- toGet(readEngine.dataPipe).get();
	 Vector#(2,Bit#(32)) dvec = unpack(data);
	 let enqCount = 2;
	 Vector#(4,Bit#(32)) dvec4;
	 dvec4[0] = dvec[0];
	 dvec4[1] = dvec[1];
	 dvec4[2] = 0;
	 dvec4[3] = 0;
	 readMifo.enq(enqCount, dvec4);
      endrule

      rule receiveMessageHeader if (reqState == MessageHeaderRequested);
	 let vec <- toGet(readMifo).get();
	 let hdr = vec[0];
	 let methodId = hdr[31:16];
	 let messageWords = hdr[15:0];
	 methodIdReg <= methodId;
	 if (verbose)
	    $display("receiveMessageHeader hdr=%x methodId=%x messageWords=%d wordCount=%d", hdr, methodId, messageWords, wordCountReg);
	 wordCountReg <= wordCountReg - 1;
	 messageWordsReg <= messageWords - 1;
	 if (hdr == 0) begin
	    if (wordCountReg == 1)
	       reqState <= UpdateTail;
	    else
	       reqState <= Drain;
	 end
	 else if (wordCountReg == 1)
	    reqState <= UpdateTail;
	 else if (messageWords == 1)
	    reqState <= MessageHeaderRequested;
	 else
	    reqState <= MessageRequested;
      endrule

      rule drain if (reqState == Drain);
	 let vec <- toGet(readMifo).get();
	 if (wordCountReg == 1)
	    reqState <= UpdateTail;
	 wordCountReg <= wordCountReg - 1;
      endrule

      rule receiveMessage if (reqState == MessageRequested);
	 let vec <- toGet(readMifo).get();
	 let data = vec[0];
	 if (verbose)
	    $display("receiveMessage data=%x messageWords=%d wordCount=%d", data, messageWordsReg, wordCountReg);
	 if (methodIdReg != 16'hFFFF)
	    portal.requests[methodIdReg].enq(data);

	 messageWordsReg <= messageWordsReg - 1;
	 wordCountReg <= wordCountReg - 1;
	 if (messageWordsReg == 1)
	    reqState <= MessageHeaderRequested;
	 else if (wordCountReg <= 1)
	    reqState <= UpdateTail;
      endrule

      rule updateTail if (reqState == UpdateTail);
	 if (verbose)
	    $display("updateTail: tail=%d", reqTailReg);
	 // update the tail pointer
	 writeEngine.cmdServer.request.put(MemengineCmd {sglId: sglIdReg,
							 base: 8,
							 len: 8,
							 burstLen: 8
							 });
	 writeEngine.dataPipe.enq(extend(reqTailReg));
	 reqState <= Waiting;
      endrule
      rule waiting if (reqState == Waiting);
	 let done <- writeEngine.cmdServer.response.get();
	 reqState <= Idle;
      endrule

      rule consumeResponse;
	 let response <- readEngine.cmdServer.response.get();
      endrule
endmodule

module mkSharedMemoryIndicationPortal#(PipePortal#(numRequests, numIndications, 32) portal,
				       MemreadServer#(64) readEngine,
				       MemwriteServer#(64) writeEngine,
				       Reg#(Bit#(32)) sglIdReg,
				       Reg#(Bool)     readyReg)(SharedMemoryPortal#(64));
      // read the head and tail pointers, if they are different, then read a request
      Reg#(Bit#(16)) indLimitReg <- mkReg(0);
      Reg#(Bit#(16)) indHeadReg <- mkReg(0);
      Reg#(Bit#(16)) indTailReg <- mkReg(0);
      Reg#(Bit#(16)) wordCountReg <- mkReg(0);
      Reg#(Bit#(16)) messageWordsReg <- mkReg(0);
      Reg#(Bit#(16)) methodIdReg <- mkReg(0);
      Reg#(Bool) paddingReg <- mkReg(False);
      Reg#(SharedMemoryPortalState) indState <- mkReg(Idle);

   let verbose = True;

   function Bool pipeOutNotEmpty(PipeOut#(a) po); return po.notEmpty(); endfunction
   Vector#(numIndications, Bool) readyBits = map(pipeOutNotEmpty, portal.indications);
   Bool      interruptStatus = False;
   Bit#(16)  readyChannel = -1;
   for (Integer i = valueOf(numIndications) - 1; i >= 0; i = i - 1) begin
      if (readyBits[i]) begin
         interruptStatus = True;
         readyChannel = fromInteger(i);
      end
   end

      rule updateIndHeadTail if (indState == Idle && readyReg);
	 readEngine.cmdServer.request.put(MemengineCmd { sglId: sglIdReg,
							base: 0,
							burstLen: 16,
							len: 16
							});
	 indState <= HeadRequested;
      endrule

      rule receiveIndHeadTail if (indState == HeadRequested || indState == TailRequested);
	 let data <- toGet(readEngine.dataPipe).get();
	 let w0 = data[31:0];
	 let w1 = data[63:32];
	 let head = indHeadReg;
	 let tail = indTailReg;
	 if (indState == HeadRequested) begin
	    indLimitReg <= truncate(w0);
	    indHeadReg <= truncate(w1);
	    head = truncate(w1);
	    indState <= TailRequested;
	 end
	 else begin
	    if (indTailReg == 0) begin
	       tail = truncate(w0);
	       indTailReg <= tail;
	    end
	    //if (tail != indHeadReg)
	       indState <= SendHeader;
	    //else
	       //indState <= Idle;
	 end
	 if (verbose)
	    $display("receiveIndHeadTail state=%d w0=%x w1=%x head=%d tail=%d limit=%d", indState, w0, w1, head, tail, indLimitReg);
      endrule

   let defaultClock <- exposeCurrentClock;
   let defaultReset <- exposeCurrentReset;
   Gearbox#(1,2,Bit#(32)) gb <- mk1toNGearbox(defaultClock, defaultReset, defaultClock, defaultReset);
   rule send64bits;
      let v = gb.first;
      gb.deq();
      writeEngine.dataPipe.enq(pack(v));
   endrule
   rule sendHeader if (indState == SendHeader && interruptStatus);
      Bit#(16) messageBits = portal.messageSize(readyChannel);
      Bit#(16) roundup = messageBits[4:0] == 0 ? 0 : 1;
      Bit#(16) numWords = (messageBits >> 5) + roundup;
      Bit#(16) totalWords = numWords + 1;
      if (numWords[0] == 0)
	 totalWords = numWords + 2;
      paddingReg <= numWords[0] == 0;
      Bit#(32) hdr = extend(readyChannel) << 16 | extend(totalWords);
      $display("sendHeader hdr=%h messageBits=%d numWords=%d totalWords=%d paddingReg=%d indHeadReg=%h", hdr, messageBits, numWords, totalWords, paddingReg, indHeadReg);

      indHeadReg <= indHeadReg + totalWords;
      messageWordsReg <= numWords;
      methodIdReg <= readyChannel;
      gb.enq(replicate(hdr));
      writeEngine.cmdServer.request.put(MemengineCmd { sglId: sglIdReg,
						      base: extend(indHeadReg) << 2,
						      burstLen: 8,
						      len: extend(totalWords) << 2 });
      indState <= SendMessage;
   endrule
   rule sendMessage if (indState == SendMessage);
      messageWordsReg <= messageWordsReg - 1;
      let v = portal.indications[methodIdReg].first;
      portal.indications[methodIdReg].deq();
      gb.enq(replicate(v));
      $display("sendMessage v=%h messageWords=%d", v, messageWordsReg);

      if (messageWordsReg == 1) begin
	 if (paddingReg)
	    indState <= SendPadding;
	 else
	    indState <= UpdateHead;
      end
   endrule
   rule sendPadding if (indState == SendPadding);
      $display("sendPadding");
      gb.enq(replicate(32'hffff0001));
      indState <= UpdateHead;
   endrule
   rule updateHead if (indState == UpdateHead);
      $display("updateIndHead limit=%d head=%d", indLimitReg, indHeadReg);
      gb.enq(replicate(extend(indLimitReg)));
      writeEngine.cmdServer.request.put(MemengineCmd { sglId: sglIdReg,
						      base: 0 << 2,
						      burstLen: 8,
						      len: 2 << 2 });
      indState <= UpdateHead2;
   endrule
   rule updateHead2 if (indState == UpdateHead2);
      $display("updateIndHead2");
      gb.enq(replicate(extend(indHeadReg)));
      indState <= SendHeader;
   endrule
   rule done;
      let done <- writeEngine.cmdServer.response.get();
   endrule

endmodule

module mkSharedMemoryPortal#(PipePortal#(numRequests, numIndications, 32) portal)(SharedMemoryPortal#(64));

   MemreadEngineV#(64,2,1) readEngine <- mkMemreadEngine();
   MemwriteEngineV#(64,2,1) writeEngine <- mkMemwriteEngine();

   Bool verbose = False;

   Reg#(Bit#(32)) sglIdReg <- mkReg(0);
   Reg#(Bool)     readyReg   <- mkReg(False);

   if (valueOf(numRequests) > 0) begin
      let readPortal <- mkSharedMemoryRequestPortal(portal, readEngine.read_servers[0], writeEngine.write_servers[0], sglIdReg, readyReg);
   end
   else if (valueOf(numIndications) > 0) begin
      let writePortal <- mkSharedMemoryIndicationPortal(portal, readEngine.read_servers[0], writeEngine.write_servers[0], sglIdReg, readyReg);
   end
   interface SharedMemoryPortalConfig cfg;
      method Action setSglId(Bit#(32) id);
	 sglIdReg <= id;
	 readyReg <= True;
      endmethod
   endinterface
   interface MemReadClient  readClient = readEngine.dmaClient;
   interface MemWriteClient writeClient = writeEngine.dmaClient;
   interface ReadOnly interrupt;
   endinterface
endmodule


use mkPlatform

use mkPlatform

// Copyright (c) 2017 Connectal Project

// 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.

import ConnectalConfig::*;
import Vector            :: *;
import GetPut::*;
import Connectable::*;
import Portal            :: *;
import Platform          :: *;
import Top               :: *;
import HostInterface     :: *;
import Pipe::*;
import CnocPortal::*;
import MemTypes:: *;
import MMU:: *;
import MemServer:: *;
import MMURequest::*;
import MMUIndication::*;
import MemServerIndication::*;
import MemServerRequest::*;
import SimDma::*;
import IfcNames::*;
import BuildVector::*;
import Axi4MasterSlave::*;
import AxiBits::*;
import AxiDma::*;
import PS8LIB::*; // mkPhysMemSlave
import FIFOF::*;
import CFFIFO::*;

`include "ConnectalProjectConfig.bsv"

`ifdef PinTypeInclude
import `PinTypeInclude::*;
`endif
`ifdef PinType
typedef `PinType PinType;
`else
typedef Empty PinType;
`endif

(* always_enabled, always_ready *)
interface AwsF1ClSh;
   method Bit#(1) flr_done();
   method Bit#(32) status0();
   method Bit#(32) status1();
   method Bit#(32) id0();
   method Bit#(32) id1();
   method Bit#(16) status_vled();
endinterface

(* always_enabled, always_ready *)
interface AwsF1ShCl;
   (* prefix="" *)
   method Action flr_assert(Bit#(1) flr_assert);
   (* prefix="" *)
   method Action ctl0(Bit#(32) ctl0);
   (* prefix="" *)
   method Action ctl1(Bit#(32) ctl1);
   (* prefix="" *)
   method Action status_vdip(Bit#(16) status_vdip);
   (* prefix="" *)
   method Action pwr_state(Bit#(2) pwr_state);
endinterface

(* always_ready, always_enabled *)
interface AwsF1Top;
   interface PinType pins;
   interface AwsF1ShCl sh_cl;
   interface AwsF1ClSh cl_sh;
   interface Axi4SlaveBits#(64,512,6,Empty) dmasink;
   interface Axi4SlaveLiteBits#(32,32) ocl;
   interface Axi4SlaveLiteBits#(32,32) sda;
   interface Axi4SlaveLiteBits#(32,32) bar1;
   interface Axi4MasterBits#(PhysAddrWidth,512,16,AwsF1Extra) pcim;
endinterface

module mkAxi4SlaveLiteBitsFromPhysMemSlave#(PhysMemSlave#(addrWidth,dataWidth) slave)
       (Axi4SlaveLiteBits#(axiaddrWidth,dataWidth)) provisos (Div#(dataWidth,8,burstLen),Add#(addrWidth,a__,axiaddrWidth));

    let burstLen = fromInteger(valueOf(burstLen));

    Wire#(Bit#(addrWidth)) araddrWire <- mkDWire(0);
    Wire#(Bit#(1)) arvalidWire <- mkDWire(0);
    Wire#(Bit#(1)) rreadyWire <- mkDWire(0);
    Wire#(Bit#(dataWidth)) rdataWire <- mkDWire(0);

    Wire#(Bit#(addrWidth)) awaddrWire <- mkDWire(0);
    Wire#(Bit#(1)) awvalidWire <- mkDWire(0);
    Wire#(Bit#(1)) wvalidWire <- mkDWire(0);
    Wire#(Bit#(dataWidth)) wdataWire <- mkDWire(0);
    Wire#(Bit#(1)) breadyWire <- mkDWire(0);

    FIFOF#(PhysMemRequest#(addrWidth,dataWidth)) arFifo <- mkCFFIFOF();
    FIFOF#(PhysMemRequest#(addrWidth,dataWidth)) awFifo <- mkCFFIFOF();
    FIFOF#(MemData#(dataWidth)) rdataFifo <- mkCFFIFOF();
    FIFOF#(MemData#(dataWidth)) wdataFifo <- mkCFFIFOF();
    FIFOF#(Bit#(MemTagSize)) brespFifo <- mkCFFIFOF();

    rule ar_rule if (arvalidWire == 1 && arFifo.notFull());
       let req = PhysMemRequest {addr: araddrWire, burstLen: burstLen, tag: 0 };
       arFifo.enq(req);
    endrule
    rule ar_to_slave;
       let req <- toGet(arFifo).get();
       slave.read_server.readReq.put(req);
    endrule

    rule aw_rule if (awvalidWire == 1 && awFifo.notFull());
       let req = PhysMemRequest {addr: awaddrWire, burstLen: burstLen, tag: 0 };
       awFifo.enq(req);
    endrule
    rule aw_to_slave;
       let req <- toGet(awFifo).get();
       slave.write_server.writeReq.put(req);
    endrule

    rule r_rule if (rreadyWire == 1 && rdataFifo.notEmpty());
       rdataFifo.deq();
    endrule
    rule rdata_rule;
       rdataWire <= rdataFifo.first.data;
    endrule
    rule rdata_from_slave;
       let mdata <- slave.read_server.readData.get();
       rdataFifo.enq(mdata);
    endrule

    rule wdata_rule if (wvalidWire == 1 && wdataFifo.notFull());
       wdataFifo.enq(MemData { data: wdataWire, tag: 0, last: True });
    endrule
    rule wdata_to_slave;
       let mdata <- toGet(wdataFifo).get();
       slave.write_server.writeData.put(mdata);
    endrule

    rule b_rule if (breadyWire == 1 && brespFifo.notEmpty());
       brespFifo.deq();
    endrule
    rule bresp_from_slave;
       let done <- slave.write_server.writeDone.get();
       brespFifo.enq(done);
    endrule

    method Action      araddr(Bit#(axiaddrWidth) v);
       araddrWire <= truncate(v);
    endmethod
    method Bit#(1)     arready();
       return pack(arFifo.notFull());
    endmethod
    method Action      arvalid(Bit#(1) v);
       arvalidWire <= v;
    endmethod
    method Action      awaddr(Bit#(axiaddrWidth) v);
       awaddrWire <= truncate(v);
    endmethod
    method Bit#(1)     awready();
       return pack(awFifo.notFull());
    endmethod
    method Action      awvalid(Bit#(1) v);
       awvalidWire <= v;
    endmethod
    method Action      bready(Bit#(1) v);
       breadyWire <= v;
    endmethod
    method Bit#(2)     bresp();
       return 0; // brespFifo.first();
    endmethod
    method Bit#(1)     bvalid();
       return pack(brespFifo.notEmpty());
    endmethod
    method Bit#(dataWidth)     rdata();
       return rdataWire;
    endmethod
    method Action      rready(Bit#(1) v);
       rreadyWire <= v;
    endmethod
    method Bit#(2)     rresp();
       return 0;
    endmethod
    method Bit#(1)     rvalid();
      return pack(rdataFifo.notEmpty);
    endmethod
    method Action      wdata(Bit#(dataWidth) v);
       wdataWire <= v;
    endmethod
    method Bit#(1)     wready();
       return pack(wdataFifo.notFull());
    endmethod
    method Action      wvalid(Bit#(1) v);
       wvalidWire <= v;
    endmethod
endmodule

(* no_default_clock, no_default_reset, clock_prefix="", reset_prefix="" *)
module mkAwsF1Top#(Clock clk_main_a0, Clock clk_extra_a1, Clock clk_extra_a2, Clock clk_extra_a3,
       Clock  clk_extra_b0, Clock clk_extra_b1, Clock clk_extra_c0, Clock clk_extra_c1,
       Reset kernel_rst_n, Reset rst_main_n
       )(AwsF1Top);

   Clock defaultClock = clk_main_a0;
   Reset defaultReset = rst_main_n;
   Clock derivedClock = clk_main_a0;
   Reset derivedReset = rst_main_n;

   XsimHost host <- mkXsimHost(clk_main_a0, rst_main_n, clk_main_a0);
   let top <- mkConnectalTop(
`ifdef IMPORT_HOSTIF
       host,
`else
`ifdef IMPORT_HOST_CLOCKS // enables synthesis boundary
       derivedClock, derivedReset,
`else
// otherwise no params
`endif
`endif
	clocked_by defaultClock, reset_by defaultReset
       );

   let platform <- mkPlatform(vec(top), clocked_by defaultClock, reset_by defaultReset);

   Axi4SlaveLiteBits#(32,32) oclSlave <- mkAxi4SlaveLiteBitsFromPhysMemSlave(platform.slave, clocked_by defaultClock, reset_by defaultReset);

   Vector#(NumberOfMasters, Axi4Master#(PhysAddrWidth,DataBusWidth,MemTagSize)) axiMasters
       <- mapM(mkAxi4DmaMaster, platform.masters, clocked_by defaultClock, reset_by defaultReset);
   Axi4MasterBits#(PhysAddrWidth,512,16,AwsF1Extra) masterBits
       <- mkAxi4MasterBits(axiMasters[0], clocked_by defaultClock, reset_by defaultReset);

   interface AwsF1ClSh cl_sh;
      method id0 = 32'hF000_1D0F; // 32'hc100_1be7;
      method id1 = 32'h1D51_FEDD; // 32'hc101_1be7;
   endinterface

   interface ocl = oclSlave;
   interface pcim = masterBits;

`ifdef PinType
   interface pins = top.pins;
`endif
endmodule

// Copyright (c) 2017 Connectal Project

// 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.

import ConnectalConfig::*;
import Vector            :: *;
import GetPut::*;
import Connectable::*;
import Portal            :: *;
import Top               :: *;
import HostInterface     :: *;
import Pipe::*;
import CnocPortal::*;
import MemTypes:: *;
import MMU:: *;
import MemServer:: *;
import MMURequest::*;
import MMUIndication::*;
import MemServerIndication::*;
import MemServerRequest::*;
import SimDma::*;
import IfcNames::*;
import BuildVector::*;
import Axi4MasterSlave::*;
import AxiBits::*;
import AxiDma::*;
import PS8LIB::*; // mkPhysMemSlave
import FIFOF::*;
import CFFIFO::*;

`include "ConnectalProjectConfig.bsv"

`ifdef PinTypeInclude
import `PinTypeInclude::*;
`endif
`ifdef PinType
typedef `PinType PinType;
`else
typedef Empty PinType;
`endif

(* always_enabled, always_ready *)
interface AwsF1ClSh;
   method Bit#(1) flr_done();
   method Bit#(32) status0();
   method Bit#(32) status1();
   method Bit#(32) id0();
   method Bit#(32) id1();
   method Bit#(16) status_vled();
endinterface

(* always_enabled, always_ready *)
interface AwsF1ShCl;
   (* prefix="" *)
   method Action flr_assert(Bit#(1) flr_assert);
   (* prefix="" *)
   method Action ctl0(Bit#(32) ctl0);
   (* prefix="" *)
   method Action ctl1(Bit#(32) ctl1);
   (* prefix="" *)
   method Action status_vdip(Bit#(16) status_vdip);
   (* prefix="" *)
   method Action pwr_state(Bit#(2) pwr_state);
endinterface

(* always_ready, always_enabled *)
interface AwsF1Top;
   interface PinType pins;
   interface AwsF1ShCl sh_cl;
   interface AwsF1ClSh cl_sh;
   interface Axi4SlaveBits#(64,512,6,Empty) dmasink;
   interface Axi4SlaveLiteBits#(32,32) ocl;
   interface Axi4SlaveLiteBits#(32,32) sda;
   interface Axi4SlaveLiteBits#(32,32) bar1;
   interface Axi4MasterBits#(PhysAddrWidth,512,16,AwsF1Extra) pcim;
endinterface

module mkAxi4SlaveLiteBitsFromPhysMemSlave#(PhysMemSlave#(addrWidth,dataWidth) slave)
       (Axi4SlaveLiteBits#(axiaddrWidth,dataWidth)) provisos (Div#(dataWidth,8,burstLen),Add#(addrWidth,a__,axiaddrWidth));

    let burstLen = fromInteger(valueOf(burstLen));

    Wire#(Bit#(addrWidth)) araddrWire <- mkDWire(0);
    Wire#(Bit#(1)) arvalidWire <- mkDWire(0);
    Wire#(Bit#(1)) rreadyWire <- mkDWire(0);
    Wire#(Bit#(dataWidth)) rdataWire <- mkDWire(0);

    Wire#(Bit#(addrWidth)) awaddrWire <- mkDWire(0);
    Wire#(Bit#(1)) awvalidWire <- mkDWire(0);
    Wire#(Bit#(1)) wvalidWire <- mkDWire(0);
    Wire#(Bit#(dataWidth)) wdataWire <- mkDWire(0);
    Wire#(Bit#(1)) breadyWire <- mkDWire(0);

    FIFOF#(PhysMemRequest#(addrWidth,dataWidth)) arFifo <- mkCFFIFOF();
    FIFOF#(PhysMemRequest#(addrWidth,dataWidth)) awFifo <- mkCFFIFOF();
    FIFOF#(MemData#(dataWidth)) rdataFifo <- mkCFFIFOF();
    FIFOF#(MemData#(dataWidth)) wdataFifo <- mkCFFIFOF();
    FIFOF#(Bit#(MemTagSize)) brespFifo <- mkCFFIFOF();

    rule ar_rule if (arvalidWire == 1 && arFifo.notFull());
       let req = PhysMemRequest {addr: araddrWire, burstLen: burstLen, tag: 0 };
       arFifo.enq(req);
    endrule
    rule ar_to_slave;
       let req <- toGet(arFifo).get();
       slave.read_server.readReq.put(req);
    endrule

    rule aw_rule if (awvalidWire == 1 && awFifo.notFull());
       let req = PhysMemRequest {addr: awaddrWire, burstLen: burstLen, tag: 0 };
       awFifo.enq(req);
    endrule
    rule aw_to_slave;
       let req <- toGet(awFifo).get();
       slave.write_server.writeReq.put(req);
    endrule

    rule r_rule if (rreadyWire == 1 && rdataFifo.notEmpty());
       rdataFifo.deq();
    endrule
    rule rdata_rule;
       rdataWire <= rdataFifo.first.data;
    endrule
    rule rdata_from_slave;
       let mdata <- slave.read_server.readData.get();
       rdataFifo.enq(mdata);
    endrule

    rule wdata_rule if (wvalidWire == 1 && wdataFifo.notFull());
       wdataFifo.enq(MemData { data: wdataWire, tag: 0, last: True });
    endrule
    rule wdata_to_slave;
       let mdata <- toGet(wdataFifo).get();
       slave.write_server.writeData.put(mdata);
    endrule

    rule b_rule if (breadyWire == 1 && brespFifo.notEmpty());
       brespFifo.deq();
    endrule
    rule bresp_from_slave;
       let done <- slave.write_server.writeDone.get();
       brespFifo.enq(done);
    endrule

    method Action      araddr(Bit#(axiaddrWidth) v);
       araddrWire <= truncate(v);
    endmethod
    method Bit#(1)     arready();
       return pack(arFifo.notFull());
    endmethod
    method Action      arvalid(Bit#(1) v);
       arvalidWire <= v;
    endmethod
    method Action      awaddr(Bit#(axiaddrWidth) v);
       awaddrWire <= truncate(v);
    endmethod
    method Bit#(1)     awready();
       return pack(awFifo.notFull());
    endmethod
    method Action      awvalid(Bit#(1) v);
       awvalidWire <= v;
    endmethod
    method Action      bready(Bit#(1) v);
       breadyWire <= v;
    endmethod
    method Bit#(2)     bresp();
       return 0; // brespFifo.first();
    endmethod
    method Bit#(1)     bvalid();
       return pack(brespFifo.notEmpty());
    endmethod
    method Bit#(dataWidth)     rdata();
       return rdataWire;
    endmethod
    method Action      rready(Bit#(1) v);
       rreadyWire <= v;
    endmethod
    method Bit#(2)     rresp();
       return 0;
    endmethod
    method Bit#(1)     rvalid();
      return pack(rdataFifo.notEmpty);
    endmethod
    method Action      wdata(Bit#(dataWidth) v);
       wdataWire <= v;
    endmethod
    method Bit#(1)     wready();
       return pack(wdataFifo.notFull());
    endmethod
    method Action      wvalid(Bit#(1) v);
       wvalidWire <= v;
    endmethod
endmodule

(* no_default_clock, no_default_reset, clock_prefix="", reset_prefix="" *)
module mkAwsF1Top#(Clock clk_main_a0, Clock clk_extra_a1, Clock clk_extra_a2, Clock clk_extra_a3,
       Clock  clk_extra_b0, Clock clk_extra_b1, Clock clk_extra_c0, Clock clk_extra_c1,
       Reset kernel_rst_n, Reset rst_main_n
       )(AwsF1Top);

   Clock defaultClock = clk_main_a0;
   Reset defaultReset = rst_main_n;
   Clock derivedClock = clk_main_a0;
   Reset derivedReset = rst_main_n;

   XsimHost host <- mkXsimHost(clk_main_a0, rst_main_n, clk_main_a0);
   let top <- mkConnectalTop(
`ifdef IMPORT_HOSTIF
       host,
`else
`ifdef IMPORT_HOST_CLOCKS // enables synthesis boundary
       derivedClock, derivedReset,
`else
// otherwise no params
`endif
`endif
	clocked_by defaultClock, reset_by defaultReset
       );

   MMUIndicationOutput lMMUIndicationOutput <- mkMMUIndicationOutput(clocked_by defaultClock, reset_by defaultReset);
   MMURequestInput lMMURequestInput <- mkMMURequestInput(clocked_by defaultClock, reset_by defaultReset);
   MMU#(PhysAddrWidth) lMMU <- mkMMU(0,True, lMMUIndicationOutput.ifc, clocked_by defaultClock, reset_by defaultReset);
   mkConnection(lMMURequestInput.pipes, lMMU.request, clocked_by defaultClock, reset_by defaultReset);

   MemServerIndicationOutput lMemServerIndicationOutput <- mkMemServerIndicationOutput(clocked_by defaultClock, reset_by defaultReset);
   MemServerRequestInput lMemServerRequestInput <- mkMemServerRequestInput(clocked_by defaultClock, reset_by defaultReset);
   MemServer::MemServer#(PhysAddrWidth,DataBusWidth,NumberOfMasters) lMemServer <- mkMemServer(top.readers, top.writers, cons(lMMU,nil), lMemServerIndicationOutput.ifc, clocked_by defaultClock, reset_by defaultReset);
   mkConnection(lMemServerRequestInput.pipes, lMemServer.request, clocked_by defaultClock, reset_by defaultReset);

   let lMMUIndicationOutputNoc <- mkPortalMsgIndication(extend(pack(PlatformIfcNames_MMUIndicationH2S)), lMMUIndicationOutput.portalIfc.indications, lMMUIndicationOutput.portalIfc.messageSize, clocked_by defaultClock, reset_by defaultReset);
   let lMMURequestInputNoc <- mkPortalMsgRequest(extend(pack(PlatformIfcNames_MMURequestS2H)), lMMURequestInput.portalIfc.requests, clocked_by defaultClock, reset_by defaultReset);
   let lMemServerIndicationOutputNoc <- mkPortalMsgIndication(extend(pack(PlatformIfcNames_MemServerIndicationH2S)), lMemServerIndicationOutput.portalIfc.indications, lMemServerIndicationOutput.portalIfc.messageSize, clocked_by defaultClock, reset_by defaultReset);
   let lMemServerRequestInputNoc <- mkPortalMsgRequest(extend(pack(PlatformIfcNames_MemServerRequestS2H)), lMemServerRequestInput.portalIfc.requests, clocked_by defaultClock, reset_by defaultReset);

   Axi4SlaveLiteBits#(32,32) oclSlave <- mkAxi4SlaveLiteBitsFromPhysMemSlave(top.slave, clocked_by defaultClock, reset_by defaultReset);

   Vector#(NumberOfMasters, Axi4Master#(PhysAddrWidth,DataBusWidth,MemTagSize)) axiMasters
       <- mapM(mkAxi4DmaMaster, lMemServer.masters, clocked_by defaultClock, reset_by defaultReset);
   Axi4MasterBits#(PhysAddrWidth,512,16,AwsF1Extra) masterBits
       <- mkAxi4MasterBits(axiMasters[0], clocked_by defaultClock, reset_by defaultReset);

   interface AwsF1ClSh cl_sh;
      method id0 = 32'hF000_1D0F; // 32'hc100_1be7;
      method id1 = 32'h1D51_FEDD; // 32'hc101_1be7;
   endinterface

   interface ocl = oclSlave;
   interface pcim = masterBits;

`ifdef PinType
   interface pins = top.pins;
`endif
endmodule


Implicit guards were failing in DMA read/write buffers, so made them explicit

Change-Id: I91648f491f0ac9816a7b48ee42cd0df8ed5b8999

// Copyright (c) 2013 Quanta Research Cambridge, Inc.

// 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.

import BRAM::*;
import FIFO::*;
import Vector::*;
import Gearbox::*;
import FIFOF::*;
import SpecialFIFOs::*;

import BRAMFIFOFLevel::*;
import GetPut::*;
import Dma::*;

function ObjectReadClient#(dataWidth) orc(DmaReadBuffer#(dataWidth,bufferDepth) rb) = rb.dmaClient;
function ObjectWriteClient#(dataWidth) owc(DmaWriteBuffer#(dataWidth,bufferDepth) wb) = wb.dmaClient;
function ObjectReadServer#(dataWidth) ors(DmaReadBuffer#(dataWidth,bufferDepth) rb) = rb.dmaServer;
function ObjectWriteServer#(dataWidth) ows(DmaWriteBuffer#(dataWidth,bufferDepth) wb) = wb.dmaServer;

//
// @brief A buffer for reading from a bus of width dataWidth.
//
// @param dataWidth The number of bits in the bus.
// @param bufferDepth The depth of the internal buffer
//
interface DmaReadBuffer#(numeric type dataWidth, numeric type bufferDepth);
   interface ObjectReadServer #(dataWidth) dmaServer;
   interface ObjectReadClient#(dataWidth) dmaClient;
endinterface

//
// @brief A buffer for writing to a bus of width dataWidth.
//
// @param dataWidth The number of bits in the bus.
// @param bufferDepth The depth of the internal buffer
//
interface DmaWriteBuffer#(numeric type dataWidth, numeric type bufferDepth);
   interface ObjectWriteServer#(dataWidth) dmaServer;
   interface ObjectWriteClient#(dataWidth) dmaClient;
endinterface

//
// @brief Makes a Dma buffer for reading wordSize words from memory.
//
// @param dataWidth The width of the bus in bits.
// @param bufferDepth The depth of the internal buffer
//
module mkDmaReadBuffer(DmaReadBuffer#(dataWidth, bufferDepth))
   provisos(Add#(b__, TAdd#(1,TLog#(bufferDepth)), 8),
	    Div#(dataWidth,8,dataWidthBytes),
	    Mul#(dataWidthBytes,8,dataWidth),
	    Log#(dataWidthBytes,beatShift));

   FIFO#(ObjectData#(dataWidth))  readBuffer <- mkSizedFIFO(valueOf(bufferDepth));
   FIFOF#(ObjectRequest)        reqOutstanding <- mkFIFOF();
   Ratchet#(TAdd#(1,TLog#(bufferDepth))) availableBuffers <- mkRatchet(fromInteger(valueOf(bufferDepth)));
   let beat_shift = fromInteger(valueOf(beatShift));

   FIFOF#(Bool) hasEnoughCapacity <- mkFIFOF();
   rule updateReady;
      Bit#(TAdd#(1,TLog#(bufferDepth))) requested = truncate(reqOutstanding.first.burstLen>>beat_shift);
      Bool ready = (unpack(truncate(reqOutstanding.first.burstLen>>beat_shift)) <= availableBuffers.read());
      if (ready) begin
	 hasEnoughCapacity.enq(True);
      end
   endrule

   // only issue the readRequest when sufficient buffering is available.  This includes the buffering we have already committed.
   interface ObjectReadServer dmaServer;
      interface Put readReq = toPut(reqOutstanding);
      interface Get readData;
	 method ActionValue#(ObjectData#(dataWidth)) get();
	    availableBuffers.increment(1);
	    let resp <- toGet(readBuffer).get();
	    return resp;
	 endmethod
      endinterface
   endinterface
   interface ObjectReadClient dmaClient;
      interface Get readReq;
	 method ActionValue#(ObjectRequest) get if (hasEnoughCapacity.notEmpty);
	    hasEnoughCapacity.deq();
	    reqOutstanding.deq;
	    availableBuffers.decrement(unpack(truncate(reqOutstanding.first.burstLen>>beat_shift)));
	    return reqOutstanding.first;
	 endmethod
      endinterface
      interface Put readData;
	 method Action put(ObjectData#(dataWidth) x);
	    readBuffer.enq(x);
	 endmethod
      endinterface
   endinterface
endmodule

//
// @brief Makes a Dma channel for writing wordSize words from memory.
//
// @param dataWidth The width of the bus in bits.
// @param bufferDepth The depth of the internal buffer
//
module mkDmaWriteBuffer(DmaWriteBuffer#(dataWidth, bufferDepth))
   provisos(Add#(b__, TAdd#(1, TLog#(bufferDepth)), 8),
	    Div#(dataWidth,8,dataWidthBytes),
	    Mul#(dataWidthBytes,8,dataWidth),
	    Log#(dataWidthBytes,beatShift));

   FIFO#(ObjectData#(dataWidth)) writeBuffer <- mkSizedFIFO(valueOf(bufferDepth));
   FIFOF#(ObjectRequest)        reqOutstanding <- mkFIFOF();
   FIFOF#(Bit#(6))                        doneTags <- mkFIFOF();
   Ratchet#(TAdd#(1,TLog#(bufferDepth))) availableWords <- mkRatchet(fromInteger(valueOf(bufferDepth)));
   let beat_shift = fromInteger(valueOf(beatShift));

   FIFOF#(Bool) hasEnoughCapacity <- mkFIFOF();
   rule updateReady;
      Bit#(TAdd#(1,TLog#(bufferDepth))) requested = truncate(reqOutstanding.first.burstLen>>beat_shift);
      if (unpack(truncate(reqOutstanding.first.burstLen>>beat_shift)) <= availableWords.read())
	 hasEnoughCapacity.enq(True);
   endrule

   // only issue the writeRequest when sufficient data is available.  This includes the data we have already committed.
   interface ObjectWriteServer dmaServer;
      interface Put writeReq = toPut(reqOutstanding);
      interface Put writeData;
	 method Action put(ObjectData#(dataWidth) d);
	    writeBuffer.enq(d);
	    availableWords.increment(1);
	 endmethod
      endinterface
      interface Get writeDone = toGet(doneTags);
   endinterface
   interface ObjectWriteClient dmaClient;
      interface Get writeReq;
	 method ActionValue#(ObjectRequest) get if (hasEnoughCapacity.notEmpty());
	    hasEnoughCapacity.deq();
	    reqOutstanding.deq;
	    availableWords.decrement(unpack(truncate(reqOutstanding.first.burstLen>>beat_shift)));
	    return reqOutstanding.first;
	 endmethod
      endinterface
      interface Get writeData;
	 method ActionValue#(ObjectData#(dataWidth)) get();
	    writeBuffer.deq;
	    return writeBuffer.first;
	 endmethod
      endinterface
      interface Put writeDone = toPut(doneTags);
   endinterface
endmodule

// Copyright (c) 2013 Quanta Research Cambridge, Inc.

// 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.

import BRAM::*;
import FIFO::*;
import Vector::*;
import Gearbox::*;
import FIFOF::*;
import SpecialFIFOs::*;

import BRAMFIFOFLevel::*;
import GetPut::*;
import Dma::*;

function ObjectReadClient#(dataWidth) orc(DmaReadBuffer#(dataWidth,bufferDepth) rb) = rb.dmaClient;
function ObjectWriteClient#(dataWidth) owc(DmaWriteBuffer#(dataWidth,bufferDepth) wb) = wb.dmaClient;
function ObjectReadServer#(dataWidth) ors(DmaReadBuffer#(dataWidth,bufferDepth) rb) = rb.dmaServer;
function ObjectWriteServer#(dataWidth) ows(DmaWriteBuffer#(dataWidth,bufferDepth) wb) = wb.dmaServer;

//
// @brief A buffer for reading from a bus of width dataWidth.
//
// @param dataWidth The number of bits in the bus.
// @param bufferDepth The depth of the internal buffer
//
interface DmaReadBuffer#(numeric type dataWidth, numeric type bufferDepth);
   interface ObjectReadServer #(dataWidth) dmaServer;
   interface ObjectReadClient#(dataWidth) dmaClient;
endinterface

//
// @brief A buffer for writing to a bus of width dataWidth.
//
// @param dataWidth The number of bits in the bus.
// @param bufferDepth The depth of the internal buffer
//
interface DmaWriteBuffer#(numeric type dataWidth, numeric type bufferDepth);
   interface ObjectWriteServer#(dataWidth) dmaServer;
   interface ObjectWriteClient#(dataWidth) dmaClient;
endinterface

//
// @brief Makes a Dma buffer for reading wordSize words from memory.
//
// @param dataWidth The width of the bus in bits.
// @param bufferDepth The depth of the internal buffer
//
module mkDmaReadBuffer(DmaReadBuffer#(dataWidth, bufferDepth))
   provisos(Add#(b__, TAdd#(1,TLog#(bufferDepth)), 8),
	    Div#(dataWidth,8,dataWidthBytes),
	    Mul#(dataWidthBytes,8,dataWidth),
	    Log#(dataWidthBytes,beatShift));

   FIFOFLevel#(ObjectData#(dataWidth),bufferDepth)  readBuffer <- mkFIFOFLevel;
   FIFOF#(ObjectRequest)        reqOutstanding <- mkFIFOF();
   Ratchet#(TAdd#(1,TLog#(bufferDepth))) availableBuffers <- mkRatchet(fromInteger(valueOf(bufferDepth)));
   let beat_shift = fromInteger(valueOf(beatShift));

   FIFO#(Bool) readyToGet <- mkFIFO();
   rule updateReady;
      readyToGet.enq(unpack(truncate(reqOutstanding.first.burstLen>>beat_shift)) <= availableBuffers.read());
   endrule

   // only issue the readRequest when sufficient buffering is available.  This includes the buffering we have already committed.
   interface ObjectReadServer dmaServer;
      interface Put readReq = toPut(reqOutstanding);
      interface Get readData;
	 method ActionValue#(ObjectData#(dataWidth)) get();
	    availableBuffers.increment(1);
	    let resp <- toGet(readBuffer).get();
	    return resp;
	 endmethod
      endinterface
   endinterface
   interface ObjectReadClient dmaClient;
      interface Get readReq;
	 method ActionValue#(ObjectRequest) get;
	    readyToGet.deq();
	    reqOutstanding.deq;
	    availableBuffers.decrement(unpack(truncate(reqOutstanding.first.burstLen>>beat_shift)));
	    return reqOutstanding.first;
	 endmethod
      endinterface
      interface Put readData;
	 method Action put(ObjectData#(dataWidth) x);
	    readBuffer.fifo.enq(x);
	 endmethod
      endinterface
   endinterface
endmodule

//
// @brief Makes a Dma channel for writing wordSize words from memory.
//
// @param dataWidth The width of the bus in bits.
// @param bufferDepth The depth of the internal buffer
//
module mkDmaWriteBuffer(DmaWriteBuffer#(dataWidth, bufferDepth))
   provisos(Add#(b__, TAdd#(1, TLog#(bufferDepth)), 8),
	    Div#(dataWidth,8,dataWidthBytes),
	    Mul#(dataWidthBytes,8,dataWidth),
	    Log#(dataWidthBytes,beatShift));

   FIFOFLevel#(ObjectData#(dataWidth),bufferDepth) writeBuffer <- mkFIFOFLevel;
   FIFOF#(ObjectRequest)        reqOutstanding <- mkFIFOF();
   FIFOF#(Bit#(6))                        doneTags <- mkFIFOF();
   Ratchet#(TAdd#(1,TLog#(bufferDepth))) availableWords <- mkRatchet(fromInteger(valueOf(bufferDepth)));
   let beat_shift = fromInteger(valueOf(beatShift));

   FIFO#(Bool) readyToGet <- mkFIFO();
   rule updateReady;
      readyToGet.enq(unpack(truncate(reqOutstanding.first.burstLen>>beat_shift)) <= availableWords.read());
   endrule

   // only issue the writeRequest when sufficient data is available.  This includes the data we have already committed.
   interface ObjectWriteServer dmaServer;
      interface Put writeReq = toPut(reqOutstanding);
      interface Put writeData;
	 method Action put(ObjectData#(dataWidth) d);
	    writeBuffer.fifo.enq(d);
	    availableWords.increment(1);
	 endmethod
      endinterface
      interface Get writeDone = toGet(doneTags);
   endinterface
   interface ObjectWriteClient dmaClient;
      interface Get writeReq;
	 method ActionValue#(ObjectRequest) get;
	    readyToGet.deq();
	    reqOutstanding.deq;
	    availableWords.decrement(unpack(truncate(reqOutstanding.first.burstLen>>beat_shift)));
	    return reqOutstanding.first;
	 endmethod
      endinterface
      interface Get writeData;
	 method ActionValue#(ObjectData#(dataWidth)) get();
	    writeBuffer.fifo.deq;
	    return writeBuffer.fifo.first;
	 endmethod
      endinterface
      interface Put writeDone = toPut(doneTags);
   endinterface
endmodule