attempt to instantiate fclk1

attempt to instantiate fclk1

Change-Id: I7509f131b56599c54e4678f91f12af2ed7784bfe

// 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 Clocks :: *;
import Vector            :: *;
import Connectable       :: *;
import Portal            :: *;
import Leds              :: *;
import Top               :: *;
import AxiMasterSlave    :: *;
import XbsvXilinxCells   :: *;
import PS7LIB::*;
import PPS7LIB::*;
import XADC::*;
import BRAM::*;
import Bscan::*;
import FIFOF::*;

//`define TRACE_AXI
//`define AXI_READ_TIMING

(* always_ready, always_enabled *)
interface ZynqTop#(type pins);
   (* prefix="" *)
   interface ZynqPins zynq;
   (* prefix="GPIO" *)
   interface LEDS             leds;
   (* prefix="XADC" *)
   interface XADC             xadc;
   interface pins             pins;
   interface Clock unused_clock0;
   interface Clock unused_clock1;
   interface Reset unused_reset0;
   interface Reset unused_reset1;
endinterface

typedef (function Module#(PortalTop#(32, 64, ipins)) mkpt(Clock clk1)) MkPortalTop#(type ipins);

module [Module] mkZynqTopFromPortal#(MkPortalTop#(ipins) constructor)(ZynqTop#(ipins));
   B2C mainclock <- mkB2C();
   B2C fclk1 <- mkB2C(clocked_by mainclock.c, reset_by mainclock.r);
   PS7 ps7 <- mkPS7(mainclock.c, mainclock.r, clocked_by mainclock.c, reset_by mainclock.r);

   let top <- constructor(fclk1.c, clocked_by mainclock.c, reset_by mainclock.r);
   Reg#(Bit#(8)) addrReg <- mkReg(9, clocked_by mainclock.c, reset_by mainclock.r);
   BscanBram#(Bit#(8), Bit#(64)) bscanBram <- mkBscanBram(1, addrReg, clocked_by mainclock.c, reset_by mainclock.r);
   BRAM_Configure bramCfg = defaultValue;
   bramCfg.memorySize = 256;
   bramCfg.latency = 1;
   BRAM2Port#(Bit#(8), Bit#(64)) traceBram <- mkSyncBRAM2Server(bramCfg, mainclock.c, mainclock.r,
								bscanBram.jtagClock, bscanBram.jtagReset);
   mkConnection(bscanBram.bramClient, traceBram.portB);

   ReadOnly#(Bit#(4)) debugReg <- mkNullCrossingWire(mainclock.c, bscanBram.debug());

   let interrupt_bit = top.interrupt ? 1'b1 : 1'b0;

