one more tweak to msix_base so the writes are not lost

// 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 BRAM           :: *;
import FIFOF          :: *;
import BRAMFIFO       :: *;
import GetPut         :: *;
import Connectable    :: *;
import PCIE           :: *;
import Clocks         :: *;
import PcieTracer     :: *;
import ConnectalMemTypes       :: *;
import AddressGenerator::*;
import Pipe           :: *;

`include "ConnectalProjectConfig.bsv"

// starting word of MSIX config registers
`define msix_base 1024

// An MSIX table entry, as defined in the PCIe spec
interface MSIX_Entry;
   interface Reg#(Bit#(32)) addr_lo;
   interface Reg#(Bit#(32)) addr_hi;
   interface Reg#(Bit#(32)) msg_data;
   interface Reg#(Bool)     masked;
endinterface

interface ReadOnly_MSIX_Entry;
   interface ReadOnly#(Bit#(32)) addr_lo;
   interface ReadOnly#(Bit#(32)) addr_hi;
   interface ReadOnly#(Bit#(32)) msg_data;
   interface ReadOnly#(Bool)     masked;
endinterface

function ReadOnly_MSIX_Entry toReadOnlyMsixEntry(MSIX_Entry msix);
   return (interface ReadOnly_MSIX_Entry;
	   interface ReadOnly addr_lo = regToReadOnly(msix.addr_lo);
	   interface ReadOnly addr_hi = regToReadOnly(msix.addr_hi);
	   interface ReadOnly msg_data = regToReadOnly(msix.msg_data);
	   interface ReadOnly masked = regToReadOnly(msix.masked);
	   endinterface);
endfunction

// control and status registers accessed from PCIe
interface PcieControlAndStatusRegs;
   interface PhysMemSlave#(32,32) memSlave;
   interface Vector#(16,ReadOnly_MSIX_Entry) msixEntry;
   interface PipeIn#(Bit#(64)) changes;
   interface TlpTraceClient traceClient;
endinterface: PcieControlAndStatusRegs

