fix type names of additional dma channels

// 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 FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import GetPut::*;
import StmtFSM::*;
import ClientServer::*;

import PortalMemory::*;
import Dma::*;
import GetPutF::*;

import RingTypes::*;
import RingBuffer::*;
import CopyEngine::*;
import EchoEngine::*;
import NopEngine::*;

interface RingRequest;
   method Action set(Bit#(1) cmd, Bit#(3) regist, Bit#(32) addr);
   method Action get(Bit#(1) cmd, Bit#(3) regist);
   method Action hwenable(Bit#(1) en);
   method Action doCommandIndirect(Bit#(32) addr);
   method Action doCommandImmediate(Bit#(64) data);
endinterface

interface RingIndication;
   method Action setResult(Bit#(1) cmd, Bit#(3) regist, Bit#(32) addr);
   method Action getResult(Bit#(1) cmd, Bit#(3) regist, Bit#(32) addr);
   method Action completion(Bit#(32) command, Bit#(32) tag);
endinterface

module mkRingRequest#(RingIndication indication,
		      DmaReadServer#(64) dma_read_chan,
		      DmaWriteServer#(64) dma_write_chan,
		      DmaReadServer#(64) cmd_read_chan,
		      DmaWriteServer#(64) status_write_chan )(RingRequest);
   DmaReadServer#(64,8) copy_read_chan <- mkDmaReadBuffer();
   DmaWriteServer#(64,8) copy_write_chan <- mkDmaWriteBuffer();

   ServerF#(Bit#(64), Bit#(64)) copyEngine <- mkCopyEngine(dma_read_chan, dma_write_chan);
   ServerF#(Bit#(64), Bit#(64)) nopEngine <- mkNopEngine();
   ServerF#(Bit#(64), Bit#(64)) echoEngine <- mkEchoEngine();

   RingBuffer cmdRing <- mkRingBuffer;
   RingBuffer statusRing <- mkRingBuffer;
   Reg#(Bool) hwenabled <- mkReg(False);
   Reg#(Bool) cmdBusy <- mkReg(False);
   Reg#(Bit#(64)) cmd <- mkReg(0);
   Reg#(Bit#(4)) ii <- mkReg(0);
   Reg#(Bit#(4)) respCtr <- mkReg(0);
   Reg#(Bit#(4)) dispCtr <- mkReg(0);
   Reg#(Bit#(6)) cmdFetchTag <- mkReg(0);
   Reg#(Bool) cmdFetchEn <- mkReg(False);

   let engineselect = pack(cmd)[63:56];
   function ServerF#(Bit#(64), Bit#(64)) cmdifc();
      if (engineselect == zeroExtend(pack(CmdNOP)))
	 return nopEngine;
      else if (engineselect == zeroExtend(pack(CmdCOPY)))
	 return copyEngine;
      else if (engineselect == zeroExtend(pack(CmdECHO)))
	 return echoEngine;
      else
	 return nopEngine;
   endfunction

   Stmt cmdFetch =
   seq
      $display("cmdFetch FSM TOP");
      while (True)
	 seq
	    if (hwenabled)
	       seq
	       if (cmdRing.bufferfirst != cmdRing.bufferlast)
		  seq
		     $display ("cmdFetch handle=%h address=%d burst=%h tag=%h", cmdRing.memhandle, cmdRing.bufferlast, 8, cmdFetchTag);
		     cmd_read_chan.readReq.put(
			DmaRequest{handle: cmdRing.memhandle,
			   address: cmdRing.bufferlast, burstLen: 8, tag: cmdFetchTag});
		     cmdRing.pop(64);
		     cmdFetchTag <= cmdFetchTag + 1;
		  endseq
	       endseq
	 endseq
   endseq;

   Stmt cmdDispatch =
   seq
      while (True) seq
	 $display("cmdDispatch FSM TOP");
	 action
	    let rv <- cmd_read_chan.readData.get();
	    cmd <= rv.data;
	    $display("cmdDispatch %h", cmd);
	    //cmdifc.request.put(rv.data);
	 endaction
	 for (dispCtr <= 1; dispCtr < 8; dispCtr <= dispCtr + 1)
	    action
	       let rv <- cmd_read_chan.readData.get();
	       //cmdifc.request.put(rv.data);
	    endaction
      endseq
   endseq;

   Stmt cmdCompletion =
   seq
      while(True) seq
	 while(!(hwenabled && statusRing.notFull())) noAction;
      endseq
   endseq;

   Stmt responseArbiter =
   seq
      while(True) seq
	 if (statusRing.notFull() && copyEngine.response.notEmpty())
	    seq
	       $display("responseArbiter copyEngine completion");
	       status_write_chan.writeReq.put(
		  DmaRequest{handle: statusRing.memhandle,
		     address: statusRing.bufferfirst, burstLen: 8, tag: 0});
	       for (respCtr <= 0; respCtr < 8; respCtr <= respCtr + 1)
		  action
		     let rv <- copyEngine.response.get();
		     status_write_chan.writeData.put(DmaData{data: rv, tag: 0});
		  endaction
	       statusRing.push(64);
	    endseq

	 if (statusRing.notFull() && echoEngine.response.notEmpty())
	    seq
	       $display("responseArbiter echoEngine completion");
	       status_write_chan.writeReq.put(
		  DmaRequest{handle: statusRing.memhandle,
		     address: statusRing.bufferfirst, burstLen: 8, tag: 0});
	       for (respCtr <= 0; respCtr < 8; respCtr <= respCtr + 1)
		  action
		     let rv <- echoEngine.response.get();
		     status_write_chan.writeData.put(DmaData{data: rv, tag: 0});
		  endaction
	       statusRing.push(64);
	    endseq

      endseq
   endseq;

   mkAutoFSM (cmdFetch);
   mkAutoFSM (cmdDispatch);
   mkAutoFSM (cmdCompletion);
   mkAutoFSM (responseArbiter);

      // to start a command, doCommand fires off a memory read to the
      // specified address. when it comes back, the doCommandRule will
      // handle it
      method Action doCommandIndirect(Bit#(32) addr);
	 //cmd_read_chan.readReq.put(addr);
      endmethod

      method Action doCommandImmediate(Bit#(64) data);
      	 $display("doCommandImmediate %h", data);
      endmethod

      method Action set(Bit#(1) _cmd, Bit#(3) regist, Bit#(32) addr);
	 if (_cmd == 0)
	    cmdRing.configifc.set(regist, addr);
	 else
	    statusRing.configifc.set(regist, addr);
	 indication.setResult(_cmd, regist, addr);
      endmethod

      method Action get(Bit#(1) _cmd, Bit#(3) regist);
	 if (_cmd == 0)
	    indication.getResult(0, regist,
	       cmdRing.configifc.get(regist));
	 else
	    indication.getResult(0, regist,
	       statusRing.configifc.get(regist));
      endmethod

      method Action hwenable(Bit#(1) en);
	 $display ("hwenable set to %h", en);
	 hwenabled <= en == 1;
      endmethod

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 FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import GetPut::*;
import StmtFSM::*;
import ClientServer::*;

import PortalMemory::*;
import Dma::*;
import GetPutF::*;

import RingTypes::*;
import RingBuffer::*;
import CopyEngine::*;
import EchoEngine::*;
import NopEngine::*;

interface RingRequest;
   method Action set(Bit#(1) cmd, Bit#(3) regist, Bit#(32) addr);
   method Action get(Bit#(1) cmd, Bit#(3) regist);
   method Action hwenable(Bit#(1) en);
   method Action doCommandIndirect(Bit#(32) addr);
   method Action doCommandImmediate(Bit#(64) data);
endinterface

interface RingIndication;
   method Action setResult(Bit#(1) cmd, Bit#(3) regist, Bit#(32) addr);
   method Action getResult(Bit#(1) cmd, Bit#(3) regist, Bit#(32) addr);
   method Action completion(Bit#(32) command, Bit#(32) tag);
endinterface

module mkRingRequest#(RingIndication indication,
		      DmaReadServer#(64) dma_read_chan,
		      DmaWriteServer#(64) dma_write_chan,
		      DmaReadServer#(64) cmd_read_chan,
		      DmaWriteServer#(64) status_write_chan )(RingRequest);
   DmaReadBuffer#(64,8) copy_read_chan <- mkDmaReadBuffer();
   DmaWriteBuffer#(64,8) copy_write_chan <- mkDmaWriteBuffer();

   ServerF#(Bit#(64), Bit#(64)) copyEngine <- mkCopyEngine(dma_read_chan, dma_write_chan);
   ServerF#(Bit#(64), Bit#(64)) nopEngine <- mkNopEngine();
   ServerF#(Bit#(64), Bit#(64)) echoEngine <- mkEchoEngine();

   RingBuffer cmdRing <- mkRingBuffer;
   RingBuffer statusRing <- mkRingBuffer;
   Reg#(Bool) hwenabled <- mkReg(False);
   Reg#(Bool) cmdBusy <- mkReg(False);
   Reg#(Bit#(64)) cmd <- mkReg(0);
   Reg#(Bit#(4)) ii <- mkReg(0);
   Reg#(Bit#(4)) respCtr <- mkReg(0);
   Reg#(Bit#(4)) dispCtr <- mkReg(0);
   Reg#(Bit#(6)) cmdFetchTag <- mkReg(0);
   Reg#(Bool) cmdFetchEn <- mkReg(False);

   let engineselect = pack(cmd)[63:56];
   function ServerF#(Bit#(64), Bit#(64)) cmdifc();
      if (engineselect == zeroExtend(pack(CmdNOP)))
	 return nopEngine;
      else if (engineselect == zeroExtend(pack(CmdCOPY)))
	 return copyEngine;
      else if (engineselect == zeroExtend(pack(CmdECHO)))
	 return echoEngine;
      else
	 return nopEngine;
   endfunction

   Stmt cmdFetch =
   seq
      $display("cmdFetch FSM TOP");
      while (True)
	 seq
	    if (hwenabled)
	       seq
	       if (cmdRing.bufferfirst != cmdRing.bufferlast)
		  seq
		     $display ("cmdFetch handle=%h address=%d burst=%h tag=%h", cmdRing.memhandle, cmdRing.bufferlast, 8, cmdFetchTag);
		     cmd_read_chan.readReq.put(
			DmaRequest{handle: cmdRing.memhandle,
			   address: cmdRing.bufferlast, burstLen: 8, tag: cmdFetchTag});
		     cmdRing.pop(64);
		     cmdFetchTag <= cmdFetchTag + 1;
		  endseq
	       endseq
	 endseq
   endseq;

   Stmt cmdDispatch =
   seq
      while (True) seq
	 $display("cmdDispatch FSM TOP");
	 action
	    let rv <- cmd_read_chan.readData.get();
	    cmd <= rv.data;
	    $display("cmdDispatch %h", cmd);
	    //cmdifc.request.put(rv.data);
	 endaction
	 for (dispCtr <= 1; dispCtr < 8; dispCtr <= dispCtr + 1)
	    action
	       let rv <- cmd_read_chan.readData.get();
	       //cmdifc.request.put(rv.data);
	    endaction
      endseq
   endseq;

   Stmt cmdCompletion =
   seq
      while(True) seq
	 while(!(hwenabled && statusRing.notFull())) noAction;
      endseq
   endseq;

   Stmt responseArbiter =
   seq
      while(True) seq
	 if (statusRing.notFull() && copyEngine.response.notEmpty())
	    seq
	       $display("responseArbiter copyEngine completion");
	       status_write_chan.writeReq.put(
		  DmaRequest{handle: statusRing.memhandle,
		     address: statusRing.bufferfirst, burstLen: 8, tag: 0});
	       for (respCtr <= 0; respCtr < 8; respCtr <= respCtr + 1)
		  action
		     let rv <- copyEngine.response.get();
		     status_write_chan.writeData.put(DmaData{data: rv, tag: 0});
		  endaction
	       statusRing.push(64);
	    endseq

	 if (statusRing.notFull() && echoEngine.response.notEmpty())
	    seq
	       $display("responseArbiter echoEngine completion");
	       status_write_chan.writeReq.put(
		  DmaRequest{handle: statusRing.memhandle,
		     address: statusRing.bufferfirst, burstLen: 8, tag: 0});
	       for (respCtr <= 0; respCtr < 8; respCtr <= respCtr + 1)
		  action
		     let rv <- echoEngine.response.get();
		     status_write_chan.writeData.put(DmaData{data: rv, tag: 0});
		  endaction
	       statusRing.push(64);
	    endseq

      endseq
   endseq;

   mkAutoFSM (cmdFetch);
   mkAutoFSM (cmdDispatch);
   mkAutoFSM (cmdCompletion);
   mkAutoFSM (responseArbiter);

      // to start a command, doCommand fires off a memory read to the
      // specified address. when it comes back, the doCommandRule will
      // handle it
      method Action doCommandIndirect(Bit#(32) addr);
	 //cmd_read_chan.readReq.put(addr);
      endmethod

      method Action doCommandImmediate(Bit#(64) data);
      	 $display("doCommandImmediate %h", data);
      endmethod

      method Action set(Bit#(1) _cmd, Bit#(3) regist, Bit#(32) addr);
	 if (_cmd == 0)
	    cmdRing.configifc.set(regist, addr);
	 else
	    statusRing.configifc.set(regist, addr);
	 indication.setResult(_cmd, regist, addr);
      endmethod

      method Action get(Bit#(1) _cmd, Bit#(3) regist);
	 if (_cmd == 0)
	    indication.getResult(0, regist,
	       cmdRing.configifc.get(regist));
	 else
	    indication.getResult(0, regist,
	       statusRing.configifc.get(regist));
      endmethod

      method Action hwenable(Bit#(1) en);
	 $display ("hwenable set to %h", en);
	 hwenabled <= en == 1;
      endmethod

endmodule


more broken comments and it works!

more broken comments
and it works!

// 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 StmtFSM::*;
import BRAM::*;
import MCSAlgorithm::*;
import StackReg::*;

/* frame arguments */
typedef struct {
   Bit#(7) aStart;
   Bit#(7) bStart;
   Bit#(7) aLen;
   Bit#(7) bLen;
   } CArgs deriving(Bits);

typedef struct {
   Bit#(7) midi;
   Bit#(7) maxj;
   } CVars deriving(Bits);

typedef enum {HCSIdle, HCS1, HCS2, HCS3, HCS4, HCS5, HCS6,
   HCSComplete} HCState deriving (Bits, Eq);

module mkHirschC#(BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strA, BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strB, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) matL, MCSAlgorithm chirschB0,  MCSAlgorithm chirschB1, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) l0, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) l1)(MCSAlgorithm)
         provisos(Add#(0, 7, strIndexWidth),
	       Add#(0, 14, lIndexWidth));

      /* pc, args, vars */
   StackReg#(128, HCState, CArgs, CVars) fr <- mkStackReg(128, HCSIdle);

   Reg#(Bit#(7)) aStartReg <- mkReg(0);
   Reg#(Bit#(7)) bStartReg <- mkReg(0);
   Reg#(Bit#(14)) rStartReg <- mkReg(0);
   Reg#(Bit#(7)) aLenReg <- mkReg(0);
   Reg#(Bit#(7)) bLenReg <- mkReg(0);
   Reg#(Bit#(7)) ii <- mkReg(0);
   Reg#(Bit#(7)) jj <- mkReg(0);
   Reg#(Bit#(8)) aData <- mkReg(0);
   Reg#(Bit#(8)) bData <- mkReg(0);
   Reg#(Bit#(14)) outcounter <- mkReg(0);
   Reg#(Bit#(16)) maxjvalue <- mkReg(0);

/*
 * HirschC(Astart, Alen, Bstart, Blen, output fifo)
 * implicit A storage, B storage
 *
 */

  // This FSM searches string B looking for the first char of string A
   Stmt hirschC2Stmt =
   seq
      //$display("hirschC2Stmt running ");
      // read A[0]
      strA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: fr.args.aStart, datain: ?});
      action
	 let tmp <- strA.response.get();
	 aData <= tmp;
      endaction
      // scan for it in B
      for (jj <= 0; jj < fr.args.bLen; jj <= jj + 1)
	 seq
	    strB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: fr.args.bStart + jj, datain: ?});
	    action
	       let tmp <- strB.response.get();
	       bData <= tmp;
	    endaction
	    if (aData == bData)
	       seq
		  //$display("output %d", aData);
		  matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: outcounter, datain: zeroExtend(aData)});
		  outcounter <= outcounter + 1;
		  break;
	       endseq
	 endseq
      fr.doreturn();
   endseq;

   FSM hC2fsm <- mkFSM(hirschC2Stmt);

   // AlgC step 1, 2, and 3
   rule hc1 (fr.pc == HCS1);
      //$display("HCS1 aStart %d aLen %d bStart %d bLen %d", fr.args.aStart, fr.args.aLen, fr.args.bStart, fr.args.bLen);
      if (fr.args.bLen == 0)
	fr.doreturn();
     else if (fr.args.aLen == 1)
	begin
	   hC2fsm.start();
	   fr.nextpc(HCS2);
	end
     else
	action
	   let midi = fr.args.aLen >> 1;
	   fr.vars.midi <= midi;
	   chirschB1.setupA(fr.args.aStart, midi);
	   chirschB1.setupB(fr.args.bStart, fr.args.bLen);
	   chirschB0.setupA(fr.args.aStart+midi, fr.args.aLen - midi);
	   chirschB0.setupB(fr.args.bStart, fr.args.bLen);
	   chirschB0.fsm.start();
	   chirschB1.fsm.start();
	   fr.nextpc(HCS3);
	endaction
   endrule

   // This FSM searches the results of the two calls to HirschB
   Stmt hirschC4Stmt =
   seq
      //$display ("hirschC4A stmt running");
      maxjvalue <= 0;
      fr.vars.maxj <= 0;
      for (jj <= 0; jj <= fr.args.bLen; jj <= jj + 1)
	 seq
	    l0.request.put(BRAMRequest{write: False, responseOnWrite: False, address: zeroExtend(jj), datain: ?});
	    l1.request.put(BRAMRequest{write: False, responseOnWrite: False, address: zeroExtend(fr.args.bLen - jj), datain: ?});
	    action
	       let t1 <- l0.response.get();
	       let t2 <- l1.response.get();
	       //$display(" j %d l0 %d l1 %d, sum %d oldmax %d",
		 // jj, t1, t2, t1 + t2, maxjvalue);
	       if ((t1 + t2) > maxjvalue)
		  action
		     maxjvalue <= t1 + t2;
		     fr.vars.maxj <= jj;
		  endaction
	    endaction
	 endseq
      //$display ("midi %d maxj %d", fr.vars.midi, fr.vars.maxj);
      fr.docall(HCS1, HCS5, CArgs {aStart: fr.args.aStart, aLen: fr.vars.midi, bStart: fr.args.bStart, bLen: fr.vars.maxj}, fr.vars);
   endseq;

   FSM hc4fsm <- mkFSM(hirschC4Stmt);

   rule hc3 (fr.pc == HCS3 && chirschB0.fsm.done() && chirschB1.fsm.done());
      //$display("HSC3");
      hc4fsm.start();
      fr.nextpc(HCS4);
   endrule

   rule hc5 (fr.pc == HCS5);
      //$display("HSC5 aStart %d aLen %d bStart %d bLen %d midi %d maxj %d",
	// fr.args.aStart, fr.args.aLen, fr.args.bStart, fr.args.bLen,
	// fr.vars.midi, fr.vars.maxj);
      fr.docall(HCS1, HCS6, CArgs{aStart: fr.args.aStart + fr.vars.midi, aLen: fr.args.aLen - fr.vars.midi, bStart: fr.args.bStart + fr.vars.maxj, bLen: fr.args.bLen - fr.vars.maxj}, fr.vars);
   endrule

   rule hc6 (fr.pc == HCS6);
      //$display("HSC6");
      fr.doreturn();
   endrule

   rule hccomplete (fr.pc == HCSComplete);
      $display("HSCComplete, result size %d", outcounter);
      fr.nextpc(HCSIdle);
   endrule

   method Action setupA(Bit#(7) start, Bit#(7) length);
      $display("HirschC setupA %d %d", start, length);
      aStartReg <= start;
      aLenReg <= length;
   endmethod

   method Action setupB(Bit#(7) start, Bit#(7) length);
      $display("HirschC setupB %d %d", start, length);
      bStartReg <= start;
      bLenReg <= length;
   endmethod

   method Action setupL(Bit#(14) start);
      rStartReg <= start;
   endmethod

   method Bit#(14) result();
      return(outcounter);
   endmethod

   interface FSM fsm;
      method Action start();
         $display("HirschC running aLen %d bLen %d", aLenReg, bLenReg);
	 fr.docall(HCS1, HCSComplete, CArgs{aStart: 0, aLen: aLenReg,
	    bStart: 0, bLen: bLenReg}, CVars {midi: 0, maxj: 0});
      endmethod
      method Bool done();
	 return(fr.pc == HCSIdle);
      endmethod
      method Action waitTillDone();
      endmethod
      method Action abort();
      endmethod
   endinterface: fsm

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 StmtFSM::*;
import BRAM::*;
import MCSAlgorithm::*;
import StackReg::*;

/* frame arguments */
typedef struct {
   Bit#(7) aStart;
   Bit#(7) bStart;
   Bit#(7) aLen;
   Bit#(7) bLen;
   } CArgs deriving(Bits);

typedef struct {
   Bit#(7) midi;
   Bit#(7) maxj;
   } CVars deriving(Bits);

typedef enum {HCSIdle, HCS1, HCS2, HCS3, HCS4, HCS5, HCS6,
   HCSComplete} HCState deriving (Bits, Eq);

module mkHirschC#(BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strA, BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strB, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) matL, MCSAlgorithm chirschB0,  MCSAlgorithm chirschB1, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) l0, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) l1)(MCSAlgorithm)
         provisos(Add#(0, 7, strIndexWidth),
	       Add#(0, 14, lIndexWidth));

      /* pc, args, vars */
   StackReg#(128, HCState, CArgs, CVars) fr <- mkStackReg(128, HCSIdle);

   Reg#(Bit#(7)) aStartReg <- mkReg(0);
   Reg#(Bit#(7)) bStartReg <- mkReg(0);
   Reg#(Bit#(14)) rStartReg <- mkReg(0);
   Reg#(Bit#(7)) aLenReg <- mkReg(0);
   Reg#(Bit#(7)) bLenReg <- mkReg(0);
   Reg#(Bit#(7)) ii <- mkReg(0);
   Reg#(Bit#(7)) jj <- mkReg(0);
   Reg#(Bit#(8)) aData <- mkReg(0);
   Reg#(Bit#(8)) bData <- mkReg(0);
   Reg#(Bit#(14)) outcounter <- mkReg(0);
   Reg#(Bit#(16)) maxjvalue <- mkReg(0);

/*
 * HirschC(Astart, Alen, Bstart, Blen, output fifo)
 * implicit A storage, B storage
 *
 */

  // This FSM searches string B looking for the first char of string A
   Stmt hirschC2Stmt =
   seq
      //$display("hirschC2Stmt running ");
      // read A[0]
      strA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: fr.args.aStart, datain: ?});
      action
	 let tmp <- strA.response.get();
	 aData <= tmp;
      endaction
      // scan for it in B
      for (jj <= 0; jj < fr.args.bLen; jj <= jj + 1)
	 seq
	    strB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: fr.args.bStart + jj, datain: ?});
	    action
	       let tmp <- strB.response.get();
	       bData <= tmp;
	    endaction
	    if (aData == bData)
	       seq
		  //$display("output %d", aData);
		  matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: outcounter, datain: zeroExtend(aData)});
		  outcounter <= outcounter + 1;
		  break;
	       endseq
	 endseq
      fr.doreturn();
   endseq;

   FSM hC2fsm <- mkFSM(hirschC2Stmt);

   // AlgC step 1, 2, and 3
   rule hc1 (fr.pc == HCS1);
      //$display("HCS1 aStart %d aLen %d bStart %d bLen %d", fr.args.aStart, fr.args.aLen, fr.args.bStart, fr.args.bLen);
      if (fr.args.bLen == 0)
	fr.doreturn();
     else if (fr.args.aLen == 1)
	begin
	   hC2fsm.start();
	   fr.nextpc(HCS2);
	end
     else
	action
	   let midi = fr.args.aLen >> 1;
	   fr.vars.midi <= midi;
	   chirschB1.setupA(fr.args.aStart, midi);
	   chirschB1.setupB(fr.args.bStart, fr.args.bLen);
	   chirschB0.setupA(fr.args.aStart+midi, fr.args.aLen - midi);
	   chirschB0.setupB(fr.args.bStart, fr.args.bLen);
	   chirschB0.fsm.start();
	   chirschB1.fsm.start();
	   fr.nextpc(HCS3);
	endaction
   endrule

   // This FSM searches the results of the two calls to HirschB
   Stmt hirschC4Stmt =
   seq
      //$display ("hirschC4A stmt running");
      maxjvalue <= 0;
      fr.vars.maxj <= 0;
      for (jj <= 0; jj <= fr.args.bLen; jj <= jj + 1)
	 seq
	    l0.request.put(BRAMRequest{write: False, responseOnWrite: False, address: zeroExtend(jj), datain: ?});
	    l1.request.put(BRAMRequest{write: False, responseOnWrite: False, address: zeroExtend(fr.args.bLen - jj), datain: ?});
	    action
	       let t1 <- l0.response.get();
	       let t2 <- l1.response.get();
	       //$display(" j %d l0 %d l1 %d, sum %d oldmax %d",
		 // jj, t1, t2, t1 + t2, maxjvalue);
	       if ((t1 + t2) > maxjvalue)
		  action
		     maxjvalue <= t1 + t2;
		     fr.vars.maxj <= jj;
		  endaction
	    endaction
	 endseq
      //$display ("midi %d maxj %d", fr.vars.midi, fr.vars.maxj);
      fr.docall(HCS1, HCS5, CArgs {aStart: fr.args.aStart, aLen: fr.vars.midi, bStart: fr.args.bStart, bLen: fr.vars.maxj}, fr.vars);
   endseq;

   FSM hc4fsm <- mkFSM(hirschC4Stmt);

   rule hc3 (fr.pc == HCS3 && chirschB0.fsm.done() && chirschB1.fsm.done());
      //$display("HSC3");
      hc4fsm.start();
      fr.nextpc(HCS4);
   endrule

   rule hc5 (fr.pc == HCS5);
      //$display("HSC5 aStart %d aLen %d bStart %d bLen %d midi %d maxj %d",
	 fr.args.aStart, fr.args.aLen, fr.args.bStart, fr.args.bLen,
	 fr.vars.midi, fr.vars.maxj);
      fr.docall(HCS1, HCS6, CArgs{aStart: fr.args.aStart + fr.vars.midi, aLen: fr.args.aLen - fr.vars.midi, bStart: fr.args.bStart + fr.vars.maxj, bLen: fr.args.bLen - fr.vars.maxj}, fr.vars);
   endrule

   rule hc6 (fr.pc == HCS6);
      //$display("HSC6");
      fr.doreturn();
   endrule

   rule hccomplete (fr.pc == HCSComplete);
      $display("HSCComplete, result size %d", outcounter);
      fr.nextpc(HCSIdle);
   endrule

   method Action setupA(Bit#(7) start, Bit#(7) length);
      $display("HirschC setupA %d %d", start, length);
      aStartReg <= start;
      aLenReg <= length;
   endmethod

   method Action setupB(Bit#(7) start, Bit#(7) length);
      $display("HirschC setupB %d %d", start, length);
      bStartReg <= start;
      bLenReg <= length;
   endmethod

   method Action setupL(Bit#(14) start);
      rStartReg <= start;
   endmethod

   method Bit#(14) result();
      return(outcounter);
   endmethod

   interface FSM fsm;
      method Action start();
         $display("HirschC running aLen %d bLen %d", aLenReg, bLenReg);
	 fr.docall(HCS1, HCSComplete, CArgs{aStart: 0, aLen: aLenReg,
	    bStart: 0, bLen: bLenReg}, CVars {midi: 0, maxj: 0});
      endmethod
      method Bool done();
	 return(fr.pc == HCSIdle);
      endmethod
      method Action waitTillDone();
      endmethod
      method Action abort();
      endmethod
   endinterface: fsm

endmodule


Fixed bug in SimRam.bsv

Fixed bug in SimRam.bsv

// Copyright (c) 2017 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.

`include "ProcConfig.bsv"

import BRAM::*;
import Vector::*;

import Port::*;
import ShiftRegister::*;

import Abstraction::*;
import RVTypes::*;

/// This module creates a GenericMemServerPort from a BRAM that is initialized
/// by a hex file
module mkSimRam#(String hex_file_name)(GenericMemServerPort#(data_sz)) provisos (Mul#(32, num_words, data_sz), Mul#(num_words, 4, TDiv#(data_sz, 8)));
    BRAM_Configure bram_config = defaultValue;
    bram_config.loadFormat = tagged Hex hex_file_name;

    BRAM1PortBE#(Bit#(16), Bit#(32), TDiv#(32,8)) bram <- mkBRAM1ServerBE(bram_config);

    ShiftRegister#(num_words, 32) dataShiftRegister <- mkShiftRegister;
    ShiftRegister#(num_words, 4) byteEnShiftRegister <- mkShiftRegister;

    Reg#(PAddr) currAddr <- mkReg(0);
    Reg#(Maybe#(Bool)) pendingReqIsStore <- mkReg(tagged Invalid);
    Reg#(Bit#(TLog#(TAdd#(num_words, 1)))) wordsLeft <- mkReg(0);

    rule handleStoreReq(pendingReqIsStore matches tagged Valid .isStore &&& (isStore && (wordsLeft != 0)));
        let word = dataShiftRegister.serial.response.first;
        dataShiftRegister.serial.response.deq;
        let byteEn = byteEnShiftRegister.serial.response.first;
        byteEnShiftRegister.serial.response.deq;
        bram.portA.request.put(BRAMRequestBE {
                                    writeen: byteEn,
                                    responseOnWrite: False,
                                    address: truncate(currAddr >> 2),
                                    datain: word});
        currAddr <= currAddr + 4;
        wordsLeft <= wordsLeft - 1;
    endrule

    rule handleLoadReq(pendingReqIsStore matches tagged Valid .isStore &&& (!isStore && (wordsLeft != 0)));
        bram.portA.request.put(BRAMRequestBE {
                                    writeen: 0,
                                    responseOnWrite: False,
                                    address: truncate(currAddr >> 2),
                                    datain: 0});
        currAddr <= currAddr + 4;
        wordsLeft <= wordsLeft - 1;
    endrule

    rule handleResp(pendingReqIsStore matches tagged Valid .isStore &&& !isStore);
        let x <- bram.portA.response.get();
        dataShiftRegister.serial.request.enq(x);
    endrule

    interface InputPort request;
        method Action enq(GenericMemReq#(data_sz) req) if (!isValid(pendingReqIsStore));
            if (req.write) begin
                Vector#(num_words, Bit#(32)) data_vec = unpack(req.data);
                dataShiftRegister.parallel.request.enq(data_vec);
                Vector#(num_words, Bit#(4)) byteEn_vec = unpack(req.byteen);
                byteEnShiftRegister.parallel.request.enq(byteEn_vec);
            end
            pendingReqIsStore <= tagged Valid req.write;
            let addr_mask = ~fromInteger((valueOf(num_words) * 4) - 1);
            currAddr <= req.addr & addr_mask;
            wordsLeft <= fromInteger(valueOf(num_words));
        endmethod
        method Bool canEnq;
            return !isValid(pendingReqIsStore);
        endmethod
    endinterface
    interface OutputPort response;
        method GenericMemResp#(data_sz) first if (pendingReqIsStore matches tagged Valid .isStore &&& ((isStore || dataShiftRegister.parallel.response.canDeq) && (wordsLeft == 0)));
            if (!isStore) begin
                let data_vec = dataShiftRegister.parallel.response.first;
                return GenericMemResp {
                            write: False,
                            data: pack(data_vec) };
            end else begin
                return GenericMemResp {
                            write: True,
                            data: 0 };
            end
        endmethod
        method Action deq if (pendingReqIsStore matches tagged Valid .isStore &&& ((isStore || dataShiftRegister.parallel.response.canDeq) && (wordsLeft == 0)));
            if (!isStore) begin
                dataShiftRegister.parallel.response.deq;
            end
            pendingReqIsStore <= tagged Invalid;
        endmethod
        method Bool canDeq;
            if (pendingReqIsStore matches tagged Valid .isStore) begin
                return (isStore || dataShiftRegister.parallel.response.canDeq);
            end else begin
                return False;
            end
        endmethod
    endinterface
endmodule

// Copyright (c) 2017 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.

`include "ProcConfig.bsv"

import BRAM::*;
import Vector::*;

import Port::*;
import ShiftRegister::*;

import Abstraction::*;
import RVTypes::*;

/// This module creates a GenericMemServerPort from a BRAM that is initialized
/// by a hex file
module mkSimRam#(String hex_file_name)(GenericMemServerPort#(data_sz)) provisos (Mul#(32, num_words, data_sz), Mul#(num_words, 4, TDiv#(data_sz, 8)));
    BRAM_Configure bram_config = defaultValue;
    bram_config.loadFormat = tagged Hex hex_file_name;

    BRAM1PortBE#(Bit#(16), Bit#(32), TDiv#(32,8)) bram <- mkBRAM1ServerBE(bram_config);

    ShiftRegister#(num_words, 32) dataShiftRegister <- mkShiftRegister;
    ShiftRegister#(num_words, 4) byteEnShiftRegister <- mkShiftRegister;

    Reg#(PAddr) currAddr <- mkReg(0);
    Reg#(Maybe#(Bool)) pendingReqIsStore <- mkReg(tagged Invalid);
    Reg#(Bit#(TLog#(TAdd#(num_words, 1)))) wordsLeft <- mkReg(0);

    rule handleStoreReq(pendingReqIsStore matches tagged Valid .isStore &&& (isStore && (wordsLeft != 0)));
        let word = dataShiftRegister.serial.response.first;
        dataShiftRegister.serial.response.deq;
        let byteEn = byteEnShiftRegister.serial.response.first;
        byteEnShiftRegister.serial.response.deq;
        bram.portA.request.put(BRAMRequestBE {
                                    writeen: byteEn,
                                    responseOnWrite: False,
                                    address: truncate(currAddr >> 2),
                                    datain: word});
        currAddr <= currAddr + 4;
        wordsLeft <= wordsLeft - 1;
    endrule

    rule handleLoadReq(pendingReqIsStore matches tagged Valid .isStore &&& (!isStore && (wordsLeft != 0)));
        bram.portA.request.put(BRAMRequestBE {
                                    writeen: 0,
                                    responseOnWrite: False,
                                    address: truncate(currAddr >> 2),
                                    datain: 0});
        currAddr <= currAddr + 4;
        wordsLeft <= wordsLeft - 1;
    endrule

    rule handleResp(pendingReqIsStore matches tagged Valid .isStore &&& !isStore);
        let x <- bram.portA.response.get();
        dataShiftRegister.serial.request.enq(x);
    endrule

    interface InputPort request;
        method Action enq(GenericMemReq#(data_sz) req) if (!isValid(pendingReqIsStore));
            if (req.write) begin
                Vector#(num_words, Bit#(32)) data_vec = unpack(req.data);
                dataShiftRegister.parallel.request.enq(data_vec);
                Vector#(num_words, Bit#(4)) byteEn_vec = unpack(req.byteen);
                byteEnShiftRegister.parallel.request.enq(byteEn_vec);
            end
            pendingReqIsStore <= tagged Valid req.write;
            currAddr <= req.addr;
            wordsLeft <= fromInteger(valueOf(num_words));
        endmethod
        method Bool canEnq;
            return !isValid(pendingReqIsStore);
        endmethod
    endinterface
    interface OutputPort response;
        method GenericMemResp#(data_sz) first if (pendingReqIsStore matches tagged Valid .isStore &&& ((isStore || dataShiftRegister.parallel.response.canDeq) && (wordsLeft == 0)));
            if (!isStore) begin
                let data_vec = dataShiftRegister.parallel.response.first;
                return GenericMemResp {
                            write: False,
                            data: pack(data_vec) };
            end else begin
                return GenericMemResp {
                            write: True,
                            data: 0 };
            end
        endmethod
        method Action deq if (pendingReqIsStore matches tagged Valid .isStore &&& ((isStore || dataShiftRegister.parallel.response.canDeq) && (wordsLeft == 0)));
            if (!isStore) begin
                dataShiftRegister.parallel.response.deq;
            end
            pendingReqIsStore <= tagged Invalid;
        endmethod
        method Bool canDeq;
            if (pendingReqIsStore matches tagged Valid .isStore) begin
                return (isStore || dataShiftRegister.parallel.response.canDeq);
            end else begin
                return False;
            end
        endmethod
    endinterface
endmodule