`ifndef TRACE_AXI
   mkConnection(ps7.m_axi_gp[0].client, top.ctrl);
`else

   Vector#(5, FIFOF#(Bit#(64))) bscan_fifos <- replicateM(mkFIFOF(clocked_by mainclock.c, reset_by mainclock.r));

   rule write_bscanBram;
      Bit#(64) data = ?;
      if (bscan_fifos[0].notEmpty) begin
	 data = bscan_fifos[0].first;
	 bscan_fifos[0].deq;
      end
      else if (bscan_fifos[1].notEmpty) begin
	 data = bscan_fifos[1].first;
	 bscan_fifos[1].deq;
      end
      else if (bscan_fifos[2].notEmpty) begin
	 data = bscan_fifos[2].first;
	 bscan_fifos[2].deq;
      end
      else if (bscan_fifos[3].notEmpty) begin
	 data = bscan_fifos[3].first;
	 bscan_fifos[3].deq;
      end
      else begin
	 data = bscan_fifos[4].first;
	 bscan_fifos[4].deq;
      end
      traceBram.portA.request.put(BRAMRequest {write:True, responseOnWrite:False, address:addrReg, datain:data});
      addrReg <= addrReg + 1;
   endrule
   Reg#(Bit#(16)) seqCounter <- mkReg(0, clocked_by mainclock.c, reset_by mainclock.r);
   rule seqinc;
       seqCounter <= seqCounter + 1;
   endrule

   // AXI trace for JTAG
   let m = ps7.m_axi_gp[0].client;
   let s = top.ctrl;
   //mkConnection(m.req_ar, s.req_ar);
   rule connect_req_ar;
       let req <- m.req_ar.get();
       s.req_ar.put(req);
       bscan_fifos[0].enq(
	   {3'h1, interrupt_bit, req.id,
`ifdef AXI_READ_TIMING
                    seqCounter,
`else
                    req.len, req.cache, req.prot, req.size,
                    pack(req.burst == 2'b01), pack(req.lock == 0 && req.qos == 0),
`endif
                    req.address});
   endrule
   //mkConnection(s.resp_read, m.resp_read);
   rule connect_resp_read;
       let resp <- s.resp_read.get();
       m.resp_read.put(resp);
       bscan_fifos[1].enq(
           {3'h2, interrupt_bit, resp.id, resp.resp, resp.last, 13'b0, resp.data});
   endrule
   //mkConnection(m.req_aw, s.req_aw);
   rule connect_req_aw;
       let req <- m.req_aw.get();
       s.req_aw.put(req);
       bscan_fifos[2].enq(
           {3'h3, interrupt_bit, req.id, req.len, req.cache, req.prot, req.size,
                    pack(req.burst == 2'b01), pack(req.lock == 0 && req.qos == 0), req.address});
   endrule
   //mkConnection(m.resp_write, s.resp_write);
   rule connect_resp_write;
       let resp <- m.resp_write.get();
       s.resp_write.put(resp);
       bscan_fifos[3].enq(
           {3'h4, interrupt_bit, resp.id, resp.last, resp.byteEnable, 11'b0, resp.data});
   endrule
   //mkConnection(s.resp_b, m.resp_b);
   rule connect_resp_b;
       let resp <- s.resp_b.get();
       m.resp_b.put(resp);
       bscan_fifos[4].enq(
           {3'h5, interrupt_bit, resp.id, resp.resp, 46'b0});
   endrule
`endif

   mkConnection(top.m_axi, ps7.s_axi_hp[0].axi.server);
   rule send_int_rule;
       ps7.interrupt(interrupt_bit);
   endrule

   rule b2c_rule;
       mainclock.inputclock(ps7.fclkclk()[0]);
       mainclock.inputreset(ps7.fclkresetn()[0]);
   endrule
   rule b2c_rule1;
       fclk1.inputclock(ps7.fclkclk()[1]);
       fclk1.inputreset(ps7.fclkresetn()[1]);
   endrule

   interface zynq = ps7.pins;
   interface leds = top.leds;
   interface XADC xadc;
       method Bit#(4) gpio;
           return debugReg;
`ifdef BOZOIFDEF
           return {interrupt_bit,
                 pack((ps7.debug.arvalid == 1)
                   && (ps7.debug.araddr[18:16] == 3'd1)   // /dev/fpga1
                   && (ps7.debug.araddr[15:14] == 2'd2)   // indication
                   && (ps7.debug.araddr[13:8] == 6'd1)),  //     #1
                 ps7.debug.rvalid,
                 pack((ps7.debug.awvalid == 1)
                   && (ps7.debug.awaddr[18:16] == 3'd2)   // /dev/fpga2
                   && (ps7.debug.awaddr[15:14] == 2'd0)   // request
                   && (ps7.debug.awaddr[13:8] == 6'd1))}; //     #1
`endif
       endmethod
   endinterface
   interface pins = top.pins;
   interface unused_clock0 = mainclock.c;
   interface unused_reset0 = mainclock.r;
   interface unused_clock1 = fclk1.c;
   interface unused_reset1 = fclk1.r;
endmodule

module mkZynqTopClk1(ZynqTop#(Empty));
   let top <- mkZynqTopFromPortal(mkPortalTop);
   return top;
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 Clocks :: *;
import Vector            :: *;
import Connectable       :: *;
import Portal            :: *;
import Leds              :: *;
import Top               :: *;
import AxiMasterSlave    :: *;
import XbsvXilinxCells   :: *;
import PS7LIB::*;
import PPS7LIB::*;
import XADC::*;
import BRAM::*;
import Bscan::*;
import FIFOF::*;

//`define TRACE_AXI
//`define AXI_READ_TIMING

(* always_ready, always_enabled *)
interface ZynqTop#(type pins);
   (* prefix="" *)
   interface ZynqPins zynq;
   (* prefix="GPIO" *)
   interface LEDS             leds;
   (* prefix="XADC" *)
   interface XADC             xadc;
   interface pins             pins;
   interface Clock unused_clock;
   interface Reset unused_reset;
endinterface

typedef (function Module#(PortalTop#(32, 64, ipins)) mkpt(Clock clk1)) MkPortalTop#(type ipins);

module [Module] mkZynqTopFromPortal#(MkPortalTop#(ipins) constructor)(ZynqTop#(ipins));
   B2C mainclock <- mkB2C();
   PS7 ps7 <- mkPS7(mainclock.c, mainclock.r, clocked_by mainclock.c, reset_by mainclock.r);
   let top <- constructor(ps7.fclk_clk1, clocked_by mainclock.c, reset_by mainclock.r);
   Reg#(Bit#(8)) addrReg <- mkReg(9, clocked_by mainclock.c, reset_by mainclock.r);
   BscanBram#(Bit#(8), Bit#(64)) bscanBram <- mkBscanBram(1, addrReg, clocked_by mainclock.c, reset_by mainclock.r);
   BRAM_Configure bramCfg = defaultValue;
   bramCfg.memorySize = 256;
   bramCfg.latency = 1;
   BRAM2Port#(Bit#(8), Bit#(64)) traceBram <- mkSyncBRAM2Server(bramCfg, mainclock.c, mainclock.r,
								bscanBram.jtagClock, bscanBram.jtagReset);
   mkConnection(bscanBram.bramClient, traceBram.portB);

   ReadOnly#(Bit#(4)) debugReg <- mkNullCrossingWire(mainclock.c, bscanBram.debug());

   let interrupt_bit = top.interrupt ? 1'b1 : 1'b0;

`ifndef TRACE_AXI
   mkConnection(ps7.m_axi_gp[0].client, top.ctrl);
`else

   Vector#(5, FIFOF#(Bit#(64))) bscan_fifos <- replicateM(mkFIFOF(clocked_by mainclock.c, reset_by mainclock.r));

   rule write_bscanBram;
      Bit#(64) data = ?;
      if (bscan_fifos[0].notEmpty) begin
	 data = bscan_fifos[0].first;
	 bscan_fifos[0].deq;
      end
      else if (bscan_fifos[1].notEmpty) begin
	 data = bscan_fifos[1].first;
	 bscan_fifos[1].deq;
      end
      else if (bscan_fifos[2].notEmpty) begin
	 data = bscan_fifos[2].first;
	 bscan_fifos[2].deq;
      end
      else if (bscan_fifos[3].notEmpty) begin
	 data = bscan_fifos[3].first;
	 bscan_fifos[3].deq;
      end
      else begin
	 data = bscan_fifos[4].first;
	 bscan_fifos[4].deq;
      end
      traceBram.portA.request.put(BRAMRequest {write:True, responseOnWrite:False, address:addrReg, datain:data});
      addrReg <= addrReg + 1;
   endrule
   Reg#(Bit#(16)) seqCounter <- mkReg(0, clocked_by mainclock.c, reset_by mainclock.r);
   rule seqinc;
       seqCounter <= seqCounter + 1;
   endrule

   // AXI trace for JTAG
   let m = ps7.m_axi_gp[0].client;
   let s = top.ctrl;
   //mkConnection(m.req_ar, s.req_ar);
   rule connect_req_ar;
       let req <- m.req_ar.get();
       s.req_ar.put(req);
       bscan_fifos[0].enq(
	   {3'h1, interrupt_bit, req.id,
`ifdef AXI_READ_TIMING
                    seqCounter,
`else
                    req.len, req.cache, req.prot, req.size,
                    pack(req.burst == 2'b01), pack(req.lock == 0 && req.qos == 0),
`endif
                    req.address});
   endrule
   //mkConnection(s.resp_read, m.resp_read);
   rule connect_resp_read;
       let resp <- s.resp_read.get();
       m.resp_read.put(resp);
       bscan_fifos[1].enq(
           {3'h2, interrupt_bit, resp.id, resp.resp, resp.last, 13'b0, resp.data});
   endrule
   //mkConnection(m.req_aw, s.req_aw);
   rule connect_req_aw;
       let req <- m.req_aw.get();
       s.req_aw.put(req);
       bscan_fifos[2].enq(
           {3'h3, interrupt_bit, req.id, req.len, req.cache, req.prot, req.size,
                    pack(req.burst == 2'b01), pack(req.lock == 0 && req.qos == 0), req.address});
   endrule
   //mkConnection(m.resp_write, s.resp_write);
   rule connect_resp_write;
       let resp <- m.resp_write.get();
       s.resp_write.put(resp);
       bscan_fifos[3].enq(
           {3'h4, interrupt_bit, resp.id, resp.last, resp.byteEnable, 11'b0, resp.data});
   endrule
   //mkConnection(s.resp_b, m.resp_b);
   rule connect_resp_b;
       let resp <- s.resp_b.get();
       m.resp_b.put(resp);
       bscan_fifos[4].enq(
           {3'h5, interrupt_bit, resp.id, resp.resp, 46'b0});
   endrule
`endif

   mkConnection(top.m_axi, ps7.s_axi_hp[0].axi.server);
   rule send_int_rule;
       ps7.interrupt(interrupt_bit);
   endrule

   rule b2c_rule;
       mainclock.inputclock(ps7.fclkclk()[0]);
       mainclock.inputreset(ps7.fclkresetn()[0]);
   endrule

   interface zynq = ps7.pins;
   interface leds = top.leds;
   interface XADC xadc;
       method Bit#(4) gpio;
           return debugReg;
`ifdef BOZOIFDEF
           return {interrupt_bit,
                 pack((ps7.debug.arvalid == 1)
                   && (ps7.debug.araddr[18:16] == 3'd1)   // /dev/fpga1
                   && (ps7.debug.araddr[15:14] == 2'd2)   // indication
                   && (ps7.debug.araddr[13:8] == 6'd1)),  //     #1
                 ps7.debug.rvalid,
                 pack((ps7.debug.awvalid == 1)
                   && (ps7.debug.awaddr[18:16] == 3'd2)   // /dev/fpga2
                   && (ps7.debug.awaddr[15:14] == 2'd0)   // request
                   && (ps7.debug.awaddr[13:8] == 6'd1))}; //     #1
`endif
       endmethod
   endinterface
   interface pins = top.pins;
   interface unused_clock = mainclock.c;
   interface unused_reset = mainclock.r;
endmodule

module mkZynqTopClk1(ZynqTop#(Empty));
   let top <- mkZynqTopFromPortal(mkPortalTop);
   return top;
endmodule


MemSlave.bsv is no longer used

MemSlave.bsv is no longer used

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

////////////////////////////// Bsim /////////////////////////////////
`ifdef BsimHostTypeIF

import Vector            :: *;
import AxiMasterSlave    :: *;
import MemTypes          :: *;

`ifndef DataBusWidth
`define DataBusWidth 64
`endif

typedef `NumberOfMasters NumberOfMasters;
typedef `DataBusWidth DataBusWidth;

// this interface should allow for different master and slave bus paraters;
interface BsimHost#(numeric type clientAddrWidth, numeric type clientBusWidth, numeric type clientIdWidth,
		    numeric type serverAddrWidth, numeric type serverBusWidth, numeric type serverIdWidth,
		    numeric type nSlaves);
   interface MemMaster#(clientAddrWidth, clientBusWidth)  mem_client;
   interface Vector#(nSlaves,Axi3Slave#(serverAddrWidth,  serverBusWidth, serverIdWidth))  axi_servers;
   interface Clock doubleClock;
   interface Reset doubleReset;
endinterface

typedef BsimHost#(32,32,12,40,DataBusWidth,6,NumberOfMasters) HostType;
`endif

////////////////////////////// PciE /////////////////////////////////
`ifdef PcieHostTypeIF

import Vector            :: *;
import GetPut            :: *;
import ClientServer      :: *;
import PCIE               :: *;
import PCIEWRAPPER       :: *;
import PcieCsr           :: *;
import MemTypes          :: *;
import Bscan             :: *;
`ifndef BSIM
import PcieEndpointX7    :: *;
`endif

`ifndef DataBusWidth
`define DataBusWidth 64
`endif

typedef `DataBusWidth DataBusWidth;
typedef `NumberOfMasters NumberOfMasters;

interface PcieHost#(numeric type dsz, numeric type nSlaves);
   interface Vector#(16,ReadOnly_MSIX_Entry)     msixEntry;
   interface MemMaster#(32,32)                   master;
   interface Vector#(nSlaves,MemSlave#(40,dsz))  slave;
   interface Put#(Tuple2#(Bit#(64),Bit#(32)))    interruptRequest;
   interface Client#(TLPData#(16), TLPData#(16)) pci;
   interface BscanTop bscanif;
endinterface

interface PcieHostTop;
   interface Clock tepClock125;
   interface Reset tepReset125;
   interface PcieHost#(DataBusWidth, NumberOfMasters) tpciehost;
`ifndef BSIM
   interface Clock tsys_clk_200mhz;
   interface Clock tsys_clk_200mhz_buf;
   interface Clock tpci_clk_100mhz_buf;
   interface PcieEndpointX7#(PcieLanes) tep7;
`endif
   interface Clock doubleClock;
   interface Reset doubleReset;
endinterface

typedef PcieHostTop HostType;
`endif

////////////////////////////// Zynq /////////////////////////////////
`ifdef ZynqHostTypeIF
import PS7LIB::*;

typedef PS7 HostType;

export PS7LIB::*;
export HostType;
`endif

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

////////////////////////////// Bsim /////////////////////////////////
`ifdef BsimHostTypeIF

import Vector            :: *;
import AxiMasterSlave    :: *;
import MemTypes          :: *;

`ifndef DataBusWidth
`define DataBusWidth 64
`endif

typedef `NumberOfMasters NumberOfMasters;
typedef `DataBusWidth DataBusWidth;

// this interface should allow for different master and slave bus paraters;
interface BsimHost#(numeric type clientAddrWidth, numeric type clientBusWidth, numeric type clientIdWidth,
		    numeric type serverAddrWidth, numeric type serverBusWidth, numeric type serverIdWidth,
		    numeric type nSlaves);
   interface MemMaster#(clientAddrWidth, clientBusWidth)  mem_client;
   interface Vector#(nSlaves,Axi3Slave#(serverAddrWidth,  serverBusWidth, serverIdWidth))  axi_servers;
   interface Clock doubleClock;
   interface Reset doubleReset;
endinterface

typedef BsimHost#(32,32,12,40,DataBusWidth,6,NumberOfMasters) HostType;
`endif

////////////////////////////// PciE /////////////////////////////////
`ifdef PcieHostTypeIF

import Vector            :: *;
import GetPut            :: *;
import ClientServer      :: *;
import PCIE               :: *;
import PCIEWRAPPER       :: *;
import PcieCsr           :: *;
import MemSlave          :: *;
import MemTypes          :: *;
import Bscan             :: *;
`ifndef BSIM
import PcieEndpointX7    :: *;
`endif

`ifndef DataBusWidth
`define DataBusWidth 64
`endif

typedef `DataBusWidth DataBusWidth;
typedef `NumberOfMasters NumberOfMasters;

interface PcieHost#(numeric type dsz, numeric type nSlaves);
   interface Vector#(16,ReadOnly_MSIX_Entry)     msixEntry;
   interface MemMaster#(32,32)                   master;
   interface Vector#(nSlaves,MemSlave#(40,dsz))  slave;
   interface Put#(Tuple2#(Bit#(64),Bit#(32)))    interruptRequest;
   interface Client#(TLPData#(16), TLPData#(16)) pci;
   interface BscanTop bscanif;
endinterface

interface PcieHostTop;
   interface Clock tepClock125;
   interface Reset tepReset125;
   interface PcieHost#(DataBusWidth, NumberOfMasters) tpciehost;
`ifndef BSIM
   interface Clock tsys_clk_200mhz;
   interface Clock tsys_clk_200mhz_buf;
   interface Clock tpci_clk_100mhz_buf;
   interface PcieEndpointX7#(PcieLanes) tep7;
`endif
   interface Clock doubleClock;
   interface Reset doubleReset;
endinterface

typedef PcieHostTop HostType;
`endif

////////////////////////////// Zynq /////////////////////////////////
`ifdef ZynqHostTypeIF
import PS7LIB::*;

typedef PS7 HostType;

export PS7LIB::*;
export HostType;
`endif


trace system memory read responses that take too many cycles to complete

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

////////////////////////////// common /////////////////////////////////

`ifndef DataBusWidth
`define DataBusWidth 64
`endif

typedef `PhysAddrWidth PhysAddrWidth;
typedef `DataBusWidth DataBusWidth;
typedef `NumberOfMasters NumberOfMasters;

////////////////////////////// Bsim /////////////////////////////////
`ifdef BsimHostTypeIF

import Vector            :: *;
import AxiMasterSlave    :: *;
import MemTypes          :: *;

// this interface should allow for different master and slave bus paraters;
interface BsimHost#(numeric type clientAddrWidth, numeric type clientBusWidth, numeric type clientIdWidth,
		    numeric type serverAddrWidth, numeric type serverBusWidth, numeric type serverIdWidth,
		    numeric type nSlaves);
   interface PhysMemMaster#(clientAddrWidth, clientBusWidth)  mem_client;
   interface Vector#(nSlaves,PhysMemSlave#(serverAddrWidth,  serverBusWidth))  mem_servers;
   interface Clock derivedClock;
   interface Reset derivedReset;
endinterface

typedef BsimHost#(32,32,12,40,DataBusWidth,6,NumberOfMasters) HostType;
`endif

////////////////////////////// PciE /////////////////////////////////
`ifndef PcieHostIF
`ifdef PcieHostTypeIF
`define PcieHostIF
`endif
`endif

`ifdef PcieHostIF

import Vector            :: *;
import GetPut            :: *;
import ClientServer      :: *;
import BRAM              :: *;
import PCIE              :: *;
import Bscan             :: *;
import PcieCsr           :: *;
import PcieTracer        :: *;
import MemTypes          :: *;
`ifndef BSIM
`ifdef XILINX
import PcieEndpointX7    :: *;
import PCIEWRAPPER       :: *;
`elsif ALTERA
import PcieEndpointS5    :: *;
`endif
`endif
typedef 40 PciePhysAddrWidth;
interface PcieHost#(numeric type dsz, numeric type nSlaves);
   interface Vector#(16,ReadOnly_MSIX_Entry)     msixEntry;
   interface PhysMemMaster#(32,32)                   master;
   interface Vector#(nSlaves,PhysMemSlave#(PciePhysAddrWidth,dsz))  slave;
   interface Put#(Tuple2#(Bit#(64),Bit#(32)))    interruptRequest;
   interface Client#(TLPData#(16), TLPData#(16)) pci;
   interface Put#(TimestampedTlpData) trace;
`ifndef PCIE_NO_BSCAN
   interface BscanTop bscanif;
`else
   interface BRAMServer#(Bit#(TAdd#(TlpTraceAddrSize,1)), TimestampedTlpData) traceBramServer;
`endif
endinterface

interface PcieHostTop;
   interface Clock tepClock125;
   interface Reset tepReset125;
   interface PcieHost#(DataBusWidth, NumberOfMasters) tpciehost;
`ifdef XILINX
   interface Clock tsys_clk_200mhz;
   interface Clock tsys_clk_200mhz_buf;
   interface Clock tpci_clk_100mhz_buf;
   interface PcieEndpointX7#(PcieLanes) tep7;
`elsif ALTERA
//   interface Clock tsys_clk_200mhz;
//   interface Clock tsys_clk_200mhz_buf;
//   interface Clock tpci_clk_100mhz_buf;
   interface PcieEndpointS5#(PcieLanes) tep7;
`endif
   interface Clock portalClock;
   interface Reset portalReset;
   interface Clock derivedClock;
   interface Reset derivedReset;
endinterface
`endif

`ifdef PcieHostTypeIF
typedef PcieHostTop HostType;
`endif

////////////////////////////// Zynq /////////////////////////////////
`ifdef ZynqHostTypeIF
import PS7LIB::*;
import Bscan::*;

interface HostType;
    interface PS7 ps7;
    interface Clock portalClock;
    interface Reset portalReset;
    interface Clock derivedClock;
    interface Reset derivedReset;
    interface BscanTop bscan;
endinterface

//export PS7LIB::*;
//export BscanTop;
//export HostType;
//export DataBusWidth;
//export NumberOfMasters;
//export PhysAddrWidth;
`endif

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

////////////////////////////// common /////////////////////////////////

`ifndef DataBusWidth
`define DataBusWidth 64
`endif

typedef `PhysAddrWidth PhysAddrWidth;
typedef `DataBusWidth DataBusWidth;
typedef `NumberOfMasters NumberOfMasters;

////////////////////////////// Bsim /////////////////////////////////
`ifdef BsimHostTypeIF

import Vector            :: *;
import AxiMasterSlave    :: *;
import MemTypes          :: *;

// this interface should allow for different master and slave bus paraters;
interface BsimHost#(numeric type clientAddrWidth, numeric type clientBusWidth, numeric type clientIdWidth,
		    numeric type serverAddrWidth, numeric type serverBusWidth, numeric type serverIdWidth,
		    numeric type nSlaves);
   interface PhysMemMaster#(clientAddrWidth, clientBusWidth)  mem_client;
   interface Vector#(nSlaves,PhysMemSlave#(serverAddrWidth,  serverBusWidth))  mem_servers;
   interface Clock derivedClock;
   interface Reset derivedReset;
endinterface

typedef BsimHost#(32,32,12,40,DataBusWidth,6,NumberOfMasters) HostType;
`endif

////////////////////////////// PciE /////////////////////////////////
`ifndef PcieHostIF
`ifdef PcieHostTypeIF
`define PcieHostIF
`endif
`endif

`ifdef PcieHostIF

import Vector            :: *;
import GetPut            :: *;
import ClientServer      :: *;
import BRAM              :: *;
import PCIE              :: *;
import Bscan             :: *;
import PcieCsr           :: *;
import PcieTracer        :: *;
import MemTypes          :: *;
`ifndef BSIM
`ifdef XILINX
import PcieEndpointX7    :: *;
import PCIEWRAPPER       :: *;
`elsif ALTERA
import PcieEndpointS5    :: *;
`endif
`endif
typedef 40 PciePhysAddrWidth;
interface PcieHost#(numeric type dsz, numeric type nSlaves);
   interface Vector#(16,ReadOnly_MSIX_Entry)     msixEntry;
   interface PhysMemMaster#(32,32)                   master;
   interface Vector#(nSlaves,PhysMemSlave#(PciePhysAddrWidth,dsz))  slave;
   interface Put#(Tuple2#(Bit#(64),Bit#(32)))    interruptRequest;
   interface Client#(TLPData#(16), TLPData#(16)) pci;
`ifndef PCIE_NO_BSCAN
   interface BscanTop bscanif;
`else
   interface BRAMServer#(Bit#(TAdd#(TlpTraceAddrSize,1)), TimestampedTlpData) traceBramServer;
`endif
endinterface

interface PcieHostTop;
   interface Clock tepClock125;
   interface Reset tepReset125;
   interface PcieHost#(DataBusWidth, NumberOfMasters) tpciehost;
`ifdef XILINX
   interface Clock tsys_clk_200mhz;
   interface Clock tsys_clk_200mhz_buf;
   interface Clock tpci_clk_100mhz_buf;
   interface PcieEndpointX7#(PcieLanes) tep7;
`elsif ALTERA
//   interface Clock tsys_clk_200mhz;
//   interface Clock tsys_clk_200mhz_buf;
//   interface Clock tpci_clk_100mhz_buf;
   interface PcieEndpointS5#(PcieLanes) tep7;
`endif
   interface Clock portalClock;
   interface Reset portalReset;
   interface Clock derivedClock;
   interface Reset derivedReset;
endinterface
`endif

`ifdef PcieHostTypeIF
typedef PcieHostTop HostType;
`endif

////////////////////////////// Zynq /////////////////////////////////
`ifdef ZynqHostTypeIF
import PS7LIB::*;
import Bscan::*;

interface HostType;
    interface PS7 ps7;
    interface Clock portalClock;
    interface Reset portalReset;
    interface Clock derivedClock;
    interface Reset derivedReset;
    interface BscanTop bscan;
endinterface

//export PS7LIB::*;
//export BscanTop;
//export HostType;
//export DataBusWidth;
//export NumberOfMasters;
//export PhysAddrWidth;
`endif


define "last" field in MemMasterEngine

define "last" field in MemMasterEngine

Change-Id: If772ee476f15de4b3304131a9c83cb13314cacdb

// 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 FIFOF        :: *;
import Vector       :: *;
import GetPut       :: *;
import Connectable  :: *;
import MIMO         :: *;
import PCIE         :: *;
import DefaultValue :: *;
import ClientServer :: *;
import MemTypes     :: *;

//
// Top interface: PCIe transaction level packets (TLPs)
// Bottom interface: MemMaster that sends read/write requests to an MemSlave
// Also sources interrupt MSIX requests
interface MemMasterEngine;
    interface Client#(TLPData#(16), TLPData#(16)) tlp;
    interface MemMaster#(32,32) master;
endinterface

(* synthesize *)
module mkMemMasterEngine#(PciId my_id)(MemMasterEngine);
    Reg#(Bit#(7)) hitReg <- mkReg(0);
    FIFOF#(TLPMemoryIO3DWHeader) readHeaderFifo <- mkSizedFIFOF(8);
    FIFOF#(TLPMemoryIO3DWHeader) readDataFifo <- mkSizedFIFOF(8);
    FIFOF#(TLPMemoryIO3DWHeader) writeHeaderFifo <- mkSizedFIFOF(8);
    FIFOF#(TLPMemoryIO3DWHeader) writeDataFifo <- mkSizedFIFOF(8);
    FIFOF#(TLPData#(16)) tlpOutFifo <- mkSizedFIFOF(8);
    Reg#(TLPTag) tlpTag <- mkReg(0);

    MIMOConfiguration mimoCfg = defaultValue;
    MIMO#(1,4,16,Bit#(32)) completionMimo <- mkMIMO(mimoCfg);
   Reg#(TLPLength) readBurstCount <- mkReg(0);
   rule completionHeader if (readBurstCount == 0 && readDataFifo.notEmpty() && completionMimo.deqReadyN(1));
      let hdr = readDataFifo.first;
      TLPLength rbc = hdr.length;

      Vector#(4, Bit#(32)) dvec = completionMimo.first();
      completionMimo.deq(1);

      //$display("completionHeader length=%d rbc=%d addr=%x", hdr.length, rbc, hdr.addr);
      TLPCompletionHeader completion = defaultValue;
      completion.format = MEM_WRITE_3DW_DATA;
      completion.pkttype = COMPLETION;
      completion.relaxed = hdr.relaxed;
      completion.nosnoop = hdr.nosnoop;
      completion.length = hdr.length;
      completion.tclass = hdr.tclass;
      completion.cmplid = my_id;
      completion.tag = truncate(hdr.tag);
      completion.bytecount = 4;
      completion.reqid = hdr.reqid;
      completion.loweraddr = getLowerAddr(hdr.addr, hdr.firstbe);
      completion.data = byteSwap(dvec[0]);
      TLPData#(16) tlp = defaultValue;
      tlp.data = pack(completion);
      tlp.sof = True;
      tlp.eof = (rbc == 1) ? True : False;
      tlp.be = 16'hFFFF;
      tlp.hit = hitReg;
      tlpOutFifo.enq(tlp);

      rbc = rbc - 1;
      readBurstCount <= rbc;
      if (rbc == 0) begin
	 readDataFifo.deq;
      end
   endrule

    function Bit#(16) tlpBe(TLPLength len);
       if (len == 0)
	  return 0;
       else if (len == 1)
	  return 16'hf000;
       else if (len == 2)
	  return 16'hff00;
       else if (len == 3)
	  return 16'hfff0;
       else
	  return 16'hffff;
    endfunction

   rule continuation if (readBurstCount > 0);
      let rbc = readBurstCount;
      let sendit = False;
      TLPData#(16) tlp = defaultValue;
      Vector#(4, Bit#(32)) dvec = unpack(0);
      tlp.sof = False;
      //$display("continuation rbc=%d", rbc);
      if (rbc > 4) begin
	 if (completionMimo.deqReadyN(4)) begin
	    rbc = rbc - 4;
	    dvec = completionMimo.first();
	    completionMimo.deq(4);
	    tlp.be = tlpBe(4);
	    tlp.eof = False;
	    sendit = True;
	 end
      end
      else begin
	 UInt#(3) deqCount = truncate(unpack(rbc));
	 if (completionMimo.deqReadyN(deqCount)) begin
	    dvec = completionMimo.first();
	    completionMimo.deq(deqCount);
	    tlp.be = tlpBe(rbc);
	    //$display("tlp.data=%h tlp.be=%h", tlp.data, tlp.be);
	    tlp.eof = True;
	    rbc = 0;
	    sendit = True;
	 end
      end

      readBurstCount <= rbc;
      if (rbc == 0) begin
	 readDataFifo.deq();
      end
      if (sendit) begin
	 for (Integer i = 0; i < 4; i = i + 1)
	    tlp.data[(i+1)*32-1:i*32] = byteSwap(dvec[3-i]);
	 tlpOutFifo.enq(tlp);
      end
   endrule

    interface Client        tlp;
    interface Put response;
        method Action put(TLPData#(16) tlp);
	    //$display("MemMasterEngine.put tlp=%h", tlp);
	    TLPMemoryIO3DWHeader h = unpack(tlp.data);
	    hitReg <= tlp.hit;
	    TLPMemoryIO3DWHeader hdr_3dw = unpack(tlp.data);
	    if (hdr_3dw.format == MEM_READ_3DW_NO_DATA) begin
	       if (readHeaderFifo.notFull())
	          readHeaderFifo.enq(hdr_3dw);
	       else begin
		  // FIXME: should generate a response or host will lock up
	       end
	    end
	    else begin
	       if (writeHeaderFifo.notFull())
		  writeHeaderFifo.enq(hdr_3dw);
	    end
	endmethod
    endinterface
    interface Get request = toGet(tlpOutFifo);
    endinterface: tlp
    interface MemMaster master;
    interface MemWriteClient write_client;
        interface Get    writeReq;
	  method ActionValue#(MemRequest#(32)) get();
	     let hdr = writeHeaderFifo.first;
	     writeHeaderFifo.deq;
	     writeDataFifo.enq(hdr);
	     let axilen = hdr.length;
	     return MemRequest { addr: extend(writeHeaderFifo.first.addr) << 2, burstLen: truncate(axilen), tag: truncate(writeHeaderFifo.first.tag)};
	  endmethod
       endinterface
        interface Get writeData;
	  method ActionValue#(MemData#(32)) get();
	     let hdr <- toGet(writeDataFifo).get();
	     let data = byteSwap(hdr.data);
	     return MemData { data: data, tag: truncate(hdr.tag), last: True};
	  endmethod
       endinterface
        interface Put       writeDone;
	  method Action put(Bit#(ObjectTagSize) resp);
	  endmethod
       endinterface
     endinterface
    interface MemReadClient read_client;
        interface Get    readReq;
	  method ActionValue#(MemRequest#(32)) get();
	     let hdr = readHeaderFifo.first;
	     readHeaderFifo.deq;
	     //$display("req_ar hdr.length=%d hdr.addr=%h", hdr.length, hdr.addr);
	     readDataFifo.enq(hdr);
	     let axilen = hdr.length;
	     return MemRequest { addr: extend(readHeaderFifo.first.addr) << 2, burstLen: truncate(axilen), tag: truncate(readHeaderFifo.first.tag)};
	    endmethod
       endinterface
        interface Put readData;
	  method Action put(MemData#(32) resp) if (completionMimo.enqReadyN(1));
	     Vector#(1, Bit#(32)) vec = cons(resp.data, nil);
	     completionMimo.enq(1, vec);
	  endmethod
	endinterface
    endinterface
    endinterface: master
endmodule: mkMemMasterEngine

interface MemInterrupt;
    interface Client#(TLPData#(16), TLPData#(16)) tlp;
    interface Put#(Tuple2#(Bit#(64),Bit#(32))) interruptRequest;
endinterface

//(* synthesize *)
module mkMemInterrupt#(PciId my_id)(MemInterrupt);
    FIFOF#(Tuple2#(Bit#(64),Bit#(32))) interruptRequestFifo <- mkSizedFIFOF(16);
    Reg#(Maybe#(Bit#(32))) interruptSecondHalf <- mkReg(tagged Invalid);
    Reg#(TLPTag) tlpTag <- mkReg(0);
    FIFOF#(TLPData#(16)) tlpOutFifo <- mkSizedFIFOF(8);

    rule interruptTlpOut if (interruptRequestFifo.notEmpty &&& interruptSecondHalf matches tagged Invalid);
       TLPData#(16) tlp = defaultValue;
       tlp.sof = True;
       tlp.eof = False;
       tlp.hit = 7'h00;
       tlp.be = 16'hffff;

       let interruptRequested = True;
       let sendInterrupt = False;

       Bit#(64) interruptAddr = tpl_1(interruptRequestFifo.first);
       Bit#(32) interruptData = tpl_2(interruptRequestFifo.first);
       if (interruptAddr == '0) begin
	  // do not write to 0 -- it wedges the host
	  interruptRequested = False;
       end
       else if (interruptAddr[63:32] == '0) begin
          TLPMemoryIO3DWHeader hdr_3dw = defaultValue();
          hdr_3dw.format = MEM_WRITE_3DW_DATA;
	  //hdr_3dw.pkttype = MEM_READ_WRITE;
          hdr_3dw.tag = tlpTag;
          hdr_3dw.reqid = my_id;
          hdr_3dw.length = 1;
          hdr_3dw.firstbe = '1;
          hdr_3dw.lastbe = '0;
          hdr_3dw.addr = interruptAddr[31:2];
	  hdr_3dw.data = byteSwap(interruptData);
	  tlp.data = pack(hdr_3dw);
	  tlp.eof = True;
	  sendInterrupt = True;
	  interruptRequested = False;
       end
       else begin
	  TLPMemory4DWHeader hdr_4dw = defaultValue;
	  hdr_4dw.format = MEM_WRITE_4DW_DATA;
	  //hdr_4dw.pkttype = MEM_READ_WRITE;
	  hdr_4dw.tag = tlpTag;
	  hdr_4dw.reqid = my_id;
	  hdr_4dw.nosnoop = SNOOPING_REQD;
	  hdr_4dw.addr = interruptAddr[40-1:2];
	  hdr_4dw.length = 1;
	  hdr_4dw.firstbe = 4'hf;
	  hdr_4dw.lastbe = 0;
	  tlp.data = pack(hdr_4dw);

	  sendInterrupt = True;
	  interruptSecondHalf <= tagged Valid interruptData;
       end

       if (!interruptRequested)
	  interruptRequestFifo.deq();
       if (sendInterrupt)
	  tlpOutFifo.enq(tlp);
    endrule

    rule interruptTlpDataOut if (interruptSecondHalf matches tagged Valid .interruptData);
       TLPData#(16) tlp = defaultValue;
       tlp.sof = False;
       tlp.eof = True;
       tlp.hit = 7'h00;
       tlp.be = 16'hf000;
       tlp.data[7+8*15:8*12] = byteSwap(interruptData);
       tlpOutFifo.enq(tlp);
       interruptSecondHalf <= tagged Invalid;
       interruptRequestFifo.deq();
    endrule

    interface Client        tlp;
    interface Put response;
        method Action put(TLPData#(16) tlp);
	endmethod
    endinterface
    interface Get request = toGet(tlpOutFifo);
    endinterface: tlp
    interface Put interruptRequest;
       method Action put(Tuple2#(Bit#(64),Bit#(32)) intr);
          interruptRequestFifo.enq(intr);
       endmethod
    endinterface
endmodule: mkMemInterrupt

// 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 FIFOF        :: *;
import Vector       :: *;
import GetPut       :: *;
import Connectable  :: *;
import MIMO         :: *;
import PCIE         :: *;
import DefaultValue :: *;
import ClientServer :: *;
import MemTypes     :: *;

//
// Top interface: PCIe transaction level packets (TLPs)
// Bottom interface: MemMaster that sends read/write requests to an MemSlave
// Also sources interrupt MSIX requests
interface MemMasterEngine;
    interface Client#(TLPData#(16), TLPData#(16)) tlp;
    interface MemMaster#(32,32) master;
endinterface

(* synthesize *)
module mkMemMasterEngine#(PciId my_id)(MemMasterEngine);
    Reg#(Bit#(7)) hitReg <- mkReg(0);
    FIFOF#(TLPMemoryIO3DWHeader) readHeaderFifo <- mkSizedFIFOF(8);
    FIFOF#(TLPMemoryIO3DWHeader) readDataFifo <- mkSizedFIFOF(8);
    FIFOF#(TLPMemoryIO3DWHeader) writeHeaderFifo <- mkSizedFIFOF(8);
    FIFOF#(TLPMemoryIO3DWHeader) writeDataFifo <- mkSizedFIFOF(8);
    FIFOF#(TLPData#(16)) tlpOutFifo <- mkSizedFIFOF(8);
    Reg#(TLPTag) tlpTag <- mkReg(0);

    MIMOConfiguration mimoCfg = defaultValue;
    MIMO#(1,4,16,Bit#(32)) completionMimo <- mkMIMO(mimoCfg);
   Reg#(TLPLength) readBurstCount <- mkReg(0);
   rule completionHeader if (readBurstCount == 0 && readDataFifo.notEmpty() && completionMimo.deqReadyN(1));
      let hdr = readDataFifo.first;
      TLPLength rbc = hdr.length;

      Vector#(4, Bit#(32)) dvec = completionMimo.first();
      completionMimo.deq(1);

      //$display("completionHeader length=%d rbc=%d addr=%x", hdr.length, rbc, hdr.addr);
      TLPCompletionHeader completion = defaultValue;
      completion.format = MEM_WRITE_3DW_DATA;
      completion.pkttype = COMPLETION;
      completion.relaxed = hdr.relaxed;
      completion.nosnoop = hdr.nosnoop;
      completion.length = hdr.length;
      completion.tclass = hdr.tclass;
      completion.cmplid = my_id;
      completion.tag = truncate(hdr.tag);
      completion.bytecount = 4;
      completion.reqid = hdr.reqid;
      completion.loweraddr = getLowerAddr(hdr.addr, hdr.firstbe);
      completion.data = byteSwap(dvec[0]);
      TLPData#(16) tlp = defaultValue;
      tlp.data = pack(completion);
      tlp.sof = True;
      tlp.eof = (rbc == 1) ? True : False;
      tlp.be = 16'hFFFF;
      tlp.hit = hitReg;
      tlpOutFifo.enq(tlp);

      rbc = rbc - 1;
      readBurstCount <= rbc;
      if (rbc == 0) begin
	 readDataFifo.deq;
      end
   endrule

    function Bit#(16) tlpBe(TLPLength len);
       if (len == 0)
	  return 0;
       else if (len == 1)
	  return 16'hf000;
       else if (len == 2)
	  return 16'hff00;
       else if (len == 3)
	  return 16'hfff0;
       else
	  return 16'hffff;
    endfunction

   rule continuation if (readBurstCount > 0);
      let rbc = readBurstCount;
      let sendit = False;
      TLPData#(16) tlp = defaultValue;
      Vector#(4, Bit#(32)) dvec = unpack(0);
      tlp.sof = False;
      //$display("continuation rbc=%d", rbc);
      if (rbc > 4) begin
	 if (completionMimo.deqReadyN(4)) begin
	    rbc = rbc - 4;
	    dvec = completionMimo.first();
	    completionMimo.deq(4);
	    tlp.be = tlpBe(4);
	    tlp.eof = False;
	    sendit = True;
	 end
      end
      else begin
	 UInt#(3) deqCount = truncate(unpack(rbc));
	 if (completionMimo.deqReadyN(deqCount)) begin
	    dvec = completionMimo.first();
	    completionMimo.deq(deqCount);
	    tlp.be = tlpBe(rbc);
	    //$display("tlp.data=%h tlp.be=%h", tlp.data, tlp.be);
	    tlp.eof = True;
	    rbc = 0;
	    sendit = True;
	 end
      end

      readBurstCount <= rbc;
      if (rbc == 0) begin
	 readDataFifo.deq();
      end
      if (sendit) begin
	 for (Integer i = 0; i < 4; i = i + 1)
	    tlp.data[(i+1)*32-1:i*32] = byteSwap(dvec[3-i]);
	 tlpOutFifo.enq(tlp);
      end
   endrule

    interface Client        tlp;
    interface Put response;
        method Action put(TLPData#(16) tlp);
	    //$display("MemMasterEngine.put tlp=%h", tlp);
	    TLPMemoryIO3DWHeader h = unpack(tlp.data);
	    hitReg <= tlp.hit;
	    TLPMemoryIO3DWHeader hdr_3dw = unpack(tlp.data);
	    if (hdr_3dw.format == MEM_READ_3DW_NO_DATA) begin
	       if (readHeaderFifo.notFull())
	          readHeaderFifo.enq(hdr_3dw);
	       else begin
		  // FIXME: should generate a response or host will lock up
	       end
	    end
	    else begin
	       if (writeHeaderFifo.notFull())
		  writeHeaderFifo.enq(hdr_3dw);
	    end
	endmethod
    endinterface
    interface Get request = toGet(tlpOutFifo);
    endinterface: tlp
    interface MemMaster master;
    interface MemWriteClient write_client;
        interface Get    writeReq;
	  method ActionValue#(MemRequest#(32)) get();
	     let hdr = writeHeaderFifo.first;
	     writeHeaderFifo.deq;
	     writeDataFifo.enq(hdr);
	     let axilen = hdr.length;
	     return MemRequest { addr: extend(writeHeaderFifo.first.addr) << 2, burstLen: truncate(axilen), tag: truncate(writeHeaderFifo.first.tag)};
	  endmethod
       endinterface
        interface Get writeData;
	  method ActionValue#(MemData#(32)) get();
	     writeDataFifo.deq;
	     let data = writeDataFifo.first.data;
	     data = byteSwap(data);
	     return MemData { data: data, tag: truncate(writeDataFifo.first.tag)};
	  endmethod
       endinterface
        interface Put       writeDone;
	  method Action put(Bit#(ObjectTagSize) resp);
	  endmethod
       endinterface
     endinterface
    interface MemReadClient read_client;
        interface Get    readReq;
	  method ActionValue#(MemRequest#(32)) get();
	     let hdr = readHeaderFifo.first;
	     readHeaderFifo.deq;
	     //$display("req_ar hdr.length=%d hdr.addr=%h", hdr.length, hdr.addr);
	     readDataFifo.enq(hdr);
	     let axilen = hdr.length;
	     return MemRequest { addr: extend(readHeaderFifo.first.addr) << 2, burstLen: truncate(axilen), tag: truncate(readHeaderFifo.first.tag)};
	    endmethod
       endinterface
        interface Put readData;
	  method Action put(MemData#(32) resp) if (completionMimo.enqReadyN(1));
	     Vector#(1, Bit#(32)) vec = cons(resp.data, nil);
	     completionMimo.enq(1, vec);
	  endmethod
	endinterface
    endinterface
    endinterface: master
endmodule: mkMemMasterEngine

interface MemInterrupt;
    interface Client#(TLPData#(16), TLPData#(16)) tlp;
    interface Put#(Tuple2#(Bit#(64),Bit#(32))) interruptRequest;
endinterface

//(* synthesize *)
module mkMemInterrupt#(PciId my_id)(MemInterrupt);
    FIFOF#(Tuple2#(Bit#(64),Bit#(32))) interruptRequestFifo <- mkSizedFIFOF(16);
    Reg#(Maybe#(Bit#(32))) interruptSecondHalf <- mkReg(tagged Invalid);
    Reg#(TLPTag) tlpTag <- mkReg(0);
    FIFOF#(TLPData#(16)) tlpOutFifo <- mkSizedFIFOF(8);

    rule interruptTlpOut if (interruptRequestFifo.notEmpty &&& interruptSecondHalf matches tagged Invalid);
       TLPData#(16) tlp = defaultValue;
       tlp.sof = True;
       tlp.eof = False;
       tlp.hit = 7'h00;
       tlp.be = 16'hffff;

       let interruptRequested = True;
       let sendInterrupt = False;

       Bit#(64) interruptAddr = tpl_1(interruptRequestFifo.first);
       Bit#(32) interruptData = tpl_2(interruptRequestFifo.first);
       if (interruptAddr == '0) begin
	  // do not write to 0 -- it wedges the host
	  interruptRequested = False;
       end
       else if (interruptAddr[63:32] == '0) begin
          TLPMemoryIO3DWHeader hdr_3dw = defaultValue();
          hdr_3dw.format = MEM_WRITE_3DW_DATA;
	  //hdr_3dw.pkttype = MEM_READ_WRITE;
          hdr_3dw.tag = tlpTag;
          hdr_3dw.reqid = my_id;
          hdr_3dw.length = 1;
          hdr_3dw.firstbe = '1;
          hdr_3dw.lastbe = '0;
          hdr_3dw.addr = interruptAddr[31:2];
	  hdr_3dw.data = byteSwap(interruptData);
	  tlp.data = pack(hdr_3dw);
	  tlp.eof = True;
	  sendInterrupt = True;
	  interruptRequested = False;
       end
       else begin
	  TLPMemory4DWHeader hdr_4dw = defaultValue;
	  hdr_4dw.format = MEM_WRITE_4DW_DATA;
	  //hdr_4dw.pkttype = MEM_READ_WRITE;
	  hdr_4dw.tag = tlpTag;
	  hdr_4dw.reqid = my_id;
	  hdr_4dw.nosnoop = SNOOPING_REQD;
	  hdr_4dw.addr = interruptAddr[40-1:2];
	  hdr_4dw.length = 1;
	  hdr_4dw.firstbe = 4'hf;
	  hdr_4dw.lastbe = 0;
	  tlp.data = pack(hdr_4dw);

	  sendInterrupt = True;
	  interruptSecondHalf <= tagged Valid interruptData;
       end

       if (!interruptRequested)
	  interruptRequestFifo.deq();
       if (sendInterrupt)
	  tlpOutFifo.enq(tlp);
    endrule

    rule interruptTlpDataOut if (interruptSecondHalf matches tagged Valid .interruptData);
       TLPData#(16) tlp = defaultValue;
       tlp.sof = False;
       tlp.eof = True;
       tlp.hit = 7'h00;
       tlp.be = 16'hf000;
       tlp.data[7+8*15:8*12] = byteSwap(interruptData);
       tlpOutFifo.enq(tlp);
       interruptSecondHalf <= tagged Invalid;
       interruptRequestFifo.deq();
    endrule

    interface Client        tlp;
    interface Put response;
        method Action put(TLPData#(16) tlp);
	endmethod
    endinterface
    interface Get request = toGet(tlpOutFifo);
    endinterface: tlp
    interface Put interruptRequest;
       method Action put(Tuple2#(Bit#(64),Bit#(32)) intr);
          interruptRequestFifo.enq(intr);
       endmethod
    endinterface
endmodule: mkMemInterrupt


switch to simpleMMU

switch to simpleMMU

// 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 Clocks::*;
import Vector::*;
import BuildVector::*;
import GetPut::*;
import Connectable::*;
import ClientServer::*;
import ConnectalMemory::*;
import ConnectalBramFifo::*;
import FIFO::*;
import FIFOF::*;
import Gearbox::*;
import GearboxGetPut::*;
import MemTypes::*;
import Pipe::*;
import Ddr3Controller::*;
import GetPutWithClocks::*;
import AxiMasterSlave::*;
import Axi4MasterSlave::*;
import AxiDdr3Wrapper  ::*;
import AxiDma::*;
import AxiBits::*;
import ConnectalConfig::*;
import HostInterface::*;
import Probe::*;
import Ddr3Controller::*;
import SharedBuffMemServer::*;
import SharedBuffMMU::*;
import MemServerIndication::*;
import GetPutWithClocks::*;

interface Ddr3TestRequest;
   method Action startWriteDram(Bit#(32) sglId, Bit#(32) transferBytes);
   method Action startReadDram(Bit#(32) sglId, Bit#(32) transferBytes);
endinterface

interface Ddr3TestIndication;
   method Action writeDone(Bit#(32) v);
   method Action readDone(Bit#(32) v);
endinterface

interface Ddr3Test;
   interface Ddr3TestRequest request;
   interface Ddr3Pins ddr3;
endinterface

typedef TDiv#(Ddr3DataWidth,DataBusWidth) BusRatio;
typedef TDiv#(Ddr3DataWidth,8) Ddr3DataBytes;

module mkDdr3Test#(HostInterface host, Ddr3TestIndication indication, MemServerIndication memind, MMUIndication mmuInd)(Ddr3Test);

   let clock <- exposeCurrentClock();
   let reset <- exposeCurrentReset();

   Reg#(Bit#(Ddr3AddrWidth)) transferLen <- mkReg(256);

   Clock clk200 = host.tsys_clk_200mhz_buf;

   let ddr3Controller <- mkDdr3(clk200);

   FIFO#(MemRequest) writeReqFifo <- mkFIFO();
   FIFO#(MemData#(Ddr3DataWidth)) writeDataFifo <- mkFIFO();
   FIFO#(Bit#(MemTagSize)) writeDoneFifo <- mkFIFO();
   MemWriteClient#(Ddr3DataWidth) writeClient = (interface MemWriteClient;
      interface Get writeReq = toGet(writeReqFifo);
      interface Get writeData = toGet(writeDataFifo);
      interface Put writeDone = toPut(writeDoneFifo);
      endinterface);

   FIFO#(MemRequest) readReqFifo <- mkFIFO();
   FIFO#(MemData#(Ddr3DataWidth)) readDataFifo <- mkFIFO();
   MemReadClient#(Ddr3DataWidth) readClient = (interface MemReadClient;
      interface Get readReq = toGet(readReqFifo);
      interface Put readData = toPut(readDataFifo);
      endinterface);

   MMU#(Ddr3AddrWidth) mmu <- mkSimpleMMU(0, False, mmuInd);
   MemServer#(Ddr3AddrWidth, Ddr3DataWidth, 1) dma <- mkMemServer(vec(readClient), vec(writeClient), vec(mmu), memind);
   Vector#(1, PhysMemSlave#(Ddr3AddrWidth, Ddr3DataWidth)) memSlaves <- replicateM(mkPhysMemSlave(ddr3Controller.axiBits, clocked_by ddr3Controller.uiClock, reset_by ddr3Controller.uiReset));
   for (Integer i=0; i<1; i=i+1) begin
      mkConnectionWithClocks(dma.masters[i], memSlaves[i], clock, reset, ddr3Controller.uiClock, ddr3Controller.uiReset);
   end

   Gearbox#(1,BusRatio,Bit#(DataBusWidth)) dramWriteGearbox <- mk1toNGearbox(clock, reset, clock, reset);
   FIFOF#(Vector#(BusRatio,Bit#(DataBusWidth))) dramWriteFifo <- mkDualClockBramFIFOF(clock, reset, ddr3Controller.uiClock, ddr3Controller.uiReset);

//   rule rl_wdata;
//      let mds <- toGet(dramWriteGearbox).get();
//      dramWriteFifo.enq(mds);
//   endrule
//   rule rl_writeDataFifo;
//      let mds <- toGet(dramWriteFifo).get();
//      // ddr3?
//   endrule

   Gearbox#(BusRatio,1,Bit#(DataBusWidth)) dramReadGearbox <- mkNto1Gearbox(ddr3Controller.uiClock, ddr3Controller.uiReset, ddr3Controller.uiClock, ddr3Controller.uiReset);
   FIFOF#(Bit#(DataBusWidth)) dramReadFifo <- mkDualClockBramFIFOF(ddr3Controller.uiClock, ddr3Controller.uiReset, clock, reset);

//   rule rl_rdata_gb;
//      Bit#(DataBusWidth) rdata <- toGet(dramReadGearbox).get();
//      dramReadFifo.enq(rdata);
//   endrule
//   rule rl_rdata_slack;
//      let rdata <- toGet(dramReadFifo).get();
//      // to readClient?
//   endrule

   interface Ddr3TestRequest request;
      method Action startWriteDram(Bit#(32) sglId, Bit#(32) transferBytes);
        transferLen <= truncate(transferBytes);
      endmethod
      method Action startReadDram(Bit#(32) sglId, Bit#(32) transferBytes);
        transferLen <= truncate(transferBytes);
      endmethod
   endinterface
   interface AxiDdr3 ddr3 = ddr3Controller.ddr3;
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 Clocks::*;
import Vector::*;
import BuildVector::*;
import GetPut::*;
import Connectable::*;
import ClientServer::*;
import ConnectalMemory::*;
import ConnectalBramFifo::*;
import FIFO::*;
import FIFOF::*;
import Gearbox::*;
import GearboxGetPut::*;
import MemTypes::*;
import Pipe::*;
import Ddr3Controller::*;
import GetPutWithClocks::*;
import AxiMasterSlave::*;
import Axi4MasterSlave::*;
import AxiDdr3Wrapper  ::*;
import AxiDma::*;
import AxiBits::*;
import ConnectalConfig::*;
import HostInterface::*;
import Probe::*;
import Ddr3Controller::*;
import SharedBuffMemServer::*;
import MemMgmt::*;
import MemServerIndication::*;
import GetPutWithClocks::*;

interface Ddr3TestRequest;
   method Action startWriteDram(Bit#(32) sglId, Bit#(32) transferBytes);
   method Action startReadDram(Bit#(32) sglId, Bit#(32) transferBytes);
endinterface

interface Ddr3TestIndication;
   method Action writeDone(Bit#(32) v);
   method Action readDone(Bit#(32) v);
endinterface

interface Ddr3Test;
   interface Ddr3TestRequest request;
   interface Ddr3Pins ddr3;
endinterface

typedef TDiv#(Ddr3DataWidth,DataBusWidth) BusRatio;
typedef TDiv#(Ddr3DataWidth,8) Ddr3DataBytes;

module mkDdr3Test#(HostInterface host, Ddr3TestIndication indication, MemServerIndication memind)(Ddr3Test);

   let clock <- exposeCurrentClock();
   let reset <- exposeCurrentReset();

   Reg#(Bit#(Ddr3AddrWidth)) transferLen <- mkReg(256);

   Clock clk200 = host.tsys_clk_200mhz_buf;

   let ddr3Controller <- mkDdr3(clk200);

   FIFO#(MemRequest) writeReqFifo <- mkFIFO();
   FIFO#(MemData#(Ddr3DataWidth)) writeDataFifo <- mkFIFO();
   FIFO#(Bit#(MemTagSize)) writeDoneFifo <- mkFIFO();
   MemWriteClient#(Ddr3DataWidth) writeClient = (interface MemWriteClient;
      interface Get writeReq = toGet(writeReqFifo);
      interface Get writeData = toGet(writeDataFifo);
      interface Put writeDone = toPut(writeDoneFifo);
      endinterface);

   FIFO#(MemRequest) readReqFifo <- mkFIFO();
   FIFO#(MemData#(Ddr3DataWidth)) readDataFifo <- mkFIFO();
   MemReadClient#(Ddr3DataWidth) readClient = (interface MemReadClient;
      interface Get readReq = toGet(readReqFifo);
      interface Put readData = toPut(readDataFifo);
      endinterface);

   MemMgmt#(Ddr3AddrWidth, 1, 1) alloc <- mkMemMgmt();
   MemServer#(Ddr3AddrWidth, Ddr3DataWidth, 1) dma <- mkMemServer(vec(readClient), vec(writeClient), vec(alloc.mmu), memind);
   Vector#(1, PhysMemSlave#(Ddr3AddrWidth, Ddr3DataWidth)) memSlaves <- replicateM(mkPhysMemSlave(ddr3Controller.axiBits, clocked_by ddr3Controller.uiClock, reset_by ddr3Controller.uiReset));
   for (Integer i=0; i<1; i=i+1) begin
      mkConnectionWithClocks(dma.masters[i], memSlaves[i], clock, reset, ddr3Controller.uiClock, ddr3Controller.uiReset);
   end

   Gearbox#(1,BusRatio,Bit#(DataBusWidth)) dramWriteGearbox <- mk1toNGearbox(clock, reset, clock, reset);
   FIFOF#(Vector#(BusRatio,Bit#(DataBusWidth))) dramWriteFifo <- mkDualClockBramFIFOF(clock, reset, ddr3Controller.uiClock, ddr3Controller.uiReset);

//   rule rl_wdata;
//      let mds <- toGet(dramWriteGearbox).get();
//      dramWriteFifo.enq(mds);
//   endrule
//   rule rl_writeDataFifo;
//      let mds <- toGet(dramWriteFifo).get();
//      // ddr3?
//   endrule

   Gearbox#(BusRatio,1,Bit#(DataBusWidth)) dramReadGearbox <- mkNto1Gearbox(ddr3Controller.uiClock, ddr3Controller.uiReset, ddr3Controller.uiClock, ddr3Controller.uiReset);
   FIFOF#(Bit#(DataBusWidth)) dramReadFifo <- mkDualClockBramFIFOF(ddr3Controller.uiClock, ddr3Controller.uiReset, clock, reset);

//   rule rl_rdata_gb;
//      Bit#(DataBusWidth) rdata <- toGet(dramReadGearbox).get();
//      dramReadFifo.enq(rdata);
//   endrule
//   rule rl_rdata_slack;
//      let rdata <- toGet(dramReadFifo).get();
//      // to readClient?
//   endrule

   interface Ddr3TestRequest request;
      method Action startWriteDram(Bit#(32) sglId, Bit#(32) transferBytes);
        transferLen <= truncate(transferBytes);
      endmethod
      method Action startReadDram(Bit#(32) sglId, Bit#(32) transferBytes);
        transferLen <= truncate(transferBytes);
      endmethod
   endinterface
   interface AxiDdr3 ddr3 = ddr3Controller.ddr3;
endmodule


enable multiple outstanding reqs

enable multiple outstanding reqs

// 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 Vector::*;
import BuildVector::*;
import FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import ClientServer::*;
import GetPut::*;
import HostInterface::*;
import MemTypes::*;
import MemwriteEngine::*;
import Pipe::*;
import AddressGenerator::*;

typedef TDiv#(DataBusWidth,32) WordsPerBeat;

interface MemwriteRequest;
   method Action startWrite(Bit#(32) pointer, Bit#(32) numWords, Bit#(32) numReqs, Bit#(32) burstLen);
endinterface

interface MemwriteIndication;
   method Action writeDone(Bit#(32) v);
   method Action writeProgress(Bit#(32) v);
endinterface

interface Memwrite;
   interface MemwriteRequest request;
   interface Vector#(1, MemWriteClient#(DataBusWidth)) dmaClients;
endinterface

module  mkMemwrite#(MemwriteIndication indication) (Memwrite);
   Reg#(SGLId)   pointer <- mkReg(0);
   Reg#(Bit#(32))        numReqs <- mkReg(0);
   Reg#(Bit#(32))        numDone <- mkReg(0);
   Reg#(Bit#(MemOffsetSize)) reqOffset <- mkReg(0);
   Reg#(Bit#(3))                   tag <- mkReg(0);
   Reg#(Bit#(32))             numWords <- mkReg(0);
   Reg#(Bit#(BurstLenSize)) burstLenBytes <- mkReg(0);
   Reg#(Bit#(32))              srcGens <- mkReg(0);

   AddressGenerator#(32, DataBusWidth) addrGenerator <- mkAddressGenerator();
   FIFO#(MemRequest) reqFifo <- mkSizedFIFO(4);
   FIFO#(PhysMemRequest#(32)) preqFifo <- mkSizedFIFO(4);
   FIFO#(MemData#(DataBusWidth))   dataFifo <- mkSizedBRAMFIFO(1024);
   FIFO#(Bit#(MemTagSize)) doneFifo <- mkSizedFIFO(4);

   let verboseProgress = False;

   rule start if (numReqs != 0);
      reqFifo.enq(MemRequest { sglId: pointer, offset: reqOffset, burstLen: burstLenBytes, tag: extend(tag) });
      preqFifo.enq(PhysMemRequest { addr: 0, burstLen: burstLenBytes, tag: extend(tag) });
      numReqs <= numReqs - 1;
      reqOffset <= reqOffset + extend(burstLenBytes);
      tag <= tag + 1;
      //$display("start numReqs", numReqs);
   endrule

   rule preq;
      let preq <- toGet(preqFifo).get();
      addrGenerator.request.put(preq);
   endrule

   rule finish;
      let donetag <- toGet(doneFifo).get();
      //$display("finished num todo=%d", numDone);
      if (numDone == 1) begin
         indication.writeDone(0);
      end
      numDone <= numDone - 1;
      if (verboseProgress)
	 indication.writeProgress(extend(donetag));
   endrule

   rule src if (numWords != 0);
      let b <- addrGenerator.addrBeat.get();

      function Bit#(32) plusi(Integer i); return srcGens + fromInteger(i); endfunction
      Vector#(WordsPerBeat, Bit#(32)) v = genWith(plusi);
      dataFifo.enq(MemData { data: pack(v), tag: b.tag, last: b.last});
      srcGens <= srcGens+fromInteger(valueOf(WordsPerBeat));
      numWords <= numWords - fromInteger(valueOf(WordsPerBeat));
   endrule

   MemWriteClient#(DataBusWidth) dmaClient = (interface MemWriteClient;
      interface Get writeReq = toGet(reqFifo);
      interface Get writeData = toGet(dataFifo);
      interface Put writeDone = toPut(doneFifo);
   endinterface );

   interface MemwriteRequest request;
       method Action startWrite(Bit#(32) wp, Bit#(32) nw, Bit#(32) nreq, Bit#(32) bl);
	  $dumpvars();
          $display("startWrite pointer=%d numWords=%d (%d) numReqs=%d burstLen=%d", pointer, nw, nreq*bl, nreq, bl);
          pointer <= wp;
          numWords  <= nw;
          burstLenBytes <= truncate(bl);
	  numReqs <= nreq;
	  numDone <= nreq;

	  reqOffset <= 0;
	  srcGens <= 0;
       endmethod
   endinterface
   interface dmaClients = vec(dmaClient);

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 Vector::*;
import BuildVector::*;
import FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import ClientServer::*;
import GetPut::*;
import HostInterface::*;
import MemTypes::*;
import MemwriteEngine::*;
import Pipe::*;
import AddressGenerator::*;

typedef TDiv#(DataBusWidth,32) WordsPerBeat;

interface MemwriteRequest;
   method Action startWrite(Bit#(32) pointer, Bit#(32) numWords, Bit#(32) numReqs, Bit#(32) burstLen);
endinterface

interface MemwriteIndication;
   method Action writeDone(Bit#(32) v);
   method Action writeProgress(Bit#(32) v);
endinterface

interface Memwrite;
   interface MemwriteRequest request;
   interface Vector#(1, MemWriteClient#(DataBusWidth)) dmaClients;
endinterface

module  mkMemwrite#(MemwriteIndication indication) (Memwrite);
   Reg#(SGLId)   pointer <- mkReg(0);
   Reg#(Bit#(32))        numReqs <- mkReg(0);
   Reg#(Bit#(32))        numDone <- mkReg(0);
   Reg#(Bit#(MemOffsetSize)) reqOffset <- mkReg(0);
   Reg#(Bit#(3))                   tag <- mkReg(0);
   Reg#(Bit#(32))             numWords <- mkReg(0);
   Reg#(Bit#(BurstLenSize)) burstLenBytes <- mkReg(0);
   Reg#(Bit#(32))              srcGens <- mkReg(0);

   AddressGenerator#(32, DataBusWidth) addrGenerator <- mkAddressGenerator();
   FIFO#(MemRequest) reqFifo <- mkFIFO();
   FIFO#(PhysMemRequest#(32)) preqFifo <- mkFIFO();
   FIFO#(MemData#(DataBusWidth))   dataFifo <- mkSizedBRAMFIFO(1024);
   FIFO#(Bit#(MemTagSize)) doneFifo <- mkFIFO();

   let verboseProgress = False;

   rule start if (numReqs != 0);
      reqFifo.enq(MemRequest { sglId: pointer, offset: reqOffset, burstLen: burstLenBytes, tag: extend(tag) });
      preqFifo.enq(PhysMemRequest { addr: 0, burstLen: burstLenBytes, tag: extend(tag) });
      numReqs <= numReqs - 1;
      reqOffset <= reqOffset + extend(burstLenBytes);
      tag <= tag + 1;
      //$display("start numReqs", numReqs);
   endrule

   rule preq;
      let preq <- toGet(preqFifo).get();
      addrGenerator.request.put(preq);
   endrule

   rule finish;
      let donetag <- toGet(doneFifo).get();
      //$display("finished num todo=%d", numDone);
      if (numDone == 1) begin
         indication.writeDone(0);
      end
      numDone <= numDone - 1;
      if (verboseProgress)
	 indication.writeProgress(extend(donetag));
   endrule

   rule src if (numWords != 0);
      let b <- addrGenerator.addrBeat.get();

      function Bit#(32) plusi(Integer i); return srcGens + fromInteger(i); endfunction
      Vector#(WordsPerBeat, Bit#(32)) v = genWith(plusi);
      dataFifo.enq(MemData { data: pack(v), tag: b.tag, last: b.last});
      srcGens <= srcGens+fromInteger(valueOf(WordsPerBeat));
      numWords <= numWords - fromInteger(valueOf(WordsPerBeat));
   endrule

   MemWriteClient#(DataBusWidth) dmaClient = (interface MemWriteClient;
      interface Get writeReq = toGet(reqFifo);
      interface Get writeData = toGet(dataFifo);
      interface Put writeDone = toPut(doneFifo);
   endinterface );

   interface MemwriteRequest request;
       method Action startWrite(Bit#(32) wp, Bit#(32) nw, Bit#(32) nreq, Bit#(32) bl);
	  $dumpvars();
          $display("startWrite pointer=%d numWords=%d (%d) numReqs=%d burstLen=%d", pointer, nw, nreq*bl, nreq, bl);
          pointer <= wp;
          numWords  <= nw;
          burstLenBytes <= truncate(bl);
	  numReqs <= nreq;
	  numDone <= nreq;

	  reqOffset <= 0;
	  srcGens <= 0;
       endmethod
   endinterface
   interface dmaClients = vec(dmaClient);

endmodule


Reduced number of adders in brAddrCalc

Reduced number of adders in brAddrCalc

import RVTypes::*;

(* noinline *)
function Addr execControl(BrFunc brFunc, Data rVal1, Data rVal2, Maybe#(Data) imm, Addr pc);
    // XXX: This should only be used with a valid imm
    Bool taken = aluBr(brFunc, rVal1, rVal2);
    Addr targetPc = brAddrCalc(brFunc, pc, rVal1, fromMaybe(?, imm));
    return taken ? targetPc : (pc + 4);
endfunction

(* noinline *)
function Bool aluBr(BrFunc brFunc, Data a, Data b);
    Bool brTaken = (case(brFunc)
            Eq:         (a == b);
            Neq:        (a != b);
            Lt:         signedLT(a, b);
            Ltu:        (a < b);
            Ge:         signedGE(a, b);
            Geu:        (a >= b);
            Jal:        True;
            Jalr:       True;
            default:    True;
        endcase);
    return brTaken;
endfunction

(* noinline *)
function Addr brAddrCalc(BrFunc brFunc, Addr pc, Data val, Data imm);
    Data in1 = (brFunc == Jalr) ? val : pc;
    Data addOut = in1 + imm;
    // if JALR, zero LSB
    Data targetAddr = (brFunc == Jalr) ? (addOut & (~1)) : addOut;
    return targetAddr;

    // XXX: Old implementation
    // Addr targetAddr = (case (brFunc)
    //         Jal:        (pc + imm);
    //         Jalr:       {(val + imm)[valueOf(AddrSz)-1:1], 1'b0};
    //         default:    (pc + imm);
    //     endcase);
    // return targetAddr;
endfunction

import RVTypes::*;

(* noinline *)
function Addr execControl(BrFunc brFunc, Data rVal1, Data rVal2, Maybe#(Data) imm, Addr pc);
    // XXX: This should only be used with a valid imm
    Bool taken = aluBr(brFunc, rVal1, rVal2);
    Addr targetPc = brAddrCalc(brFunc, pc, rVal1, fromMaybe(?, imm));
    return taken ? targetPc : (pc + 4);
endfunction

(* noinline *)
function Bool aluBr(BrFunc brFunc, Data a, Data b);
    Bool brTaken = (case(brFunc)
            Eq:         (a == b);
            Neq:        (a != b);
            Lt:         signedLT(a, b);
            Ltu:        (a < b);
            Ge:         signedGE(a, b);
            Geu:        (a >= b);
            Jal:        True;
            Jalr:       True;
            default:    True;
        endcase);
    return brTaken;
endfunction

(* noinline *)
function Addr brAddrCalc(BrFunc brFunc, Addr pc, Data val, Data imm);
    Addr targetAddr = (case (brFunc)
            Jal:        (pc + imm);
            Jalr:       {(val + imm)[valueOf(AddrSz)-1:1], 1'b0};
            default:    (pc + imm);
        endcase);
    return targetAddr;
endfunction


remove MCSAlgorithm, update to SWAlgorithm

// 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 FIFO::*;
import FIFOF::*;
import SpecialFIFOs::*;
import GetPut::*;
import StmtFSM::*;
//import Vector::*;
import BRAM::*;
//import Gearbox::*;
import Connectable::*;

//import AxiMasterSlave::*;
import Dma::*;
import DmaUtils::*;
import Dma2BRAM::*;

// algorithm
import GotohB::*;
import GotohC::*;

interface SmithwatermanRequest;
   method Action setupA(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
   method Action setupB(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
   method Action start(Bit#(32) alg);
endinterface

interface SmithwatermanIndication;
   method Action searchResult(Bit#(32) v);
   method Action setupAComplete();
   method Action setupBComplete();
endinterface

typedef Bit#(64) DWord;
typedef Bit#(32) Word;

typedef 16384 MaxStringLen;
typedef 16384 MaxFetchLen;
typedef TLog#(MaxStringLen) StringIdxWidth;
typedef Bit#(StringIdxWidth) StringIdx;
typedef TLog#(MaxFetchLen) LIdxWidth;
typedef Bit#(LIdxWidth) LIdx;

module mkSmithwatermanRequest#(SmithwatermanIndication indication,
			ObjectReadServer#(busWidth)   setupA_read_server,
			ObjectReadServer#(busWidth)   setupB_read_server)(SmithwatermanRequest)

   provisos(Add#(a__, 8, busWidth),
	    Div#(busWidth,8,nc),
	    Mul#(nc,8,busWidth),
	    Add#(1, b__, nc),
	    Add#(c__, 32, busWidth),
	    Add#(1, d__, TDiv#(busWidth, 32)),
	    Mul#(TDiv#(busWidth, 32), 32, busWidth),
            Mul#(TDiv#(busWidth, 16), 16, busWidth),
            Add#(1, e__, TDiv#(busWidth, 16)),
            Add#(1, f__, TMul#(2, TDiv#(busWidth, 16))),
            Add#(TDiv#(busWidth, 16), g__, TMul#(2, TDiv#(busWidth, 16))));

  Reg#(Bit#(14)) aLenReg <- mkReg(0);
  Reg#(Bit#(14)) bLenReg <- mkReg(0);
  Reg#(Bit#(14)) rLenReg <- mkReg(0);
   BRAM2Port#(StringIdx, Bit#(8)) strA  <- mkBRAM2Server(defaultValue);
   BRAM2Port#(StringIdx, Bit#(8)) strB <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) cc <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) dd <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) rr <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) ss <- mkBRAM2Server(defaultValue);

   BRAMReadClient#(StringIdxWidth,busWidth) n2a <- mkBRAMReadClient(strA.portB);
   mkConnection(n2a.dmaClient, setupA_read_server);
   BRAMReadClient#(StringIdxWidth,busWidth) n2b <- mkBRAMReadClient(strB.portB);
   mkConnection(n2b.dmaClient, setupB_read_server);

   Reg#(Bool) gotohCRunning <- mkReg(False);

   GotohAlgorithm cgotohB1 <- mkGotohB(strA.portA, strB.portA, matL0.portA, 1);
   GotohAlgorithm cgotohB0 <- mkGotohB(strA.portA, strB.portA, matL1.portA, 0);
   SWAlgorithm gotohC <- mkGotohC(strA.portA, strB.portA, cgotohB0, cgotohB1, cc.portB, dd.portB, rr.portB, ss.portB);
   // create BRAM Write client for matL

   rule finish_setupA;
      $display("finish setupA");
      let x <- n2a.finish;
      indication.setupAComplete();
   endrule

   rule finish_setupB;
      $display("finish setupB");
      let x <- n2b.finish;
      indication.setupBComplete();
   endrule

   rule gotohC_completion (gotohCRunning && gotohC.fsm.done);
      gotohCRunning <= False;
      indication.searchResult(pack(zeroExtend(gotohC.result())));
      endrule

   method Action setupA(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
      aLenReg <= truncate(strLen);
      $display("setupA %h %h %d", strPointer, strOffset, strLen);
      n2a.start(strPointer, 0, pack(truncate(strOffset)), pack(truncate(strOffset + strLen-1)));
      gotohC.setupA(truncate(strOffset), pack(truncate(strLen)));
   endmethod

   method Action setupB(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
      bLenReg <= truncate(strLen);
      $display("setupB %h %h %d", strPointer, strOffset, strLen);
      n2b.start(strPointer, 0, pack(truncate(strOffset)), pack(truncate(strOffset + strLen-1)));
      gotohC.setupB(truncate(strOffset), pack(truncate(strLen)));
   endmethod

   method Action start(Bit#(32) alg);
      $display ("start %d", alg);
      case (alg)
	 3: begin
	       gotohC.fsm.start();
	       gotohCRunning <= True;
	    end
      endcase
   endmethod

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 FIFO::*;
import FIFOF::*;
import SpecialFIFOs::*;
import GetPut::*;
import StmtFSM::*;
//import Vector::*;
import BRAM::*;
//import Gearbox::*;
import Connectable::*;

//import AxiMasterSlave::*;
import Dma::*;
import DmaUtils::*;
import Dma2BRAM::*;

// algorithm
import GotohB::*;
import GotohC::*;

interface SmithwatermanRequest;
   method Action setupA(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
   method Action setupB(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
   method Action start(Bit#(32) alg);
endinterface

interface SmithwatermanIndication;
   method Action searchResult(Bit#(32) v);
   method Action setupAComplete();
   method Action setupBComplete();
endinterface

typedef Bit#(64) DWord;
typedef Bit#(32) Word;

typedef 16384 MaxStringLen;
typedef 16384 MaxFetchLen;
typedef TLog#(MaxStringLen) StringIdxWidth;
typedef Bit#(StringIdxWidth) StringIdx;
typedef TLog#(MaxFetchLen) LIdxWidth;
typedef Bit#(LIdxWidth) LIdx;

module mkSmithwatermanRequest#(SmithwatermanIndication indication,
			ObjectReadServer#(busWidth)   setupA_read_server,
			ObjectReadServer#(busWidth)   setupB_read_server)(SmithwatermanRequest)

   provisos(Add#(a__, 8, busWidth),
	    Div#(busWidth,8,nc),
	    Mul#(nc,8,busWidth),
	    Add#(1, b__, nc),
	    Add#(c__, 32, busWidth),
	    Add#(1, d__, TDiv#(busWidth, 32)),
	    Mul#(TDiv#(busWidth, 32), 32, busWidth),
            Mul#(TDiv#(busWidth, 16), 16, busWidth),
            Add#(1, e__, TDiv#(busWidth, 16)),
            Add#(1, f__, TMul#(2, TDiv#(busWidth, 16))),
            Add#(TDiv#(busWidth, 16), g__, TMul#(2, TDiv#(busWidth, 16))));

  Reg#(Bit#(14)) aLenReg <- mkReg(0);
  Reg#(Bit#(14)) bLenReg <- mkReg(0);
  Reg#(Bit#(14)) rLenReg <- mkReg(0);
   BRAM2Port#(StringIdx, Bit#(8)) strA  <- mkBRAM2Server(defaultValue);
   BRAM2Port#(StringIdx, Bit#(8)) strB <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) cc <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) dd <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) rr <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) ss <- mkBRAM2Server(defaultValue);

   BRAMReadClient#(StringIdxWidth,busWidth) n2a <- mkBRAMReadClient(strA.portB);
   mkConnection(n2a.dmaClient, setupA_read_server);
   BRAMReadClient#(StringIdxWidth,busWidth) n2b <- mkBRAMReadClient(strB.portB);
   mkConnection(n2b.dmaClient, setupB_read_server);

   Reg#(Bool) gotohCRunning <- mkReg(False);

   MCSAlgorithm cgotohB1 <- mkGotohB(strA.portA, strB.portA, matL0.portA, 1);
   MCSAlgorithm cgotohB0 <- mkGotohB(strA.portA, strB.portA, matL1.portA, 0);
   MCSAlgorithm gotohC <- mkGotohC(strA.portA, strB.portA, cgotohB0, cgotohB1, cc.portB, dd.portB, rr.portB, ss.portB);
   // create BRAM Write client for matL

   rule finish_setupA;
      $display("finish setupA");
      let x <- n2a.finish;
      indication.setupAComplete();
   endrule

   rule finish_setupB;
      $display("finish setupB");
      let x <- n2b.finish;
      indication.setupBComplete();
   endrule

   rule gotohC_completion (gotohCRunning && gotohC.fsm.done);
      gotohCRunning <= False;
      indication.searchResult(pack(zeroExtend(gotohC.result())));
      endrule

   method Action setupA(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
      aLenReg <= truncate(strLen);
      $display("setupA %h %h %d", strPointer, strOffset, strLen);
      n2a.start(strPointer, 0, pack(truncate(strOffset)), pack(truncate(strOffset + strLen-1)));
      gotohC.setupA(truncate(strOffset), pack(truncate(strLen)));
   endmethod

   method Action setupB(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
      bLenReg <= truncate(strLen);
      $display("setupB %h %h %d", strPointer, strOffset, strLen);
      n2b.start(strPointer, 0, pack(truncate(strOffset)), pack(truncate(strOffset + strLen-1)));
      gotohC.setupB(truncate(strOffset), pack(truncate(strLen)));
   endmethod

   method Action start(Bit#(32) alg);
      $display ("start %d", alg);
      case (alg)
	 3: begin
	       gotohC.fsm.start();
	       gotohCRunning <= True;
	    end
      endcase
   endmethod

endmodule