// This module encapsulates all of the logic for instantiating and
// accessing the control and status registers. It defines the
// registers, the address map, and how the registers respond to reads
// and writes.
(* synthesize *)
module mkPcieControlAndStatusRegs(PcieControlAndStatusRegs);

   // Utility for module creating all of the storage for a single MSIX
   // table entry
   module mkMSIXEntry(MSIX_Entry);
      Reg#(Bit#(32)) _addr_lo  <- mkReg(0);
      Reg#(Bit#(32)) _addr_hi  <- mkReg(0);
      Reg#(Bit#(32)) _msg_data <- mkReg(0);
      Reg#(Bool)     _masked   <- mkReg(True);

      interface addr_lo  = _addr_lo;
      interface addr_hi  = _addr_hi;
      interface msg_data = _msg_data;
      interface masked   = _masked;
   endmodule: mkMSIXEntry

   // Registers and their default values
   Vector#(16,MSIX_Entry) msix_entry              <- replicateM(mkMSIXEntry);
   Reg#(TimestampedTlpData) pcieTraceBramResponse <- mkReg(unpack(0));

   // Function to return a one-word slice of the tlpTraceBramResponse
   function Bit#(32) tlpTraceBramResponseSlice(Reg#(TimestampedTlpData) data, Integer i);
       Bit#(8) i8 = fromInteger(i);
       begin
           Bit#(TMul#(12,32)) v = extend(pack(data));
           return v[31 + (i8*32) : 0 + (i8*32)];
       end
   endfunction

   FIFOF#(BRAMRequest#(Bit#(TAdd#(TlpTraceAddrSize,1)),TimestampedTlpData)) bramRequestFifo <- mkFIFOF();
   FIFOF#(TimestampedTlpData)                                               bramResponseFifo <- mkFIFOF();
   Reg#(Bool)                   tlpTracingReg                <- mkReg(True);
   Reg#(Bit#(TlpTraceAddrSize)) tlpTraceLimitReg             <- mkReg(0);
   Reg#(Bit#(TlpTraceAddrSize)) tlpTraceBramWrAddrReg        <- mkReg(0);
   FIFOF#(Bit#(64))             changeFifo                   <- mkSizedBRAMFIFOF(256);

   // State used to actually service read and write requests
   rule brmMuxResponse;
       let v <- toGet(bramResponseFifo).get();
       pcieTraceBramResponse <= v;
   endrule

   AddressGenerator#(16,32)           csrRag <- mkAddressGenerator;
   AddressGenerator#(16,32)           csrWag <- mkAddressGenerator;
   FIFOF#(MemData#(32))     readResponseFifo <- mkFIFOF();
   FIFOF#(MemData#(32))        writeDataFifo <- mkFIFOF();
   FIFOF#(Bit#(MemTagSize)) writeDoneFifo <- mkFIFOF();

   FIFOF#(AddrBeat#(16)) csrRagBeatFifo <- mkFIFOF();
   FIFOF#(Bool)       csrIsMsixAddrFifo <- mkFIFOF();
   FIFOF#(Bit#(2))     csrOneHotFifo000 <- mkFIFOF();
   FIFOF#(Bit#(29))    csrOneHotFifo774 <- mkFIFOF();
   FIFOF#(Bit#(2))     csrOneHotFifo992 <- mkFIFOF();

   FIFOF#(AddrBeat#(16)) csrWagBeatFifo <- mkFIFOF();
   FIFOF#(Bool)       csrWagIsMsixAddrFifo <- mkFIFOF();
   FIFOF#(Bit#(8))     csrWagOneHotFifo768 <- mkFIFOF();
   FIFOF#(Bit#(3))     csrWagOneHotFifo792 <- mkFIFOF();

   rule readDataRule;
      let beat <- csrRag.addrBeat.get();
      let addr = beat.addr >> 2; // word address
      Bit#(32) data = 0;
      let modaddr = (addr % 8192);
      let msixaddr = modaddr - `msix_base;

      csrRagBeatFifo.enq(beat);
      csrIsMsixAddrFifo.enq(msixaddr >= 0 && msixaddr <= 63);
      Bit#(1024) onehot = (1 << addr[9:0]);
      csrOneHotFifo000.enq(onehot[1:0]);
      csrOneHotFifo774.enq(onehot[802:774]);
      csrOneHotFifo992.enq(onehot[993:992]);
   endrule
   rule readDataRule2;
      let beat       <- toGet(csrRagBeatFifo).get();
      let isMsixAddr <- toGet(csrIsMsixAddrFifo).get();
      let addr = beat.addr >> 2; // word address
      Bit#(32) data = 32'hbad0add0;
      let modaddr = (addr % 8192);
      let msix_base = `msix_base;
      let msixaddr = modaddr - msix_base;
      let oneHotDecode000 <- toGet(csrOneHotFifo000).get();
      let oneHotDecode774 <- toGet(csrOneHotFifo774).get();
      let oneHotDecode992 <- toGet(csrOneHotFifo992).get();

      if (isMsixAddr) begin
         begin
            let groupaddr = (msixaddr / 4);
            //******************************** msix_base has to match CONFIG.MXIx_Table_Offset in scripts/connectal-synth-pcie.tcl
            case (msixaddr % 4)
               0: data = msix_entry[groupaddr].addr_lo;
               1: data = msix_entry[groupaddr].addr_hi;
               2: data = msix_entry[groupaddr].msg_data;
               3: data = {'0, pack(msix_entry[groupaddr].masked)}; // vector control
               default: data = 32'hbad0add0;
	  //******************************** end of MSIX Table
            endcase
         end
      end
      else begin
	  // board identification
	  if (oneHotDecode000[0] == 1) data = 32'h65756c42; // Blue
	  if (oneHotDecode000[1] == 1) data = 32'h63657073; // spec

	  if (oneHotDecode774[774-774] == 1) data = fromInteger(2**valueOf(TAdd#(TlpTraceAddrSize,1)));
	  if (oneHotDecode774[775-774] == 1) data = (tlpTracingReg ? 1 : 0);
	  if (oneHotDecode774[776-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 0);
	  if (oneHotDecode774[777-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 1);
	  if (oneHotDecode774[778-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 2);
	  if (oneHotDecode774[779-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 3);
	  if (oneHotDecode774[780-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 4);
	  if (oneHotDecode774[781-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 5);
	  if (oneHotDecode774[792-774] == 1) data = extend(tlpTraceBramWrAddrReg);
	  if (oneHotDecode774[794-774] == 1) data = extend(tlpTraceLimitReg);
	  if (oneHotDecode774[795-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 6);
	  if (oneHotDecode774[796-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 7);
	  if (oneHotDecode774[797-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 8);
	  if (oneHotDecode774[798-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 9);
	  if (oneHotDecode774[799-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 10);
	  if (oneHotDecode774[800-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 11);
   	  if (oneHotDecode774[801-774] == 1) data = (changeFifo.notEmpty()) ? (changeFifo.first()[31:0]) : 0;
   	  if (oneHotDecode774[802-774] == 1) data = (changeFifo.notEmpty()) ? (changeFifo.first()[63:32]) : 0;

         //******************************** msix_base has to match CONFIG.MXIx_PBA_Offset in scripts/connectal-synth-pcie.tcl
	  // 16-bit MSIx pending bit field
	  if (oneHotDecode992[992-992] == 1) data = '0;                               // PBA structure (low)
	  if (oneHotDecode992[993-992] == 1) data = '0;                               // PBA structure (high)
	  //******************************** end of PBA Table
      end
      if (oneHotDecode774[802-774] == 1 && changeFifo.notEmpty())
	 changeFifo.deq();
      readResponseFifo.enq(MemData { data: data, tag: beat.tag, last: beat.last });
   endrule

   rule writeDataRule;
      let beat <- csrWag.addrBeat.get();
      let addr = beat.addr >> 2; // word address

      let modaddr = (addr % 8192);
      let msixaddr = modaddr - `msix_base;

      csrWagBeatFifo.enq(beat);
      csrWagIsMsixAddrFifo.enq(msixaddr >= 0 && msixaddr <= 63);
      Bit#(1024) onehot = (1 << addr[9:0]);
      $display("addr: %h", addr);
      csrWagOneHotFifo768.enq(onehot[775:768]);
      csrWagOneHotFifo792.enq(onehot[794:792]);
   endrule

   rule writeDataRule2;
      let memData <- toGet(writeDataFifo).get();
      let dword = memData.data;

      $display("data: %h, last: %h, tag: %h", dword, memData.last, memData.tag);
      let beat       <- toGet(csrWagBeatFifo).get();
      let isMsixAddr <- toGet(csrWagIsMsixAddrFifo).get();
      let addr = beat.addr >> 2; // word address
      let modaddr = (addr % 8192);
      let msix_base = `msix_base;
      let msixaddr = modaddr - msix_base;
      let oneHotDecode768 <- toGet(csrWagOneHotFifo768).get();
      let oneHotDecode792 <- toGet(csrWagOneHotFifo792).get();

      if (isMsixAddr)
         begin
            let groupaddr = (msixaddr / 4);
            //******************************** area referenced from xilinx_x7_pcie_wrapper.v
            case (msixaddr % 4)
               0: msix_entry[groupaddr].addr_lo  <= (dword & 32'hfffffffc);
               1: msix_entry[groupaddr].addr_hi  <= dword;
               2: msix_entry[groupaddr].msg_data <= dword;
               3: msix_entry[groupaddr].masked <= unpack(dword[0]);
            endcase
         end
      else begin
	 if (oneHotDecode768[775-768] == 1) tlpTracingReg <= (dword != 0) ? True : False;
	 if (oneHotDecode768[768-768] == 1)
	     bramRequestFifo.enq(BRAMRequest{ write: False, responseOnWrite: False, address: truncate(dword), datain: ?});
	 if (oneHotDecode792[792-792] == 1) tlpTraceBramWrAddrReg <= truncate(dword);
	 if (oneHotDecode792[794-792] == 1) tlpTraceLimitReg <= truncate(dword);
      end
      if (beat.last)
	 writeDoneFifo.enq(beat.tag);
   endrule

   interface PhysMemSlave memSlave;
      interface PhysMemReadServer read_server;
	 interface Put readReq;
	    method Action put(PhysMemRequest#(32,32) req);
	       csrRag.request.put(PhysMemRequest { addr: truncate(req.addr), burstLen: req.burstLen, tag: req.tag
`ifdef BYTE_ENABLES
						  , firstbe: req.firstbe, lastbe: req.lastbe
`endif
						  });
	    endmethod
	 endinterface
	 interface Get readData = toGet(readResponseFifo);
   endinterface: read_server

  interface PhysMemWriteServer write_server;
	 interface Put writeReq;
	    method Action put(PhysMemRequest#(32,32) req);
               $display("csrWag Request, addr=%h, burstLen=%h, tag=%h", req.addr, req.burstLen, req.tag);
	       csrWag.request.put(PhysMemRequest { addr: truncate(req.addr), burstLen: req.burstLen, tag: req.tag
`ifdef BYTE_ENABLES
						  , firstbe: req.firstbe, lastbe: req.lastbe
`endif
						  });
	    endmethod
	 endinterface
     interface Put writeData = toPut(writeDataFifo);
     interface Get writeDone = toGet(writeDoneFifo);
   endinterface: write_server
   endinterface
   interface changes = toPipeIn(changeFifo);
   interface TlpTraceClient traceClient;
      interface Reg tlpTracing = tlpTracingReg;
      interface Reg tlpTraceLimit = tlpTraceLimitReg;
      interface Reg tlpTraceBramWrAddr = tlpTraceBramWrAddrReg;
      interface BRAMClient bramClient;
         interface Get request = toGet(bramRequestFifo);
	 interface Put response = toPut(bramResponseFifo);
      endinterface: bramClient
   endinterface: traceClient
   interface Vector msixEntry = map(toReadOnlyMsixEntry, msix_entry);
endmodule: mkPcieControlAndStatusRegs

// 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 BRAM           :: *;
import FIFOF          :: *;
import BRAMFIFO       :: *;
import GetPut         :: *;
import Connectable    :: *;
import PCIE           :: *;
import Clocks         :: *;
import PcieTracer     :: *;
import ConnectalMemTypes       :: *;
import AddressGenerator::*;
import Pipe           :: *;

`include "ConnectalProjectConfig.bsv"

// starting word of MSIX config registers
`define msix_base 4096

// An MSIX table entry, as defined in the PCIe spec
interface MSIX_Entry;
   interface Reg#(Bit#(32)) addr_lo;
   interface Reg#(Bit#(32)) addr_hi;
   interface Reg#(Bit#(32)) msg_data;
   interface Reg#(Bool)     masked;
endinterface

interface ReadOnly_MSIX_Entry;
   interface ReadOnly#(Bit#(32)) addr_lo;
   interface ReadOnly#(Bit#(32)) addr_hi;
   interface ReadOnly#(Bit#(32)) msg_data;
   interface ReadOnly#(Bool)     masked;
endinterface

function ReadOnly_MSIX_Entry toReadOnlyMsixEntry(MSIX_Entry msix);
   return (interface ReadOnly_MSIX_Entry;
	   interface ReadOnly addr_lo = regToReadOnly(msix.addr_lo);
	   interface ReadOnly addr_hi = regToReadOnly(msix.addr_hi);
	   interface ReadOnly msg_data = regToReadOnly(msix.msg_data);
	   interface ReadOnly masked = regToReadOnly(msix.masked);
	   endinterface);
endfunction

// control and status registers accessed from PCIe
interface PcieControlAndStatusRegs;
   interface PhysMemSlave#(32,32) memSlave;
   interface Vector#(16,ReadOnly_MSIX_Entry) msixEntry;
   interface PipeIn#(Bit#(64)) changes;
   interface TlpTraceClient traceClient;
endinterface: PcieControlAndStatusRegs

// This module encapsulates all of the logic for instantiating and
// accessing the control and status registers. It defines the
// registers, the address map, and how the registers respond to reads
// and writes.
(* synthesize *)
module mkPcieControlAndStatusRegs(PcieControlAndStatusRegs);

   // Utility for module creating all of the storage for a single MSIX
   // table entry
   module mkMSIXEntry(MSIX_Entry);
      Reg#(Bit#(32)) _addr_lo  <- mkReg(0);
      Reg#(Bit#(32)) _addr_hi  <- mkReg(0);
      Reg#(Bit#(32)) _msg_data <- mkReg(0);
      Reg#(Bool)     _masked   <- mkReg(True);

      interface addr_lo  = _addr_lo;
      interface addr_hi  = _addr_hi;
      interface msg_data = _msg_data;
      interface masked   = _masked;
   endmodule: mkMSIXEntry

   // Registers and their default values
   Vector#(16,MSIX_Entry) msix_entry              <- replicateM(mkMSIXEntry);
   Reg#(TimestampedTlpData) pcieTraceBramResponse <- mkReg(unpack(0));

   // Function to return a one-word slice of the tlpTraceBramResponse
   function Bit#(32) tlpTraceBramResponseSlice(Reg#(TimestampedTlpData) data, Integer i);
       Bit#(8) i8 = fromInteger(i);
       begin
           Bit#(TMul#(12,32)) v = extend(pack(data));
           return v[31 + (i8*32) : 0 + (i8*32)];
       end
   endfunction

   FIFOF#(BRAMRequest#(Bit#(TAdd#(TlpTraceAddrSize,1)),TimestampedTlpData)) bramRequestFifo <- mkFIFOF();
   FIFOF#(TimestampedTlpData)                                               bramResponseFifo <- mkFIFOF();
   Reg#(Bool)                   tlpTracingReg                <- mkReg(True);
   Reg#(Bit#(TlpTraceAddrSize)) tlpTraceLimitReg             <- mkReg(0);
   Reg#(Bit#(TlpTraceAddrSize)) tlpTraceBramWrAddrReg        <- mkReg(0);
   FIFOF#(Bit#(64))             changeFifo                   <- mkSizedBRAMFIFOF(256);

   // State used to actually service read and write requests
   rule brmMuxResponse;
       let v <- toGet(bramResponseFifo).get();
       pcieTraceBramResponse <= v;
   endrule

   AddressGenerator#(16,32)           csrRag <- mkAddressGenerator;
   AddressGenerator#(16,32)           csrWag <- mkAddressGenerator;
   FIFOF#(MemData#(32))     readResponseFifo <- mkFIFOF();
   FIFOF#(MemData#(32))        writeDataFifo <- mkFIFOF();
   FIFOF#(Bit#(MemTagSize)) writeDoneFifo <- mkFIFOF();

   FIFOF#(AddrBeat#(16)) csrRagBeatFifo <- mkFIFOF();
   FIFOF#(Bool)       csrIsMsixAddrFifo <- mkFIFOF();
   FIFOF#(Bit#(2))     csrOneHotFifo000 <- mkFIFOF();
   FIFOF#(Bit#(29))    csrOneHotFifo774 <- mkFIFOF();
   FIFOF#(Bit#(2))     csrOneHotFifo992 <- mkFIFOF();

   FIFOF#(AddrBeat#(16)) csrWagBeatFifo <- mkFIFOF();
   FIFOF#(Bool)       csrWagIsMsixAddrFifo <- mkFIFOF();
   FIFOF#(Bit#(8))     csrWagOneHotFifo768 <- mkFIFOF();
   FIFOF#(Bit#(3))     csrWagOneHotFifo792 <- mkFIFOF();

   rule readDataRule;
      let beat <- csrRag.addrBeat.get();
      let addr = beat.addr >> 2; // word address
      Bit#(32) data = 0;
      let modaddr = (addr % 8192);
      let msixaddr = modaddr - (`msix_base >> 2);

      csrRagBeatFifo.enq(beat);
      csrIsMsixAddrFifo.enq(msixaddr >= 0 && msixaddr <= 63);
      Bit#(1024) onehot = (1 << addr[9:0]);
      csrOneHotFifo000.enq(onehot[1:0]);
      csrOneHotFifo774.enq(onehot[802:774]);
      csrOneHotFifo992.enq(onehot[993:992]);
   endrule
   rule readDataRule2;
      let beat       <- toGet(csrRagBeatFifo).get();
      let isMsixAddr <- toGet(csrIsMsixAddrFifo).get();
      let addr = beat.addr >> 2; // word address
      Bit#(32) data = 32'hbad0add0;
      let modaddr = (addr % 8192);
      let msix_base = (`msix_base >> 2);
      let msixaddr = modaddr - msix_base;
      let oneHotDecode000 <- toGet(csrOneHotFifo000).get();
      let oneHotDecode774 <- toGet(csrOneHotFifo774).get();
      let oneHotDecode992 <- toGet(csrOneHotFifo992).get();

      if (isMsixAddr) begin
         begin
            let groupaddr = (msixaddr / 4);
            //******************************** msix_base has to match CONFIG.MXIx_Table_Offset in scripts/connectal-synth-pcie.tcl
            case (msixaddr % 4)
               0: data = msix_entry[groupaddr].addr_lo;
               1: data = msix_entry[groupaddr].addr_hi;
               2: data = msix_entry[groupaddr].msg_data;
               3: data = {'0, pack(msix_entry[groupaddr].masked)}; // vector control
               default: data = 32'hbad0add0;
	  //******************************** end of MSIX Table
            endcase
         end
      end
      else begin
	  // board identification
	  if (oneHotDecode000[0] == 1) data = 32'h65756c42; // Blue
	  if (oneHotDecode000[1] == 1) data = 32'h63657073; // spec

	  if (oneHotDecode774[774-774] == 1) data = fromInteger(2**valueOf(TAdd#(TlpTraceAddrSize,1)));
	  if (oneHotDecode774[775-774] == 1) data = (tlpTracingReg ? 1 : 0);
	  if (oneHotDecode774[776-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 0);
	  if (oneHotDecode774[777-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 1);
	  if (oneHotDecode774[778-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 2);
	  if (oneHotDecode774[779-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 3);
	  if (oneHotDecode774[780-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 4);
	  if (oneHotDecode774[781-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 5);
	  if (oneHotDecode774[792-774] == 1) data = extend(tlpTraceBramWrAddrReg);
	  if (oneHotDecode774[794-774] == 1) data = extend(tlpTraceLimitReg);
	  if (oneHotDecode774[795-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 6);
	  if (oneHotDecode774[796-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 7);
	  if (oneHotDecode774[797-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 8);
	  if (oneHotDecode774[798-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 9);
	  if (oneHotDecode774[799-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 10);
	  if (oneHotDecode774[800-774] == 1) data = tlpTraceBramResponseSlice(pcieTraceBramResponse, 11);
   	  if (oneHotDecode774[801-774] == 1) data = (changeFifo.notEmpty()) ? (changeFifo.first()[31:0]) : 0;
   	  if (oneHotDecode774[802-774] == 1) data = (changeFifo.notEmpty()) ? (changeFifo.first()[63:32]) : 0;

         //******************************** msix_base has to match CONFIG.MXIx_PBA_Offset in scripts/connectal-synth-pcie.tcl
	  // 16-bit MSIx pending bit field
	  if (oneHotDecode992[992-992] == 1) data = '0;                               // PBA structure (low)
	  if (oneHotDecode992[993-992] == 1) data = '0;                               // PBA structure (high)
	  //******************************** end of PBA Table
      end
      if (oneHotDecode774[802-774] == 1 && changeFifo.notEmpty())
	 changeFifo.deq();
      readResponseFifo.enq(MemData { data: data, tag: beat.tag, last: beat.last });
   endrule

   rule writeDataRule;
      let beat <- csrWag.addrBeat.get();
      let addr = beat.addr >> 2; // word address

      let modaddr = (addr % 8192);
      let msixaddr = modaddr - `msix_base;

      csrWagBeatFifo.enq(beat);
      csrWagIsMsixAddrFifo.enq(msixaddr >= 0 && msixaddr <= 63);
      Bit#(1024) onehot = (1 << addr[9:0]);
      $display("addr: %h", addr);
      csrWagOneHotFifo768.enq(onehot[775:768]);
      csrWagOneHotFifo792.enq(onehot[794:792]);
   endrule

   rule writeDataRule2;
      let memData <- toGet(writeDataFifo).get();
      let dword = memData.data;

      $display("data: %h, last: %h, tag: %h", dword, memData.last, memData.tag);
      let beat       <- toGet(csrWagBeatFifo).get();
      let isMsixAddr <- toGet(csrWagIsMsixAddrFifo).get();
      let addr = beat.addr >> 2; // word address
      let modaddr = (addr % 8192);
      let msix_base = `msix_base;
      let msixaddr = modaddr - msix_base;
      let oneHotDecode768 <- toGet(csrWagOneHotFifo768).get();
      let oneHotDecode792 <- toGet(csrWagOneHotFifo792).get();

      if (isMsixAddr)
         begin
            let groupaddr = (msixaddr / 4);
            //******************************** area referenced from xilinx_x7_pcie_wrapper.v
            case (msixaddr % 4)
               0: msix_entry[groupaddr].addr_lo  <= (dword & 32'hfffffffc);
               1: msix_entry[groupaddr].addr_hi  <= dword;
               2: msix_entry[groupaddr].msg_data <= dword;
               3: msix_entry[groupaddr].masked <= unpack(dword[0]);
            endcase
         end
      else begin
	 if (oneHotDecode768[775-768] == 1) tlpTracingReg <= (dword != 0) ? True : False;
	 if (oneHotDecode768[768-768] == 1)
	     bramRequestFifo.enq(BRAMRequest{ write: False, responseOnWrite: False, address: truncate(dword), datain: ?});
	 if (oneHotDecode792[792-792] == 1) tlpTraceBramWrAddrReg <= truncate(dword);
	 if (oneHotDecode792[794-792] == 1) tlpTraceLimitReg <= truncate(dword);
      end
      if (beat.last)
	 writeDoneFifo.enq(beat.tag);
   endrule

   interface PhysMemSlave memSlave;
      interface PhysMemReadServer read_server;
	 interface Put readReq;
	    method Action put(PhysMemRequest#(32,32) req);
	       csrRag.request.put(PhysMemRequest { addr: truncate(req.addr), burstLen: req.burstLen, tag: req.tag
`ifdef BYTE_ENABLES
						  , firstbe: req.firstbe, lastbe: req.lastbe
`endif
						  });
	    endmethod
	 endinterface
	 interface Get readData = toGet(readResponseFifo);
   endinterface: read_server

  interface PhysMemWriteServer write_server;
	 interface Put writeReq;
	    method Action put(PhysMemRequest#(32,32) req);
               $display("csrWag Request, addr=%h, burstLen=%h, tag=%h", req.addr, req.burstLen, req.tag);
	       csrWag.request.put(PhysMemRequest { addr: truncate(req.addr), burstLen: req.burstLen, tag: req.tag
`ifdef BYTE_ENABLES
						  , firstbe: req.firstbe, lastbe: req.lastbe
`endif
						  });
	    endmethod
	 endinterface
     interface Put writeData = toPut(writeDataFifo);
     interface Get writeDone = toGet(writeDoneFifo);
   endinterface: write_server
   endinterface
   interface changes = toPipeIn(changeFifo);
   interface TlpTraceClient traceClient;
      interface Reg tlpTracing = tlpTracingReg;
      interface Reg tlpTraceLimit = tlpTraceLimitReg;
      interface Reg tlpTraceBramWrAddr = tlpTraceBramWrAddrReg;
      interface BRAMClient bramClient;
         interface Get request = toGet(bramRequestFifo);
	 interface Put response = toPut(bramResponseFifo);
      endinterface: bramClient
   endinterface: traceClient
   interface Vector msixEntry = map(toReadOnlyMsixEntry, msix_entry);
endmodule: mkPcieControlAndStatusRegs


import MCSAlgorithm

import MCSAlgorithm

// 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::*;

module mkHirschB#(BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strA, BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strB, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) matL)(MCSAlgorithm)
         provisos(Add#(0, 7, strIndexWidth),
	       Add#(0, 14, lIndexWidth));

    Reg#(Bit#(7)) aLenReg <- mkReg(0);
  Reg#(Bit#(7)) bLenReg <- mkReg(0);
  Reg#(Bit#(14)) rLenReg <- 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#(16)) k1jm1 <- mkReg(0);
  Reg#(Bit#(16)) k0j <- mkReg(0);

  Stmt hirschB =
   seq
      /* initialize two rows of temporary storage */
      for (jj <= 0; jj < aLenReg; jj <= jj + 1)
	 seq
	    matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: 0});
	    matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {1,jj}, datain: 0});
	 endseq
      /* Loop through string a */
      for (ii <= 1; ii <= aLenReg; ii <= ii + 1)
	 seq
	    /* Copy L[1] to L[0].  could pingpong instead, or unroll loop */
	    for (jj <= 0; jj <= bLenReg; jj <= jj + 1)
	       seq
		  matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {0,jj}, datain: 0});
		  action
		     let ta <- matL.response.get();
		     matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {1,jj}, datain: ta});
		  endaction
	       endseq
	    /* Loop through string B */
	    for (jj <= 0; jj <= bLenReg; jj <= jj + 1)
	       seq
		  /* Read a[i] and b[j] */
		  strA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: ii-1, datain: 0});
		  strB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: jj-1, datain: 0});
		  action
		     let ta <- strA.response.get();
		     let tb <- strB.response.get();
		     aData <= ta;
		     bData <= tb;
		  endaction
		  if (aData == bData)
		     seq
			matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {1,jj-1}, datain: 0});
			action
			   let ta <- matL.response.get();
			   matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: ta + 1});
			endaction
		     endseq
		  else
		     seq
			/* read K[0][j] and K[1][j-1] */
			matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {1,jj}, datain: 0});
			action
			   let ta <- matL.response.get();
			   k0j <= ta;
			endaction
			matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {0,jj-1}, datain: 0});
			action
			   let ta <- matL.response.get();
			   k1jm1 <= ta;
			endaction
			matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: max(k0j,k1jm1)});
		     endseq
		  endseq
	 endseq
   endseq;

   FSM hB <- mkFSM(hirschB);

   method Action setupA(Bit#(7) strLen);
      strLenA <= strLen;
   endmethod

   method Action setupB(Bit#(7) strLen);
      strLenB <= strLen;
   endmethod

   interface FSM fsm = hB;

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::*;

module mkHirschB#(BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strA, BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strB, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) matL)(MCSAlgorithm)
         provisos(Add#(0, 7, strIndexWidth),
	       Add#(0, 14, lIndexWidth));

    Reg#(Bit#(7)) aLenReg <- mkReg(0);
  Reg#(Bit#(7)) bLenReg <- mkReg(0);
  Reg#(Bit#(14)) rLenReg <- 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#(16)) k1jm1 <- mkReg(0);
  Reg#(Bit#(16)) k0j <- mkReg(0);

  Stmt hirschB =
   seq
      /* initialize two rows of temporary storage */
      for (jj <= 0; jj < aLenReg; jj <= jj + 1)
	 seq
	    matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: 0});
	    matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {1,jj}, datain: 0});
	 endseq
      /* Loop through string a */
      for (ii <= 1; ii <= aLenReg; ii <= ii + 1)
	 seq
	    /* Copy L[1] to L[0].  could pingpong instead, or unroll loop */
	    for (jj <= 0; jj <= bLenReg; jj <= jj + 1)
	       seq
		  matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {0,jj}, datain: 0});
		  action
		     let ta <- matL.response.get();
		     matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {1,jj}, datain: ta});
		  endaction
	       endseq
	    /* Loop through string B */
	    for (jj <= 0; jj <= bLenReg; jj <= jj + 1)
	       seq
		  /* Read a[i] and b[j] */
		  strA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: ii-1, datain: 0});
		  strB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: jj-1, datain: 0});
		  action
		     let ta <- strA.response.get();
		     let tb <- strB.response.get();
		     aData <= ta;
		     bData <= tb;
		  endaction
		  if (aData == bData)
		     seq
			matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {1,jj-1}, datain: 0});
			action
			   let ta <- matL.response.get();
			   matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: ta + 1});
			endaction
		     endseq
		  else
		     seq
			/* read K[0][j] and K[1][j-1] */
			matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {1,jj}, datain: 0});
			action
			   let ta <- matL.response.get();
			   k0j <= ta;
			endaction
			matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {0,jj-1}, datain: 0});
			action
			   let ta <- matL.response.get();
			   k1jm1 <= ta;
			endaction
			matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: max(k0j,k1jm1)});
		     endseq
		  endseq
	 endseq
   endseq;

   method Action setupA(Bit#(7) strLen);
      strLenA <= strLen;
   endmethod

   method Action setupB(Bit#(7) strLen);
      strLenB <= strLen;
   endmethod

   FSM fsm <- mkFSM(hirschB);

endmodule


optimizations for hirschb

optimizations for hirschb

// 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::*;

module mkHirschB#(BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strA, BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strB, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) matL)(MCSAlgorithm)
         provisos(Add#(0, 7, strIndexWidth),
	       Add#(0, 14, lIndexWidth));

    Reg#(Bit#(7)) aLenReg <- mkReg(0);
  Reg#(Bit#(7)) bLenReg <- mkReg(0);
  Reg#(Bit#(14)) rLenReg <- 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#(16)) k1j <- mkReg(0);
   Reg#(Bit#(16)) k1jm1 <- mkReg(0);
  Reg#(Bit#(16)) k0j <- mkReg(0);
  Reg#(Bit#(16)) k0jm1 <- mkReg(0);

  Stmt hirschB =
   seq
      $display("hirschB running ");
      /* initialize two rows of temporary storage */
      for (jj <= 0; jj < aLenReg; jj <= jj + 1)
	 seq
	    matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: 0});
	    matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {1,jj}, datain: 0});
	 endseq
      /* Loop through string a */
      for (ii <= 1; ii <= aLenReg; ii <= ii + 1)
	 seq
	    //$display("hirschB ii = %d", ii);
	    /* Copy L[1] to L[0].  could pingpong instead, or unroll loop */
	    /* L[1] is stored in matL[0] and L[0] is stored in matL[1] so that the result is in the right place at the end */
	    for (jj <= 0; jj <= bLenReg; jj <= jj + 1)
	       seq
		  matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {0,jj}, datain: 0});
		  action
		     let ta <- matL.response.get();
		     matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {1,jj}, datain: ta});
		  endaction
	       endseq
	    /* initialize pipelining */
	    k0j <= 0;
	    k1j <= 0;
	    /* Loop through string B */
	    for (jj <= 1; jj <= bLenReg; jj <= jj + 1)
	       seq
		  action
		     /* Read a[i] and b[j] */
		     strA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: ii-1, datain: 0});
		     strB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: jj-1, datain: 0});
		     k0jm1 <= k0j;  /* pipeline from previous cycle */
		     k1jm1 <= k1j;
		     /* start read of k0j */
		     matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {1,jj}, datain: 0});
		  endaction
		  action
		     let ta <- strA.response.get();
		     let tb <- strB.response.get();
		     let tk <- matL.response.get();
		     aData <= ta;
		     bData <= tb;
		     k0j <= tk;
		  endaction
		  /* $display("hirschB ii %d jj %d A %d B %d", ii, jj, aData, bData);	*/
		  if (aData == bData)
		     action
			k1j <= k0jm1 + 1;
			/*$display("   EQ L[%d][%d] = %d", ii, jj, ta+1); */
		     endaction
		  else
		     action
			let tmax = max(k0j,k1jm1);
			//$display("     L[%d][%d] = %d = max(%d, %d)", ii, jj, tmax, k0j, k1jm1);
			k1j <= tmax;
		     endaction
		  matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: k1j});

	       endseq
	 endseq
   endseq;

   FSM hB <- mkFSM(hirschB);

   method Action setupA(Bit#(7) strLen);
      aLenReg <= strLen;
   endmethod

   method Action setupB(Bit#(7) strLen);
      bLenReg <= strLen;
   endmethod

   interface FSM fsm = hB;

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::*;

module mkHirschB#(BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strA, BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strB, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) matL)(MCSAlgorithm)
         provisos(Add#(0, 7, strIndexWidth),
	       Add#(0, 14, lIndexWidth));

    Reg#(Bit#(7)) aLenReg <- mkReg(0);
  Reg#(Bit#(7)) bLenReg <- mkReg(0);
  Reg#(Bit#(14)) rLenReg <- 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#(16)) k1jm1 <- mkReg(0);
  Reg#(Bit#(16)) k0j <- mkReg(0);

  Stmt hirschB =
   seq
      $display("hirschB running ");
      /* initialize two rows of temporary storage */
      for (jj <= 0; jj < aLenReg; jj <= jj + 1)
	 seq
	    matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: 0});
	    matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {1,jj}, datain: 0});
	 endseq
      /* Loop through string a */
      for (ii <= 1; ii <= aLenReg; ii <= ii + 1)
	 seq
	    //$display("hirschB ii = %d", ii);
	    /* Copy L[1] to L[0].  could pingpong instead, or unroll loop */
	    /* L[1] is stored in matL[0] and L[0] is stored in matL[1] so that the result is in the right place at the end */
	    for (jj <= 0; jj <= bLenReg; jj <= jj + 1)
	       seq
		  matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {0,jj}, datain: 0});
		  action
		     let ta <- matL.response.get();
		     matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {1,jj}, datain: ta});
		  endaction
	       endseq
	    /* Loop through string B */
	    for (jj <= 1; jj <= bLenReg; jj <= jj + 1)
	       seq
		  /* Read a[i] and b[j] */
		  strA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: ii-1, datain: 0});
		  strB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: jj-1, datain: 0});
		  action
		     let ta <- strA.response.get();
		     let tb <- strB.response.get();
		     aData <= ta;
		     bData <= tb;
		  endaction
		  //$display("hirschB ii %d jj %d A %d B %d", ii, jj, aData, bData);
		  if (aData == bData)
		     seq
			matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {1,jj-1}, datain: 0});
			action
			   let ta <- matL.response.get();
			   //$display("   EQ L[%d][%d] = %d", ii, jj, ta+1);

			   matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: ta + 1});
			endaction
		     endseq
		  else
		     seq
			/* read K[0][j] and K[1][j-1] */
			matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {1,jj}, datain: 0});
			action
			   let ta <- matL.response.get();
			   k0j <= ta;
			endaction
			matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {0,jj-1}, datain: 0});
			action
			   let ta <- matL.response.get();
			   k1jm1 <= ta;
			endaction
			action
			   let tmax = max(k0j,k1jm1);
			   //$display("     L[%d][%d] = %d = max(%d, %d)", ii, jj, tmax, k0j, k1jm1);
			   matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: tmax});
			endaction
		     endseq
		  endseq
	 endseq
   endseq;

   FSM hB <- mkFSM(hirschB);

   method Action setupA(Bit#(7) strLen);
      aLenReg <= strLen;
   endmethod

   method Action setupB(Bit#(7) strLen);
      bLenReg <= strLen;
   endmethod

   interface FSM fsm = hB;

endmodule


Testing simpler AxiScratchPad for now

Testing simpler AxiScratchPad for now

import SceMi      :: *;
import Kintex7PcieBridge:: *;

// Setup for PCIE to a Kintex7
import Xilinx         :: *;
import XilinxPCIE     :: *;
import Clocks         :: *;
import DefaultValue   :: *;
import Connectable    :: *;
import CommitIfc      :: *;
import TieOff         :: *;
import Memory         :: *;
import GetPut         :: *;
import ClientServer   :: *;
import BUtils         :: *;
import AxiMasterSlave :: *;
import EchoWrapper    :: *;
import AxiScratchPad  :: *;

(* synthesize, no_default_clock, no_default_reset *)
module mkBridge #(Clock pci_sys_clk_p, Clock pci_sys_clk_n,
		  Clock sys_clk_p,     Clock sys_clk_n,
		  Clock user_clk_p, Clock user_clk_n,
		  Reset pci_sys_reset_n)
                 (KC705_FPGA_DDR3);

   Clock sys_clk <- mkClockIBUFDS(sys_clk_p, sys_clk_n);
   Clock user_clk <- mkClockIBUFDS(user_clk_p, user_clk_n);

   ClockGenerator7Params clk_params = defaultValue();
   clk_params.clkin1_period     = 5.000;       // 200 MHz reference
   clk_params.clkin_buffer      = False;       // necessary buffer is instanced above
   clk_params.reset_stages      = 0;           // no sync on reset so input clock has pll as only load
   clk_params.clkfbout_mult_f   = 5.000;       // 1000 MHz VCO
   clk_params.clkout0_divide_f  = `SCEMI_CLOCK_PERIOD;
   clk_params.clkout1_divide    = 5;           // ddr3 reference clock (200 MHz)

   ClockGenerator7 clk_gen <- mkClockGenerator7(clk_params, clocked_by sys_clk, reset_by pci_sys_reset_n);

   Clock clk = clk_gen.clkout0;
   Reset rst_n <- mkAsyncReset( 1, pci_sys_reset_n, clk );
   Reset ddr3ref_rst_n <- mkAsyncReset( 1, rst_n, clk_gen.clkout1 );

   DDR3_Configure_K7 ddr3_cfg;
   ddr3_cfg.num_reads_in_flight = 2;   // adjust as needed
   ddr3_cfg.fast_train_sim_only = False; // adjust if simulating

   DDR3_Controller_K7 ddr3_ctrl <- mkKintex7DDR3Controller(ddr3_cfg, clocked_by clk_gen.clkout1, reset_by ddr3ref_rst_n);

   // ddr3_ctrl.user needs to connect to user logic and should use ddr3clk and ddr3rstn
   Clock ddr3clk = ddr3_ctrl.user.clock;
   Reset ddr3rstn = ddr3_ctrl.user.reset_n;

   K7PcieBridgeIfc#(8) k7pcie <- mkK7PcieBridge( pci_sys_clk_p, pci_sys_clk_n, pci_sys_reset_n, clk_gen.clkout0,
                                                 64'h05ce_0006_7050_2602 );

   SyncFIFOIfc#(MemoryRequest#(32,256)) fMemReq <- mkSyncFIFO(1, clk, rst_n, ddr3clk);
   SyncFIFOIfc#(MemoryResponse#(256))   fMemResp <- mkSyncFIFO(1, ddr3clk, ddr3rstn, clk);

   let memclient = interface Client;
		      interface request  = toGet(fMemReq);
		      interface response = toPut(fMemResp);
		   endinterface;

   mkConnection( memclient, ddr3_ctrl.user, clocked_by ddr3clk, reset_by ddr3rstn );

   ReadOnly#(Bool) _isLinkUp         <- mkNullCrossing(noClock, k7pcie.isLinkUp);
   ReadOnly#(Bool) _isCalibrated     <- mkNullCrossing(noClock, ddr3_ctrl.user.init_done);

   AxiScratchPad echoWrapper <- mkAxiScratchPad(clocked_by k7pcie.clock125, reset_by k7pcie.reset125);
   mkConnection(k7pcie.portal0, echoWrapper.ctrl, clocked_by k7pcie.clock125, reset_by k7pcie.reset125);

   interface pcie = k7pcie.pcie;
   interface ddr3 = ddr3_ctrl.ddr3;
   method leds = zeroExtend({ pack(_isCalibrated)
			     ,pack(False)
			     ,pack(False)
			     ,pack(_isLinkUp)
			     });
endmodule: mkBridge

instance Connectable#(MemoryClient#(32, 256), DDR3_User_K7);
   module mkConnection#(MemoryClient#(32, 256) client, DDR3_User_K7 ddr3)(Empty);
      rule connect_requests;
	 let request <- client.request.get;
	 Bit#(28) address = truncate(request.address) << 2;
	 Bool     addrhi  = unpack(request.address[0]);
	 Bit#(64) writeen = addrhi ? zeroExtend(request.byteen) << 32 : zeroExtend(request.byteen);
	 Bit#(512) datain = duplicate(request.data);
	 if (request.write) begin
	    ddr3.request(address, writeen, datain);
	 end
	 else begin
	    ddr3.request(address, 0, ?);
	 end
      endrule

      rule connect_responses;
	 let response <- ddr3.read_data;
	 Bit#(256) data = truncate(response);
	 client.response.put(unpack(data));
      endrule
   endmodule
endinstance

import SceMi      :: *;
import Kintex7PcieBridge:: *;

// Setup for PCIE to a Kintex7
import Xilinx         :: *;
import XilinxPCIE     :: *;
import Clocks         :: *;
import DefaultValue   :: *;
import Connectable    :: *;
import CommitIfc      :: *;
import TieOff         :: *;
import Memory         :: *;
import GetPut         :: *;
import ClientServer   :: *;
import BUtils         :: *;
import AxiMasterSlave :: *;
import EchoWrapper    :: *;

(* synthesize, no_default_clock, no_default_reset *)
module mkBridge #(Clock pci_sys_clk_p, Clock pci_sys_clk_n,
		  Clock sys_clk_p,     Clock sys_clk_n,
		  Clock user_clk_p, Clock user_clk_n,
		  Reset pci_sys_reset_n)
                 (KC705_FPGA_DDR3);

   Clock sys_clk <- mkClockIBUFDS(sys_clk_p, sys_clk_n);
   Clock user_clk <- mkClockIBUFDS(user_clk_p, user_clk_n);

   ClockGenerator7Params clk_params = defaultValue();
   clk_params.clkin1_period     = 5.000;       // 200 MHz reference
   clk_params.clkin_buffer      = False;       // necessary buffer is instanced above
   clk_params.reset_stages      = 0;           // no sync on reset so input clock has pll as only load
   clk_params.clkfbout_mult_f   = 5.000;       // 1000 MHz VCO
   clk_params.clkout0_divide_f  = `SCEMI_CLOCK_PERIOD;
   clk_params.clkout1_divide    = 5;           // ddr3 reference clock (200 MHz)

   ClockGenerator7 clk_gen <- mkClockGenerator7(clk_params, clocked_by sys_clk, reset_by pci_sys_reset_n);

   Clock clk = clk_gen.clkout0;
   Reset rst_n <- mkAsyncReset( 1, pci_sys_reset_n, clk );
   Reset ddr3ref_rst_n <- mkAsyncReset( 1, rst_n, clk_gen.clkout1 );

   DDR3_Configure_K7 ddr3_cfg;
   ddr3_cfg.num_reads_in_flight = 2;   // adjust as needed
   ddr3_cfg.fast_train_sim_only = False; // adjust if simulating

   DDR3_Controller_K7 ddr3_ctrl <- mkKintex7DDR3Controller(ddr3_cfg, clocked_by clk_gen.clkout1, reset_by ddr3ref_rst_n);

   // ddr3_ctrl.user needs to connect to user logic and should use ddr3clk and ddr3rstn
   Clock ddr3clk = ddr3_ctrl.user.clock;
   Reset ddr3rstn = ddr3_ctrl.user.reset_n;

   K7PcieBridgeIfc#(8) k7pcie <- mkK7PcieBridge( pci_sys_clk_p, pci_sys_clk_n, pci_sys_reset_n, clk_gen.clkout0,
                                                 64'h05ce_0006_7050_2600 );

   SyncFIFOIfc#(MemoryRequest#(32,256)) fMemReq <- mkSyncFIFO(1, clk, rst_n, ddr3clk);
   SyncFIFOIfc#(MemoryResponse#(256))   fMemResp <- mkSyncFIFO(1, ddr3clk, ddr3rstn, clk);

   let memclient = interface Client;
		      interface request  = toGet(fMemReq);
		      interface response = toPut(fMemResp);
		   endinterface;

   mkConnection( memclient, ddr3_ctrl.user, clocked_by ddr3clk, reset_by ddr3rstn );

   ReadOnly#(Bool) _isLinkUp         <- mkNullCrossing(noClock, k7pcie.isLinkUp);
   ReadOnly#(Bool) _isCalibrated     <- mkNullCrossing(noClock, ddr3_ctrl.user.init_done);

   EchoWrapper echoWrapper <- mkEchoWrapper(clocked_by k7pcie.clock125, reset_by k7pcie.reset125);
   mkConnection(k7pcie.portal0, echoWrapper.ctrl, clocked_by k7pcie.clock125, reset_by k7pcie.reset125);

   interface pcie = k7pcie.pcie;
   interface ddr3 = ddr3_ctrl.ddr3;
   method leds = zeroExtend({ pack(_isCalibrated)
			     ,pack(False)
			     ,pack(False)
			     ,pack(_isLinkUp)
			     });
endmodule: mkBridge

instance Connectable#(MemoryClient#(32, 256), DDR3_User_K7);
   module mkConnection#(MemoryClient#(32, 256) client, DDR3_User_K7 ddr3)(Empty);
      rule connect_requests;
	 let request <- client.request.get;
	 Bit#(28) address = truncate(request.address) << 2;
	 Bool     addrhi  = unpack(request.address[0]);
	 Bit#(64) writeen = addrhi ? zeroExtend(request.byteen) << 32 : zeroExtend(request.byteen);
	 Bit#(512) datain = duplicate(request.data);
	 if (request.write) begin
	    ddr3.request(address, writeen, datain);
	 end
	 else begin
	    ddr3.request(address, 0, ?);
	 end
      endrule

      rule connect_responses;
	 let response <- ddr3.read_data;
	 Bit#(256) data = truncate(response);
	 client.response.put(unpack(data));
      endrule
   endmodule
endinstance