sonicuser.bsv is not working

sonicuser.bsv is not working

// Copyright (c) 2013 Nokia, 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 Vector::*;
import Pipe::*;
import GetPut::*;

typedef struct {
   Bit#(8) port_no;
   Bit#(64) data;
} BufData deriving (Bits, Eq);

interface DtpIfc;
   interface PipeIn#(Bit#(128)) timestamp; // streaming time counter from NetTop.
   interface Vector#(4, PipeOut#(Bit#(53))) fromHost;
   interface Vector#(4, PipeIn#(Bit#(53)))  toHost;
endinterface

interface SonicUserRequest;
   method Action read_timestamp_req(Bit#(8) cmd);
   method Action write_delay(Bit#(64) host_cnt);
   method Action log_write(Bit#(8) port_no, Bit#(64) local_cnt);
   method Action log_read_req(Bit#(8) port_no);
endinterface

interface SonicUserIndication;
   method Action read_timestamp_resp(Bit#(64) val);
   method Action log_read_resp(Bit#(8) port_no, Bit#(64) local_cnt, Bit#(64) global_cnt);
endinterface

interface SonicUser;
   interface SonicUserRequest request;
   interface DtpIfc           dtp;
endinterface

module mkSonicUser#(SonicUserIndication indication)(SonicUser);
   let verbose = False;
   Reg#(Bit#(64))  cycle_count <- mkReg(0);
   Reg#(Bit#(64))  last_count  <- mkReg(0);

   FIFOF#(Bit#(128)) rxFifo    <- mkFIFOF();
   Reg#(Bit#(128)) timestamp_reg <- mkReg(0);

   Vector#(4, FIFOF#(Bit#(53))) fromHostFifo <- replicateM(mkSizedFIFOF(4));
   Vector#(4, FIFOF#(Bit#(53))) toHostFifo <- replicateM(mkSizedFIFOF(4));
   FIFOF#(BufData) toHostBuffered <- mkSizedFIFOF(16);

   Reg#(Bit#(8))  lwrite_port <- mkReg(0);
   Reg#(Bit#(53)) lwrite_timestamp <- mkReg(0);
   FIFOF#(void)    lwrite_cf <- mkSizedFIFOF(8);

   Reg#(Bit#(8))  lread_port <- mkReg(0);
   FIFOF#(void)   lread_cf <- mkSizedFIFOF(8);

   rule count;
      cycle_count <= cycle_count + 1;
   endrule

   rule snapshot_dtp_timestamp;
      let v <- toGet(rxFifo).get;
      timestamp_reg <= v;
   endrule

   rule log_from_host;
      let v <- toGet(lwrite_cf).get;
      fromHostFifo[lwrite_port].enq(lwrite_timestamp);
   endrule

   Reg#(Bit#(TLog#(4))) arb <- mkReg(0);
   rule arbit;
      arb <= arb + 1;
   endrule
   for (Integer i=0; i<4; i=i+1) begin
      rule save_to_host_data (arb == fromInteger(i));
         let port_no = fromInteger(i);
         if (toHostFifo[port_no].notEmpty) begin
            toHostBuffered.enq(BufData{port_no:port_no, data:zeroExtend(toHostFifo[port_no].first)});
            toHostFifo[port_no].deq;
         end
      endrule
   end

   rule log_to_host;
      let v <- toGet(lread_cf).get;
      //let v <- toGet(toHostBuffered).get;
      //indication.log_read_resp(v.port_no, truncate(timestamp_reg), v.data);
   endrule

   interface dtp = (interface DtpIfc;
      interface timestamp = toPipeIn(rxFifo);
      interface toHost = map(toPipeIn, toHostFifo);
      interface fromHost = map(toPipeOut, fromHostFifo);
   endinterface);

   interface SonicUserRequest request;
   method Action read_timestamp_req(Bit#(8) cmd);
      indication.read_timestamp_resp(truncate(timestamp_reg));
   endmethod
   method Action write_delay(Bit#(64) host_cnt);
      Bit#(64) delay = (host_cnt - cycle_count) >> 1;
   endmethod
   method Action log_write(Bit#(8) port_no, Bit#(64) host_timestamp);
      // Check valid port No.
      if (port_no < 4) begin
         lwrite_port <= port_no;
         lwrite_timestamp <= truncate(host_timestamp);
         lwrite_cf.enq(?);
      end
   endmethod
   method Action log_read_req(Bit#(8) port_no);
      if (port_no < 4) begin
         lread_port <= port_no;
         lread_cf.enq(?);
      end
   endmethod
   endinterface
endmodule

// Copyright (c) 2013 Nokia, 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 Vector::*;
import Pipe::*;
import GetPut::*;

typedef struct {
   Bit#(8) port_no;
   Bit#(64) local_cnt;
   Bit#(64) global_cnt;
   } S3 deriving (Bits, Eq);

interface DtpIfc;
   interface PipeIn#(Bit#(128)) timestamp; // streaming time counter from NetTop.
   interface Vector#(4, PipeOut#(Bit#(53))) fromHost;
   interface Vector#(4, PipeIn#(Bit#(53)))  toHost;
endinterface

interface SonicUserRequest;
   method Action read_timestamp_req(Bit#(8) cmd);
   method Action write_delay(Bit#(64) host_cnt);
   method Action log_write(Bit#(8) port_no, Bit#(64) local_cnt);
   method Action log_read_req(Bit#(8) port_no);
endinterface

interface SonicUserIndication;
   method Action read_timestamp_resp(Bit#(64) val);
   method Action log_read_resp(Bit#(8) port_no, Bit#(64) local_cnt, Bit#(64) global_cnt);
endinterface

interface SonicUser;
   interface SonicUserRequest request;
   interface DtpIfc           dtp;
endinterface

module mkSonicUser#(SonicUserIndication indication)(SonicUser);
   let verbose = False;
   Reg#(Bit#(64))  cycle_count <- mkReg(0);
   Reg#(Bit#(64))  last_count  <- mkReg(0);

   FIFOF#(Bit#(128)) rxFifo    <- mkFIFOF();
   Reg#(Bit#(128)) timestamp_reg <- mkReg(0);

   Vector#(4, FIFOF#(Bit#(53))) fromHostFifo <- replicateM(mkSizedFIFOF(32));
   Vector#(4, FIFOF#(Bit#(53))) toHostFifo <- replicateM(mkSizedFIFOF(32));
   Vector#(4, Reg#(Bit#(128)))  toHostReg <- replicateM(mkReg(0));

   rule count;
      cycle_count <= cycle_count + 1;
   endrule

   rule receive_dtp_timestamp;
      let v <- toGet(rxFifo).get;
      timestamp_reg <= v;
   endrule

   interface dtp = (interface DtpIfc;
      interface timestamp = toPipeIn(rxFifo);
      interface toHost = map(toPipeIn, toHostFifo);
      interface fromHost = map(toPipeOut, fromHostFifo);
   endinterface);

   interface SonicUserRequest request;
   method Action read_timestamp_req(Bit#(8) cmd);
      indication.read_timestamp_resp(truncate(timestamp_reg));
   endmethod
   method Action write_delay(Bit#(64) host_cnt);
      Bit#(64) delay = (host_cnt - cycle_count) >> 1;
   endmethod
   method Action log_write(Bit#(8) port_no, Bit#(64) host_timestamp);
      case (port_no)
         0: fromHostFifo[0].enq(truncate(host_timestamp));
         1: fromHostFifo[1].enq(truncate(host_timestamp));
         2: fromHostFifo[2].enq(truncate(host_timestamp));
         3: fromHostFifo[3].enq(truncate(host_timestamp));
      endcase
   endmethod
   method Action log_read_req(Bit#(8) port_no);
      Int#(64) invalid_data=-1;
      Int#(8)  invalid_port=-1;
      let v = 0;
      if (port_no < 4) begin
         v <- toGet(toHostFifo[port_no]).get;
      end
      case (port_no)
         0: indication.log_read_resp(0, truncate(timestamp_reg), zeroExtend(v));
         1: indication.log_read_resp(1, truncate(timestamp_reg), zeroExtend(v));
         2: indication.log_read_resp(2, truncate(timestamp_reg), zeroExtend(v));
         3: indication.log_read_resp(3, truncate(timestamp_reg), zeroExtend(v));
         default: indication.log_read_resp(pack(signExtend(invalid_port)), pack(signExtend(invalid_data)), pack(signExtend(invalid_data)));
      endcase
   endmethod
   endinterface
endmodule


fixed de5 pins name

fixed de5 pins name

import Clocks::*;
import Vector::*;

import ConnectalClocks::*;
import LedController::*;
import PushButtonController::*;

import AlteraExtra::*;
import ALTERA_SI570_WRAPPER::*;

(* always_ready, always_enabled *)
interface DE5Pins;
`ifndef SIMULATION
   method Action osc_50(Bit#(1) b3d, Bit#(1) b4a, Bit#(1) b4d, Bit#(1) b7a, Bit#(1) b7d, Bit#(1) b8a, Bit#(1) b8d);
   method Action sfp(Bit#(1) refclk);
   method Vector#(4, Bit#(1)) serial_tx_data;
   method Action serial_rx(Vector#(4, Bit#(1)) data);
   method Bit#(4) led;
   method Bit#(4) led_bracket;
   method Action buttons(Vector#(4, Bit#(1)) v);
   interface Si570wrapI2c i2c;
   interface De5SfpCtrl#(4) sfpctrl;
   interface Clock deleteme_unused_clock;
   interface Clock deleteme_unused_clock2;
   interface Clock deleteme_unused_clock3;
   interface Reset deleteme_unused_reset;
`endif
endinterface

interface De5Clocks;
   interface Si570wrapI2c i2c;
   interface Clock clock_50;
   interface Reset reset_50_n;
   interface Clock clock_156_25;
   interface Reset reset_156_25_n;
   interface Clock clock_644_53;
endinterface

module mkDe5Clocks#(Bit#(1) clk_50, Bit#(1) clk_644)(De5Clocks);
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   B2C1 iclock_50 <- mkB2C1();
   B2C1 iclock_644 <- mkB2C1();

   //Reset reset_50 <- mkResetInverter(reset_n, clocked_by clk_50_b4a_buf.outclk);
   Reset rst_50_n <- mkAsyncReset(2, defaultReset, iclock_50.c);
   Reset reset_644 <- mkResetInverter(defaultReset, clocked_by iclock_644.c);
   //Reset reset_644_53_n <- mkAsyncReset(2, reset_n, sfp_refclk);

   // ===================================
   // PLL:
   // Input:   SFP REFCLK from SI570
   // Output:  156.25MHz
   // Reset: Active High, must invert default Reset
   PLL156 pll156 <- mkPLL156(iclock_644.c, reset_644, clocked_by iclock_644.c, reset_by reset_644);
   Clock clk_156_25 = pll156.outclk_0;
   Reset rst_156   <- mkResetInverter(defaultReset, clocked_by clk_156_25);
   Reset rst_156_n <- mkAsyncReset(2, defaultReset, clk_156_25, clocked_by clk_156_25);

   // ===================================
   // PLL: SI570 configurable clock
   // Input:
   // Output:
   // Reset: Active Low, use default Reset
   Si570Wrap si570 <- mkSi570Wrap(iclock_50.c, rst_50_n, clocked_by iclock_50.c, reset_by rst_50_n);

   rule si570_connections;
      let ifreq_mode = 3'b110;  //644.53125 MHZ
      si570.ifreq.mode(ifreq_mode);
      si570.istart.go(1'b0);
   endrule

   rule input_clock_50;
      iclock_50.inputclock(clk_50);
   endrule

   rule input_clock_644;
      iclock_644.inputclock(clk_644);
   endrule

   interface i2c = si570.i2c;
   interface clock_50 = iclock_50.c;
   interface reset_50_n = rst_50_n;
   interface clock_156_25 = clk_156_25;
   interface reset_156_25_n = rst_156_n;
   interface clock_644_53 = iclock_644.c;
endmodule

interface De5Leds;
   method Bit#(4) led_out;
endinterface

module mkDe5Leds#(Clock clk0, Clock clk1, Clock clk2, Clock clk3)(De5Leds);
   Clock defaultClock <- exposeCurrentClock;
   Reset defaultReset <- exposeCurrentReset;

   Reset reset0 <- mkSyncReset(2, defaultReset, clk0);
   Reset reset1 <- mkSyncReset(2, defaultReset, clk1);
   Reset reset2 <- mkSyncReset(2, defaultReset, clk2);
   Reset reset3 <- mkSyncReset(2, defaultReset, clk3);

   LedController led0 <- mkLedController(False, clocked_by clk0, reset_by reset0);
   LedController led1 <- mkLedController(False, clocked_by clk1, reset_by reset1);
   LedController led2 <- mkLedController(False, clocked_by clk2, reset_by reset2);
   LedController led3 <- mkLedController(False, clocked_by clk3, reset_by reset3);

   rule led0_run;
      led0.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   rule led1_run;
      led1.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   rule led2_run;
      led2.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   rule led3_run;
      led3.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   method led_out = {led0.ifc.out,
                     led1.ifc.out,
                     led2.ifc.out,
                     led3.ifc.out
                     };
endmodule

interface De5SfpCtrl#(numeric type nPorts);
   method Action los ((* port="" *) Vector#(nPorts, Bit#(1)) v);
   method Action mod0_presnt_n ((* port="" *) Vector#(nPorts, Bit#(1)) v);
   method Action txfault ((* port="" *) Vector#(nPorts, Bit#(1)) v);
// SCL/SDA not implemented
(* prefix="", result="ratesel0" *)   method Vector#(nPorts, Bit#(1)) ratesel0;
(* prefix="", result="ratesel1" *)   method Vector#(nPorts, Bit#(1)) ratesel1;
(* prefix="", result="txdisable" *)   method Vector#(nPorts, Bit#(1)) txdisable;
endinterface

module mkDe5SfpCtrl(De5SfpCtrl#(nPorts));
   Vector#(nPorts, Wire#(Bit#(1))) los_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) mod0_presnt_n_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) txfault_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) ratesel0_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) ratesel1_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) txdisable_wire <- replicateM(mkDWire(0));

   for (Integer i=0; i<valueOf(nPorts); i=i+1) begin
      rule set_output;
         ratesel0_wire[i] <= 1'b1;
         ratesel1_wire[i] <= 1'b1;
         txdisable_wire[i] <= 1'b0;
      endrule
   end

   method los = writeVReg(los_wire);
   method mod0_presnt_n = writeVReg(mod0_presnt_n_wire);
   method txfault = writeVReg(txfault_wire);
   method ratesel0 = readVReg(ratesel0_wire);
   method ratesel1 = readVReg(ratesel1_wire);
   method txdisable = readVReg(txdisable_wire);
endmodule

interface De5Buttons#(numeric type nButtons);
   method Action pins((* port="" *) Vector#(nButtons, Bit#(1)) v);
(* prefix="", result="pressed" *)   method Vector#(nButtons, Bool) pressed;
endinterface

module mkDe5Buttons(De5Buttons#(nButtons));
   Clock defaultClock <- exposeCurrentClock;
   Reset defaultReset <- exposeCurrentReset;
   Vector#(nButtons, Wire#(Bit#(1))) button_in <- replicateM(mkDWire(0));
   Vector#(nButtons, Wire#(Bool)) button_pressed <- replicateM(mkDWire(False));

   Vector#(4, PushButtonController) buttons <- replicateM(mkPushButtonController(defaultClock));
   for (Integer i=0; i<valueOf(nButtons); i=i+1) begin
      rule setPushButtonInput;
         buttons[i].ifc.button(button_in[i]);
      endrule

      rule setPushButtonParam;
         buttons[i].setRepeatParams(10, 10);
      endrule

      rule setPushButtonOutput;
         button_pressed[i] <= buttons[i].pressed;
      endrule
   end

   method pins = writeVReg(button_in);
   method pressed = readVReg(button_pressed);
endmodule

import Clocks::*;
import Vector::*;

import ConnectalClocks::*;
import LedController::*;
import PushButtonController::*;

import AlteraExtra::*;
import ALTERA_SI570_WRAPPER::*;

(* always_ready, always_enabled *)
interface DE5Pins;
`ifndef SIMULATION
   method Action osc_50(Bit#(1) b3d, Bit#(1) b4a, Bit#(1) b4d, Bit#(1) b7a, Bit#(1) b7d, Bit#(1) b8a, Bit#(1) b8d);
   method Action sfp(Bit#(1) refclk);
   method Vector#(4, Bit#(1)) serial_tx_data;
   method Action serial_rx(Vector#(4, Bit#(1)) data);
   method Bit#(4) led;
   method Bit#(4) led_bracket;
   method Action buttons(Vector#(4, Bit#(1)) v);
   interface Si570wrapI2c i2c;
   interface De5SfpCtrl#(4) sfpctrl;
   interface Clock deleteme_unused_clock;
   interface Clock deleteme_unused_clock2;
   interface Clock deleteme_unused_clock3;
   interface Reset deleteme_unused_reset;
`endif
endinterface

interface De5Clocks;
   interface Si570wrapI2c i2c;
   interface Clock clock_50;
   interface Reset reset_50_n;
   interface Clock clock_156_25;
   interface Reset reset_156_25_n;
   interface Clock clock_644_53;
endinterface

module mkDe5Clocks#(Bit#(1) clk_50, Bit#(1) clk_644)(De5Clocks);
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   B2C1 iclock_50 <- mkB2C1();
   B2C1 iclock_644 <- mkB2C1();

   //Reset reset_50 <- mkResetInverter(reset_n, clocked_by clk_50_b4a_buf.outclk);
   Reset rst_50_n <- mkAsyncReset(2, defaultReset, iclock_50.c);
   Reset reset_644 <- mkResetInverter(defaultReset, clocked_by iclock_644.c);
   //Reset reset_644_53_n <- mkAsyncReset(2, reset_n, sfp_refclk);

   // ===================================
   // PLL:
   // Input:   SFP REFCLK from SI570
   // Output:  156.25MHz
   // Reset: Active High, must invert default Reset
   PLL156 pll156 <- mkPLL156(iclock_644.c, reset_644, clocked_by iclock_644.c, reset_by reset_644);
   Clock clk_156_25 = pll156.outclk_0;
   Reset rst_156   <- mkResetInverter(defaultReset, clocked_by clk_156_25);
   Reset rst_156_n <- mkAsyncReset(2, defaultReset, clk_156_25, clocked_by clk_156_25);

   // ===================================
   // PLL: SI570 configurable clock
   // Input:
   // Output:
   // Reset: Active Low, use default Reset
   Si570Wrap si570 <- mkSi570Wrap(iclock_50.c, rst_50_n, clocked_by iclock_50.c, reset_by rst_50_n);

   rule si570_connections;
      let ifreq_mode = 3'b110;  //644.53125 MHZ
      si570.ifreq.mode(ifreq_mode);
      si570.istart.go(1'b0);
   endrule

   rule input_clock_50;
      iclock_50.inputclock(clk_50);
   endrule

   rule input_clock_644;
      iclock_644.inputclock(clk_644);
   endrule

   interface i2c = si570.i2c;
   interface clock_50 = iclock_50.c;
   interface reset_50_n = rst_50_n;
   interface clock_156_25 = clk_156_25;
   interface reset_156_25_n = rst_156_n;
   interface clock_644_53 = iclock_644.c;
endmodule

interface De5Leds;
   method Bit#(4) led_out;
endinterface

module mkDe5Leds#(Clock clk0, Clock clk1, Clock clk2, Clock clk3)(De5Leds);
   Clock defaultClock <- exposeCurrentClock;
   Reset defaultReset <- exposeCurrentReset;

   Reset reset0 <- mkSyncReset(2, defaultReset, clk0);
   Reset reset1 <- mkSyncReset(2, defaultReset, clk1);
   Reset reset2 <- mkSyncReset(2, defaultReset, clk2);
   Reset reset3 <- mkSyncReset(2, defaultReset, clk3);

   LedController led0 <- mkLedController(False, clocked_by clk0, reset_by reset0);
   LedController led1 <- mkLedController(False, clocked_by clk1, reset_by reset1);
   LedController led2 <- mkLedController(False, clocked_by clk2, reset_by reset2);
   LedController led3 <- mkLedController(False, clocked_by clk3, reset_by reset3);

   rule led0_run;
      led0.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   rule led1_run;
      led1.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   rule led2_run;
      led2.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   rule led3_run;
      led3.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   method led_out = {led0.ifc.out,
                     led1.ifc.out,
                     led2.ifc.out,
                     led3.ifc.out
                     };
endmodule

interface De5SfpCtrl#(numeric type nPorts);
   method Action los ((* port="los" *) Vector#(nPorts, Bit#(1)) v);
   method Action mod0_presnt_n ((* port="mod0_presnt_n" *) Vector#(nPorts, Bit#(1)) v);
   method Action txfault ((* port="txfault" *) Vector#(nPorts, Bit#(1)) v);
// SCL/SDA not implemented
(* prefix="", result="ratesel0" *)   method Vector#(nPorts, Bit#(1)) ratesel0;
(* prefix="", result="ratesel1" *)   method Vector#(nPorts, Bit#(1)) ratesel1;
(* prefix="", result="txdisable" *)   method Vector#(nPorts, Bit#(1)) txdisable;
endinterface

module mkDe5SfpCtrl(De5SfpCtrl#(nPorts));
   Vector#(nPorts, Wire#(Bit#(1))) los_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) mod0_presnt_n_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) txfault_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) ratesel0_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) ratesel1_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) txdisable_wire <- replicateM(mkDWire(0));

   for (Integer i=0; i<valueOf(nPorts); i=i+1) begin
      rule set_output;
         ratesel0_wire[i] <= 1'b1;
         ratesel1_wire[i] <= 1'b1;
         txdisable_wire[i] <= 1'b0;
      endrule
   end

   method los = writeVReg(los_wire);
   method mod0_presnt_n = writeVReg(mod0_presnt_n_wire);
   method txfault = writeVReg(txfault_wire);
   method ratesel0 = readVReg(ratesel0_wire);
   method ratesel1 = readVReg(ratesel1_wire);
   method txdisable = readVReg(txdisable_wire);
endmodule

interface De5Buttons#(numeric type nButtons);
   method Action pins((* port="pins" *) Vector#(nButtons, Bit#(1)) v);
(* prefix="", result="pressed" *)   method Vector#(nButtons, Bool) pressed;
endinterface

module mkDe5Buttons(De5Buttons#(nButtons));
   Clock defaultClock <- exposeCurrentClock;
   Reset defaultReset <- exposeCurrentReset;
   Vector#(nButtons, Wire#(Bit#(1))) button_in <- replicateM(mkDWire(0));
   Vector#(nButtons, Wire#(Bool)) button_pressed <- replicateM(mkDWire(False));

   Vector#(4, PushButtonController) buttons <- replicateM(mkPushButtonController(defaultClock));
   for (Integer i=0; i<valueOf(nButtons); i=i+1) begin
      rule setPushButtonInput;
         buttons[i].ifc.button(button_in[i]);
      endrule

      rule setPushButtonParam;
         buttons[i].setRepeatParams(10, 10);
      endrule

      rule setPushButtonOutput;
         button_pressed[i] <= buttons[i].pressed;
      endrule
   end

   method pins = writeVReg(button_in);
   method pressed = readVReg(button_pressed);
endmodule


remove warnings

remove warnings

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

/*
 * Implementation of:
 *    MP algorithm on pages 7-11 from "Pattern Matching Algorithms" by
 *       Alberto Apostolico, Zvi Galil, 1997
 */

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

import AxiMasterSlave::*;
import MemTypes::*;
import Dma2BRAM::*;

interface MPEngine#(numeric type busWidth);
   method Action setup(Bit#(32) needlePointer, Bit#(32) mpNextPointer, Bit#(32) needle_len);
   method Action search(Bit#(32) haystackPointer, Bit#(32) haystack_len, Bit#(32) haystack_base);
   interface ObjectReadClient#(busWidth) needle_read_client;
   interface ObjectReadClient#(busWidth) mp_next_read_client;
   interface ObjectReadClient#(busWidth) haystack_read_client;
endinterface

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

typedef 1024 MaxNeedleLen;
typedef TLog#(MaxNeedleLen) NeedleIdxWidth;
typedef Bit#(NeedleIdxWidth) NeedleIdx;

typedef enum {Idle, Ready, Run} Stage deriving (Eq, Bits);

module mkMPEngine#(FIFOF#(void) compf,
		   FIFOF#(void) conff,
		   FIFOF#(Int#(32)) locf )(MPEngine#(busWidth))

   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));

   Clock clk <- exposeCurrentClock;
   Reset rst <- exposeCurrentReset;
   BRAM2Port#(NeedleIdx, Char) needle  <- mkBRAM2Server(defaultValue);
   BRAM2Port#(NeedleIdx, Bit#(32)) mpNext <- mkBRAM2Server(defaultValue);
   Gearbox#(nc,1,Char) haystack <- mkNto1Gearbox(clk,rst,clk,rst);

   Reg#(Stage)    stage <- mkReg(Idle);
   Reg#(Bit#(32)) needleLenReg <- mkReg(0);
   Reg#(Bit#(32)) haystackLenReg <- mkReg(0);
   Reg#(Bit#(32)) haystackBase <- mkReg(0);
   Reg#(Bit#(32)) jReg <- mkReg(0); // offset in haystack
   Reg#(Bit#(32)) iReg <- mkReg(0); // offset in needle
   Reg#(Bit#(2))  epochReg <- mkReg(0);
   Reg#(Bit#(6))  dmaTag <- mkReg(0);
   Reg#(Bit#(32)) haystackOff <- mkReg(0);
   Reg#(ObjectPointer) haystackPointer <- mkReg(0);

   BRAMReadClient#(NeedleIdxWidth,busWidth) n2b <- mkBRAMReadClient(needle.portB);
   BRAMReadClient#(NeedleIdxWidth,busWidth) mp2b <- mkBRAMReadClient(mpNext.portB);
   MemReader#(busWidth) hreader <- mkMemReader;

   FIFOF#(Tuple2#(Bit#(2),Bit#(32))) efifo <- mkSizedFIFOF(2);

   rule finish_setup;
      $display("mkMPEngine::finish_setup");
      let x <- n2b.finish;
      let y <- mp2b.finish;
      stage <= Ready;
      conff.enq(?);
   endrule

   rule haystackReq (stage == Run && haystackOff < extend(haystackLenReg));
      //$display("haystackReq %x", haystackOff);
      hreader.readServer.readReq.put(ObjectRequest {pointer: haystackPointer, offset: extend(haystackBase+haystackOff), burstLen: fromInteger(valueOf(nc)), tag: dmaTag});
      haystackOff <= haystackOff + fromInteger(valueOf(nc));
   endrule

   rule haystackResp;
      //$display("haystackResp");
      let rv <- hreader.readServer.readData.get;
      Vector#(nc,Char) pv = unpack(rv.data);
      if(rv.tag == dmaTag)
	 haystack.enq(pv);
   endrule

   rule haystackDrain(stage != Run);
      //$display("haystackDrain");
      haystack.deq;
   endrule

   rule bramDrain(stage != Run);
      //$display("mpNextDrain");
      let x <- mpNext.portA.response.get;
      let y <- needle.portA.response.get;
      efifo.deq;
   endrule

   rule matchNeedleReq(stage == Run);
      //$display(" matchNeedleReq %d %d", epochReg, iReg);
      needle.portA.request.put(BRAMRequest{write:False, address: truncate(iReg-1), datain:?, responseOnWrite:?});
      mpNext.portA.request.put(BRAMRequest{write:False, address: truncate(iReg), datain:?, responseOnWrite:?});
      efifo.enq(tuple2(epochReg,iReg));
      iReg <= iReg+1;
   endrule

   rule matchNeedleResp(stage == Run);
      let nv <- needle.portA.response.get;
      let mp <- mpNext.portA.response.get;
      let epoch = tpl_1(efifo.first);
      efifo.deq;
      //$display("matchNeedleResp %d %d", epochReg, epoch);
      if (epoch == epochReg) begin
	 let n = haystackLenReg;
	 let m = needleLenReg;
	 let hv = haystack.first;
	 let i = tpl_2(efifo.first);
	 let j = jReg;
	 //$display("feck %d %d %d %d %c", n, m, i, j, hv[0]);
	 if (j > n) begin
	    // jReg points to the end of the haystack; we are done
	    compf.enq(?);
	    stage <= Ready;
	    //$display("end of search %d", j);
	 end
	 else if (i==m+1) begin
	    // iReg points to the end of the needle; we have a match
	    //$display("string match %d", j);
	    locf.enq(unpack(haystackBase+j-i));
	    epochReg <= epochReg + 1;
	    iReg <= 1;
	 end
	 else if ((i>0) && (nv != hv[0])) begin
	    // mismatch betwen head of haystack and head of needle; rewind iReg
	    //$display("char mismatch %d %d MP_Next[i]=%d", i, j, mp);
	    epochReg <= epochReg + 1;
	    iReg <= mp;
	 end
	 else begin
	    // match between head of needle and head of haystack; increment haystack
	    //$display("char match %d %d", i, j);
	    jReg <= j+1;
	    haystack.deq;
	 end
      end
      else begin
	 //$display("discard");
	 noAction;
      end
   endrule

   method Action setup(Bit#(32) needle_pointer, Bit#(32) mpNext_pointer, Bit#(32) needle_len);
      needleLenReg <= extend(needle_len);
      n2b.start(needle_pointer, 0, 0, pack(truncate(needle_len)));
      mp2b.start(mpNext_pointer, 0, 0, pack(truncate(needle_len)));
      jReg <= 0;
      iReg <= 0;
   endmethod

   method Action search(Bit#(32) haystack_pointer, Bit#(32) haystack_len, Bit#(32) haystack_base) if (stage == Ready && !efifo.notEmpty && !haystack.notEmpty);
      $display("search %d %d",  haystack_base, haystack_len);
      haystackLenReg <= extend(haystack_len);
      haystackPointer <= haystack_pointer;
      haystackBase <= extend(haystack_base);
      dmaTag   <= dmaTag+1;
      haystackOff <= 0;
      stage <= Run;
      iReg <= 1;
      jReg <= 1;
      efifo.clear;
      epochReg <= 0;
   endmethod

   interface needle_read_client = n2b.dmaClient;
   interface mp_next_read_client = mp2b.dmaClient;
   interface haystack_read_client = hreader.readClient;

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.

/*
 * Implementation of:
 *    MP algorithm on pages 7-11 from "Pattern Matching Algorithms" by
 *       Alberto Apostolico, Zvi Galil, 1997
 */

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

import AxiMasterSlave::*;
import MemTypes::*;
import Dma2BRAM::*;

interface MPEngine#(numeric type busWidth);
   method Action setup(Bit#(32) needlePointer, Bit#(32) mpNextPointer, Bit#(32) needle_len);
   method Action search(Bit#(32) haystackPointer, Bit#(32) haystack_len, Bit#(32) haystack_base);
   interface ObjectReadClient#(busWidth) needle_read_client;
   interface ObjectReadClient#(busWidth) mp_next_read_client;
   interface ObjectReadClient#(busWidth) haystack_read_client;
endinterface

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

typedef 1024 MaxNeedleLen;
typedef TLog#(MaxNeedleLen) NeedleIdxWidth;
typedef Bit#(NeedleIdxWidth) NeedleIdx;

typedef enum {Idle, Ready, Run} Stage deriving (Eq, Bits);

module mkMPEngine#(FIFOF#(void) compf,
		   FIFOF#(void) conff,
		   FIFOF#(Int#(32)) locf )(MPEngine#(busWidth))

   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));

   Clock clk <- exposeCurrentClock;
   Reset rst <- exposeCurrentReset;
   BRAM2Port#(NeedleIdx, Char) needle  <- mkBRAM2Server(defaultValue);
   BRAM2Port#(NeedleIdx, Bit#(32)) mpNext <- mkBRAM2Server(defaultValue);
   Gearbox#(nc,1,Char) haystack <- mkNto1Gearbox(clk,rst,clk,rst);

   Reg#(Stage)    stage <- mkReg(Idle);
   Reg#(Bit#(32)) needleLenReg <- mkReg(0);
   Reg#(Bit#(32)) haystackLenReg <- mkReg(0);
   Reg#(Bit#(32)) haystackBase <- mkReg(0);
   Reg#(Bit#(32)) jReg <- mkReg(0); // offset in haystack
   Reg#(Bit#(32)) iReg <- mkReg(0); // offset in needle
   Reg#(Bit#(2))  epochReg <- mkReg(0);
   Reg#(Bit#(6))  dmaTag <- mkReg(0);
   Reg#(Bit#(32)) haystackOff <- mkReg(0);
   Reg#(ObjectPointer) haystackPointer <- mkReg(0);

   BRAMReadClient#(NeedleIdxWidth,busWidth) n2b <- mkBRAMReadClient(needle.portB);
   BRAMReadClient#(NeedleIdxWidth,busWidth) mp2b <- mkBRAMReadClient(mpNext.portB);
   MemReader#(busWidth) hreader <- mkMemReader;

   FIFOF#(Tuple2#(Bit#(2),Bit#(32))) efifo <- mkSizedFIFOF(2);

   rule finish_setup;
      $display("mkMPEngine::finish_setup");
      let x <- n2b.finish;
      let y <- mp2b.finish;
      stage <= Ready;
      conff.enq(?);
   endrule

   rule haystackReq (stage == Run && haystackOff < extend(haystackLenReg));
      //$display("haystackReq %x", haystackOff);
      hreader.readServer.readReq.put(ObjectRequest {pointer: haystackPointer, offset: extend(haystackBase+haystackOff), burstLen: fromInteger(valueOf(nc)), tag: dmaTag});
      haystackOff <= haystackOff + fromInteger(valueOf(nc));
   endrule

   rule haystackResp;
      //$display("haystackResp");
      let rv <- hreader.readServer.readData.get;
      Vector#(nc,Char) pv = unpack(rv.data);
      if(rv.tag == dmaTag)
	 haystack.enq(pv);
   endrule

   rule haystackDrain(stage != Run);
      //$display("haystackDrain");
      haystack.deq;
   endrule

   rule bramDrain(stage != Run);
      //$display("mpNextDrain");
      let x <- mpNext.portA.response.get;
      let y <- needle.portA.response.get;
      efifo.deq;
   endrule

   rule matchNeedleReq(stage == Run);
      //$display(" matchNeedleReq %d %d", epochReg, iReg);
      needle.portA.request.put(BRAMRequest{write:False, address: truncate(iReg-1)});
      mpNext.portA.request.put(BRAMRequest{write:False, address: truncate(iReg)});
      efifo.enq(tuple2(epochReg,iReg));
      iReg <= iReg+1;
   endrule

   rule matchNeedleResp(stage == Run);
      let nv <- needle.portA.response.get;
      let mp <- mpNext.portA.response.get;
      let epoch = tpl_1(efifo.first);
      efifo.deq;
      //$display("matchNeedleResp %d %d", epochReg, epoch);
      if (epoch == epochReg) begin
	 let n = haystackLenReg;
	 let m = needleLenReg;
	 let hv = haystack.first;
	 let i = tpl_2(efifo.first);
	 let j = jReg;
	 //$display("feck %d %d %d %d %c", n, m, i, j, hv[0]);
	 if (j > n) begin
	    // jReg points to the end of the haystack; we are done
	    compf.enq(?);
	    stage <= Ready;
	    //$display("end of search %d", j);
	 end
	 else if (i==m+1) begin
	    // iReg points to the end of the needle; we have a match
	    //$display("string match %d", j);
	    locf.enq(unpack(haystackBase+j-i));
	    epochReg <= epochReg + 1;
	    iReg <= 1;
	 end
	 else if ((i>0) && (nv != hv[0])) begin
	    // mismatch betwen head of haystack and head of needle; rewind iReg
	    //$display("char mismatch %d %d MP_Next[i]=%d", i, j, mp);
	    epochReg <= epochReg + 1;
	    iReg <= mp;
	 end
	 else begin
	    // match between head of needle and head of haystack; increment haystack
	    //$display("char match %d %d", i, j);
	    jReg <= j+1;
	    haystack.deq;
	 end
      end
      else begin
	 //$display("discard");
	 noAction;
      end
   endrule

   method Action setup(Bit#(32) needle_pointer, Bit#(32) mpNext_pointer, Bit#(32) needle_len);
      needleLenReg <= extend(needle_len);
      n2b.start(needle_pointer, 0, 0, pack(truncate(needle_len)));
      mp2b.start(mpNext_pointer, 0, 0, pack(truncate(needle_len)));
      jReg <= 0;
      iReg <= 0;
   endmethod

   method Action search(Bit#(32) haystack_pointer, Bit#(32) haystack_len, Bit#(32) haystack_base) if (stage == Ready && !efifo.notEmpty && !haystack.notEmpty);
      $display("search %d %d",  haystack_base, haystack_len);
      haystackLenReg <= extend(haystack_len);
      haystackPointer <= haystack_pointer;
      haystackBase <= extend(haystack_base);
      dmaTag   <= dmaTag+1;
      haystackOff <= 0;
      stage <= Run;
      iReg <= 1;
      jReg <= 1;
      efifo.clear;
      epochReg <= 0;
   endmethod

   interface needle_read_client = n2b.dmaClient;
   interface mp_next_read_client = mp2b.dmaClient;
   interface haystack_read_client = hreader.readClient;

endmodule


working on compilling

working on compilling

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

import AxiClientServer::*;
import AxiRDMA::*;
import BsimRDMA::*;
import PortalMemory::*;
import PortalRMemory::*;
import StmtFSM::*;

import RingTypes::*;

import RingBuffer::*;
import FIFO::*;
import GetPut::*;
import ClientServer::*;
import CopyEngine::*;
import EchoEngine::*;
import NopEngine::*;

interface CoreRequest;
   method Action set(Bit#(1) cmd, Bit#(2) regist, Bit#(40) addr);
   method Action get(Bit#(1) cmd, Bit#(2) regist);
   method Action hwenable(Bit#(1) en);
   method Action doCommandIndirect(Bit#(40) addr);
   method Action doCommandImmediate(CommandStruct cmd);
endinterface

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

interface RingRequest;
   interface Axi3Client#(40,64,8,12) m_axi;
   interface CoreRequest coreRequest;
   interface DMARequest dmaRequest;
endinterface

interface RingIndication;
   interface CoreIndication coreIndication;
   interface DMAIndication dmaIndication;
endinterface

module mkRingRequest#(RingIndication indication)(RingRequest);

`ifdef BSIM
   BsimDMA#(Bit#(64))  dma <- mkBsimDMA(indication.dmaIndication);
`else
   AxiDMA#(Bit#(64))   dma <- mkAxiDMA(indication.dmaIndication);
`endif

   Server#(Bit#(64), Bit#(64)) copyEngine <- mkCopyEngine(dma.read.readChannels[2], dma.write.writeChannels[2]);

   Server#(Bit#(64), Bit#(64)) nopEngine <- mkNopEngine();
   Server#(Bit#(64), Bit#(64)) echoEngine <- mkEchoEngine();

  Server#(Bit#(64), Bit#(64)) responseServer;

   ReadChan#(Bit#(64))   dma_read_chan = dma.read.readChannels[0];
   WriteChan#(Bit#(64)) dma_write_chan = dma.write.writeChannels[0];
   ReadChan#(Bit#(64)) cmd_read_chan = dma.read.readChannels[1];
   WriteChan#(Bit#(64)) status_write_chan = dma.write.writeChannels[1];

   RingBuffer cmdRing <- mkRingBuffer;
   RingBuffer statusRing <- mkRingBuffer;
   Reg#(Bool) hwenabled <- mkReg(False);
   Reg#(Bool) cmdBusy <- mkReg(False);
   Reg#(UInt#(64)) cmd <- mkReg(0);

   let ifcselect = cmd[63:56];
   function Server#(Bit#(64), Bit#(64)) cmdifc();
      if (ifcselect == cmdNOP)
	 return nopEngine;
      else if (ifcselect == cmdCOPY)
	 return copyEngine;
      else if (ifcselect == cmdECHO)
	 return echoServer;
      else
	 return nopEngine;
   endfunction

   method statusput(Bit#(64) d);
      action
	 status_write_chan.writeReq.put(statusRing.expBufferFirst);
	 status_write_chan.writeDataq.put(d);
	 statusRing.push(8);
      endaction
   endmethod;

   // wait for hwenabled
   // wait for not cmdBusy
   // wait for cmdRing not empty
   // then start fetches for the next command
   Stmt cmdFetch =
   seq
      while (True) seq
	 while(!(hwenabled && cmdRing.notEmpty())) noAction;
	 cmd_read_chan.readReq.put(cmdRing.expBufferLast);
	 cmdRing.pop();
      endseq
   endseq;

   let fn = cmd[63:56];

   Stmt cmdDispatch =
   seq
      while (True) seq
	 cmd <= cmd_read_chan.readData.get();
	 cmdifc.put(cmd);
	 for (ii <= 1; ii < 8; ii <= ii + 1)
	    cmdifc.put(cmd_read_chan.readData.get());
      endseq
   endseq;

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

   Stmt responseArbiter =
   seq
      while(True) seq
	 if (statusRing.notFull() && copyEngine.response.notEmpty())
	    for (ii <= 1; ii < 8; ii <= ii + 1)
	       statusput(copyEngine.get());
	 if (statusRing.notFull() && echoEngine.response.notEmpty())
	    for (ii <= 1; ii < 8; ii <= ii + 1)
	       statusput(echoEngine.get());
      endseq;
   endseq;

   rule copyCompletion;
      let v <- ce.response.get();
      indication.coreIndication.completion(1, v);
   endrule

//   rule doCommandRule;
      //let v <- cmd_read_chan.readData.get;
      //doCommandImmediate(v);
//   endrule

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

   interface CoreRequest coreRequest;

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

      method Action doCommandImmediate(CommandStruct cmd);
      	 $display("doCopy %h %h %h", cmd.fromAddress, cmd.toAddress, cmd.count);
	 ce.request.put(cmd);
      endmethod

      method Action set(Bit#(1) cmd, Bit#(2) regist, Bit#(40) addr);
	 if (cmd == 1)
	    cmdRing.set(regist, addr);
	 else
	    statusRing.set(regist, addr);
	 indication.coreIndication.setResult(cmd, regist, addr);
      endmethod

      method Action get(Bit#(1) cmd, Bit#(2) regist);
	 if (cmd == 1)
	    indication.coreIndication.getResult(1, regist, cmdRing.get(regist));
	 else
	    indication.coreIndication.getResult(0, regist,
	       statusRing.get(regist));
      endmethod

      method Action hwenable(Bit#(1) en);
	 hwenabled <= en == 1;
      endmethod

   endinterface

`ifndef BSIM
   interface Axi3Client m_axi = dma.m_axi;
`endif
   interface DMARequest dmaRequest = dma.request;
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 FIFOF::*;
import BRAMFIFO::*;
import GetPut::*;

import AxiClientServer::*;
import AxiRDMA::*;
import BsimRDMA::*;
import PortalMemory::*;
import PortalRMemory::*;
import StmtFSM::*;

import RingTypes::*;

import RingBuffer::*;
import FIFO::*;
import GetPut::*;
import ClientServer::*;
import CopyEngine::*;
import EchoEngine::*;
import NopEngine::*;

interface CoreRequest;
   method Action set(Bit#(1) cmd, Bit#(2) regist, Bit#(40) addr);
   method Action get(Bit#(1) cmd, Bit#(2) regist);
   method Action hwenable(Bit#(1) en);
   method Action doCommandIndirect(Bit#(40) addr);
   method Action doCommandImmediate(CommandStruct cmd);
endinterface

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

interface RingRequest;
   interface Axi3Client#(40,64,8,12) m_axi;
   interface CoreRequest coreRequest;
   interface DMARequest dmaRequest;
endinterface

interface RingIndication;
   interface CoreIndication coreIndication;
   interface DMAIndication dmaIndication;
endinterface

module mkRingRequest#(RingIndication indication)(RingRequest);

`ifdef BSIM
   BsimDMA#(Bit#(64))  dma <- mkBsimDMA(indication.dmaIndication);
`else
   AxiDMA#(Bit#(64))   dma <- mkAxiDMA(indication.dmaIndication);
`endif

   Server#(Bit#(64), Bit#(64)) ce <- mkCopyEngine(dma.read.readChannels[2], dma.write.writeChannels[2]);
   Server#(Bit#(64), Bit#(64)) discardServer <- mkNopServer();
   Server#(Bit#(64), Bit#(64)) echoServer <- mkEchoServer();

   Server#(Bit#(64), Bit#(64)) cmdServer;
   Server#(Bit#(64), Bit#(64)) responseServer;

   ReadChan#(Bit#(64))   dma_read_chan = dma.read.readChannels[0];
   WriteChan#(Bit#(64)) dma_write_chan = dma.write.writeChannels[0];
   ReadChan#(CommandStruct) cmd_read_chan = dma.read.readChannels[1];
   WriteChan#(Bit#(64)) status_write_chan = dma.write.writeChannels[1];

   RingBuffer cmdRing <- mkRingBuffer;
   RingBuffer statusRing <- mkRingBuffer;
   Reg#(Bool) hwenabled <- mkReg(False);
   Reg#(Bool) cmdBusy <- mkReg(False);
   UInt#(64) cmd;

   // wait for hwenabled
   // wait for not cmdBusy
   // wait for cmdRing not empty
   // then start fetches for the next command
   Stmt CmdFetch =
   seq
      while (True) seq
	 while(!(hwenabled && cmdRing.notEmpty())) noAction;
	 cmd_read_chan.readReq.put(cmdRing.expBufferLast);
	 cmdRing.expBufferLast <= cmdRing.expBufferLast + 8;
      endseq
   endseq

   function UInt#(8) getopcode(UInt#(64) a);
      return a[63:56];
   endfunction

   Stmt CmdDispatch =
   seq
      while (True) seq
	 cmd = cmd_read_chan.readData.get();
	 let fn = getopcode(cmd);
	 if (fn == cmdNop)
	    cmdServer = nopServer;
	 else if (fn == cmdCOPY)
	    cmdServer = ce;
	 else if (fn == cmdECHO)
	    cmdServer = echoServer;
	 cmdServer.put(cmd);
	 for (ii = 1; ii < 8; ii = ii + 1)
	    cmdServer.put(cmd_read_chan.readData.get());
      endseq
   endseq

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

   rule copyCompletion;
      let v <- ce.response.get();
      indication.coreIndication.completion(1, v);
   endrule

//   rule doCommandRule;
      //let v <- cmd_read_chan.readData.get;
      //doCommandImmediate(v);
//   endrule

   interface CoreRequest coreRequest;

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

      method Action doCommandImmediate(CommandStruct cmd);
      	 $display("doCopy %h %h %h", cmd.fromAddress, cmd.toAddress, cmd.count);
	 ce.request.put(cmd);
      endmethod

      method Action set(Bit#(1) cmd, Bit#(2) regist, Bit#(40) addr);
	 if (cmd == 1)
	    cmdRing.set(regist, addr);
	 else
	    statusRing.set(regist, addr);
	 indication.coreIndication.setResult(cmd, regist, addr);
      endmethod

      method Action get(Bit#(1) cmd, Bit#(2) regist);
	 if (cmd == 1)
	    indication.coreIndication.getResult(1, regist, cmdRing.get(regist));
	 else
	    indication.coreIndication.getResult(0, regist,
	       statusRing.get(regist));
      endmethod

      method Action hwenable(Bit#(1) en);
	 hwenabled <= en == 1;
      endmethod

   endinterface

`ifndef BSIM
   interface Axi3Client m_axi = dma.m_axi;
`endif
   interface DMARequest dmaRequest = dma.request;
endmodule


fix up msgFromSoftware and msgToSoftware in the string search accelerator

// Copyright (c) 2016 Connectal Project

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Arbitrate::*;
import BRAM::*;
import BuildVector::*;
import Clocks::*;
import Connectable::*;
import FIFOF::*;
import Gearbox::*;
import GetPut::*;
import Probe::*;
import StmtFSM::*;
import Vector::*;

import AddressGenerator::*;
import AxiBits::*;
import AxiStream::*;
import ConnectalClocks::*;
import ConnectalConfig::*;
import DefaultValue::*;
import GearboxGetPut::*;
import HostInterface::*;
import MemReadEngine::*;
import MemTypes::*;
import PhysMemSlaveFromBram::*;
import Pipe::*;
import TraceMemClient::*;
import XilinxCells::*;
import MPEngine::*;

import Nvme::*;
import NvmeIfc::*;
import NvmePins::*;
import StringSearchIfc::*;

interface NvmeSearch;
   interface NvmeRequest request;
   interface NvmeDriverRequest driverRequest;
   interface MemServerPortalRequest bramRequest;
   interface StringSearchRequest searchRequest;
   interface NvmeTrace trace;
   interface NvmePins pins;
   interface Vector#(2, MemReadClient#(DataBusWidth)) dmaReadClient;
   interface Vector#(1, MemWriteClient#(DataBusWidth)) dmaWriteClient;
`ifdef TOP_SOURCES_PORTAL_CLOCK
   interface Clock portalClockSource;
`endif
endinterface

typedef enum {
   Loopback,
   Needle,
   MpNext,
   Clear,
   Opcode,
   StartBlock,
   NumBlocks,
   Start
   } MsgFromSoftwareTag deriving (Bits,Eq);

typedef struct {
   MsgFromSoftwareTag tag;
   Bit#(24)  data;
   } MsgFromSoftware deriving (Bits);

typedef enum {
   Loopback=1,
   LocDone=2,
   TransferDone=3
   } MsgToSoftwareTag deriving (Bits,Eq);

typedef struct {
   MsgToSoftwareTag tag;
   Bit#(24)  data;
   } MsgToSoftware deriving (Bits);

(* synthesize *)
module mkSearchAcceleratorClient(NvmeAcceleratorClient);
   Reg#(Bit#(32))                       dataCounter <- mkReg(0);
   FIFOF#(Bit#(32))                  dataLengthFifo <- mkFIFOF();
   Reg#(Bit#(24))                      needleLenReg <- mkReg(0);
   MPStreamEngine#(PcieDataBusWidth,DataBusWidth)    mpEngine <- mkMPStreamEngine();

   FIFOF#(MemData#(32)) msgFromSoftwareFifo <- mkFIFOF();
   FIFOF#(MemData#(32)) msgToSoftwareFifo <- mkFIFOF();
   FIFOF#(MemDataF#(PcieDataBusWidth)) dataFromNvmeFifo <- mkFIFOF();
   FIFOF#(MemDataF#(PcieDataBusWidth)) dataToNvmeFifo <- mkFIFOF();
   FIFOF#(Bit#(SizeOf#(NvmeIoCommand))) requestFifo <- mkFIFOF();
   FIFOF#(Bit#(SizeOf#(NvmeIoResponse))) responseFifo <- mkFIFOF();

   mkConnection(toPipeOut(dataFromNvmeFifo), mpEngine.haystack);

   Reg#(Bit#(8)) opcode <- mkReg(extend(pack(NvmeRead)));
   Reg#(Bit#(32)) startBlock <- mkReg(0);
   Reg#(Bit#(32))  numBlocks <- mkReg(0);
   Reg#(Bit#(16)) requestId <- mkReg(0);

   let inmsgTagProbe <- mkProbe();
   let inmsgDataProbe <- mkProbe();
   let outmsgTagProbe <- mkProbe();
   let outmsgDataProbe <- mkProbe();
   let responseProbe <- mkProbe();
   rule rl_msg_from_software;
      let md <- toGet(msgFromSoftwareFifo).get();
      MsgFromSoftware msg = unpack(truncate(md.data));
      inmsgTagProbe <= msg.tag;
      inmsgDataProbe <= msg.data;
      case (msg.tag) matches
	 Loopback: begin
		      MsgToSoftware outmsg = MsgToSoftware { tag: Loopback, data: msg.data };
		      outmsgTagProbe <= outmsg.tag;
		      outmsgDataProbe <= outmsg.data;
		      msgToSoftwareFifo.enq(MemData { data: extend(pack(outmsg)), last: md.last });
		   end
	 Needle: mpEngine.needle.enq(MemDataF { data: extend(msg.data), first: False, last: md.last, tag: 0 });
	 MpNext: mpEngine.mpNext.enq(MemDataF { data: extend(msg.data), first: False, last: md.last, tag: 0 });
	 Clear:  mpEngine.clear();
	 Opcode:         opcode <= truncate(msg.data);
	 StartBlock: startBlock <= extend(msg.data);
	 NumBlocks:   numBlocks <= extend(msg.data);
	 Start: begin
		   mpEngine.start(extend(msg.data));
		   needleLenReg <= msg.data;
		   requestFifo.enq(pack(NvmeIoCommand {
		      opcode: opcode,
		      flags: 0,
		      requestId: requestId,
		      startBlock: extend(startBlock),
		      numBlocks: numBlocks,
		      dsm: 'h71 // FIXME copied value from nvme.cpp, but where did this come from?
		      }));
		   requestId <= requestId + 1;
		end
      endcase
   endrule
   rule rl_response;
      let r <- toGet(responseFifo).get();
      NvmeIoResponse response = unpack(r);
      Bit#(8) sct = truncate(response.statusCodeType);
      responseProbe <= response.statusCode;

      MsgToSoftware outmsg = MsgToSoftware { tag: TransferDone, data: { sct, response.statusCode }};
      outmsgTagProbe <= outmsg.tag;
      outmsgDataProbe <= outmsg.data;
      msgToSoftwareFifo.enq(MemData { data: extend(pack(outmsg)), last: True });
   endrule
   rule rl_match;
      let loc <- toGet(mpEngine.locdone).get();
      MsgToSoftware outmsg = MsgToSoftware { tag: LocDone, data: truncate(pack(loc)) };
      outmsgTagProbe <= outmsg.tag;
      outmsgDataProbe <= outmsg.data;
      msgToSoftwareFifo.enq(MemData { data: extend(pack(outmsg)), last: (loc == -1) });
   endrule

   AxiStreamSlave#(32) msgFromSoftwareStream <- mkAxiStream(msgFromSoftwareFifo);
   AxiStreamMaster#(32) msgToSoftwareStream <- mkAxiStream(msgToSoftwareFifo);
   AxiStreamSlave#(PcieDataBusWidth) dataFromNvmeStream <- mkAxiStream(dataFromNvmeFifo);
   AxiStreamMaster#(PcieDataBusWidth) dataToNvmeStream <- mkAxiStream(dataToNvmeFifo);
   AxiStreamMaster#(SizeOf#(NvmeIoCommand)) requestStream <- mkAxiStream(requestFifo);
   AxiStreamSlave#(SizeOf#(NvmeIoResponse)) responseStream <- mkAxiStream(responseFifo);

   interface AxiStreamSlave msgFromSoftware = msgFromSoftwareStream;
   interface AxiStreamMaster msgToSoftware = msgToSoftwareStream;
   interface AxiStreamSlave dataFromNvme = dataFromNvmeStream;
   interface AxiStreamMaster dataToNvme = dataToNvmeStream;
   interface AxiStreamMaster request = requestStream;
   interface AxiStreamSlave response = responseStream;

endmodule

module mkNvmeSearch#(NvmeIndication ind, NvmeDriverIndication driverInd, NvmeTrace trace, MemServerPortalIndication bramIndication,
	       StringSearchResponse searchIndication)(NvmeSearch);

   let nvme <- mkNvme(ind, driverInd, trace, bramIndication);

   MemReadEngine#(DataBusWidth,DataBusWidth,2,3) re <- mkMemReadEngine();

`ifndef NVME_ACCELERATOR_INTERFACE
   Reg#(Bit#(32))                       dataCounter <- mkReg(0);
   FIFOF#(Bit#(32))                  dataLengthFifo <- mkFIFOF();
   FIFOF#(MemDataF#(PcieDataBusWidth))     fifoToMp <- mkFIFOF();
   let                                 needleLenReg <- mkReg(0);
   MPStreamEngine#(PcieDataBusWidth,DataBusWidth)    mpEngine <- mkMPStreamEngine();
   mkConnection(re.readServers[0].data, mpEngine.needle);
   mkConnection(re.readServers[1].data, mpEngine.mpNext);
   mkConnection(toPipeOut(fifoToMp), mpEngine.haystack);

   Reg#(Bool) firstReg <- mkReg(True);
   rule rl_count_data_to_mp;
      let data <- toGet(nvme.dataFromNvme).get();
      if (dataLengthFifo.notEmpty()) begin
	 data.last = (dataCounter+fromInteger(valueOf(PcieDataBusWidth)/8)) >= dataLengthFifo.first;
	 let md = MemDataF {data: data.data, last: data.last, first: firstReg, tag: 0};
	 firstReg <= data.last;
	 fifoToMp.enq(md);
      end
      dataCounter <= dataCounter + 1;
   endrule

   rule rl_locdone;
      let loc <- toGet(mpEngine.locdone).get();
      searchIndication.strstrLoc(pack(loc));
   endrule
`endif

   interface NvmeRequest                request = nvme.request;
   interface NvmeDriverRequest    driverRequest = nvme.driverRequest;
   interface MemServerPortalRequest bramRequest = nvme.bramRequest;
   interface NvmeTrace                    trace = nvme.trace;
   interface NvmePins                      pins = nvme.pins;
   interface StringSearchRequest searchRequest;
      method Action setSearchString(Bit#(32) needleSglId, Bit#(32) mpNextSglId, Bit#(32) needleLen);
`ifndef NVME_ACCELERATOR_INTERFACE
	 mpEngine.clear();
	 needleLenReg <= needleLen;

	 let burstLen = fromInteger(valueOf(DataBusWidth)/8);
	 let mask = burstLen - 1;
	 needleLen = (needleLen + mask) & ~mask;
	 re.readServers[0].request.put(MemengineCmd {sglId: needleSglId, base: 0, burstLen: burstLen, len: needleLen, tag: 0});
	 re.readServers[1].request.put(MemengineCmd {sglId: mpNextSglId, base: 0, burstLen: burstLen, len: needleLen*4, tag: 0});
`endif
      endmethod
      method Action startSearch(Bit#(32) haystackLen);
`ifndef NVME_ACCELERATOR_INTERFACE
	 mpEngine.start(needleLenReg);
	 dataLengthFifo.enq(haystackLen);
`endif
      endmethod
   endinterface
   interface Clock portalClockSource = nvme.portalClockSource;
   interface Vector dmaReadClient = append(nvme.dmaReadClient, vec(re.dmaClient));
   interface Vector dmaWriteClient = nvme.dmaWriteClient;
endmodule

// Copyright (c) 2016 Connectal Project

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Arbitrate::*;
import BRAM::*;
import BuildVector::*;
import Clocks::*;
import Connectable::*;
import FIFOF::*;
import Gearbox::*;
import GetPut::*;
import Probe::*;
import StmtFSM::*;
import Vector::*;

import AddressGenerator::*;
import AxiBits::*;
import AxiStream::*;
import ConnectalClocks::*;
import ConnectalConfig::*;
import DefaultValue::*;
import GearboxGetPut::*;
import HostInterface::*;
import MemReadEngine::*;
import MemTypes::*;
import PhysMemSlaveFromBram::*;
import Pipe::*;
import TraceMemClient::*;
import XilinxCells::*;
import MPEngine::*;

import Nvme::*;
import NvmeIfc::*;
import NvmePins::*;
import StringSearchIfc::*;

interface NvmeSearch;
   interface NvmeRequest request;
   interface NvmeDriverRequest driverRequest;
   interface MemServerPortalRequest bramRequest;
   interface StringSearchRequest searchRequest;
   interface NvmeTrace trace;
   interface NvmePins pins;
   interface Vector#(2, MemReadClient#(DataBusWidth)) dmaReadClient;
   interface Vector#(1, MemWriteClient#(DataBusWidth)) dmaWriteClient;
`ifdef TOP_SOURCES_PORTAL_CLOCK
   interface Clock portalClockSource;
`endif
endinterface

typedef enum {
   Loopback,
   Needle,
   MpNext,
   Clear,
   Opcode,
   StartBlock,
   NumBlocks,
   Start
   } MsgFromSoftwareTag deriving (Bits,Eq);

typedef struct {
   Bool     last;
   MsgFromSoftwareTag tag;
   Bit#(24)  data;
   } MsgFromSoftware deriving (Bits);

typedef enum {
   Loopback,
   LocDone,
   TransferDone
   } MsgToSoftwareTag deriving (Bits,Eq);

typedef struct {
   Bool     last;
   MsgToSoftwareTag tag;
   Bit#(24)  data;
   } MsgToSoftware deriving (Bits);

(* synthesize *)
module mkSearchAcceleratorClient(NvmeAcceleratorClient);
   Reg#(Bit#(32))                       dataCounter <- mkReg(0);
   FIFOF#(Bit#(32))                  dataLengthFifo <- mkFIFOF();
   Reg#(Bit#(24))                      needleLenReg <- mkReg(0);
   MPStreamEngine#(PcieDataBusWidth,DataBusWidth)    mpEngine <- mkMPStreamEngine();

   FIFOF#(Bit#(32)) msgFromSoftwareFifo <- mkFIFOF();
   FIFOF#(Bit#(32)) msgToSoftwareFifo <- mkFIFOF();
   FIFOF#(MemDataF#(PcieDataBusWidth)) dataFromNvmeFifo <- mkFIFOF();
   FIFOF#(MemDataF#(PcieDataBusWidth)) dataToNvmeFifo <- mkFIFOF();
   FIFOF#(Bit#(SizeOf#(NvmeIoCommand))) requestFifo <- mkFIFOF();
   FIFOF#(Bit#(SizeOf#(NvmeIoResponse))) responseFifo <- mkFIFOF();

   mkConnection(toPipeOut(dataFromNvmeFifo), mpEngine.haystack);

   Reg#(Bit#(8)) opcode <- mkReg(extend(pack(NvmeRead)));
   Reg#(Bit#(32)) startBlock <- mkReg(0);
   Reg#(Bit#(32))  numBlocks <- mkReg(0);
   Reg#(Bit#(16)) requestId <- mkReg(0);

   let inmsgTagProbe <- mkProbe();
   let inmsgDataProbe <- mkProbe();
   let outmsgTagProbe <- mkProbe();
   let outmsgDataProbe <- mkProbe();
   rule rl_msg_from_software;
      let m <- toGet(msgFromSoftwareFifo).get();
      MsgFromSoftware msg = unpack(truncate(m));
      inmsgTagProbe <= msg.tag;
      inmsgDataProbe <= msg.data;
      case (msg.tag) matches
	 Loopback: begin
		      MsgToSoftware msg = MsgToSoftware { tag: Loopback, data: msg.data, last: msg.last};
		      outmsgTagProbe <= msg.tag;
		      outmsgDataProbe <= msg.data;
		      msgToSoftwareFifo.enq(extend(pack(msg)));
		   end
	 Needle: mpEngine.needle.enq(MemDataF { data: extend(msg.data), first: False, last: msg.last, tag: 0 });
	 MpNext: mpEngine.mpNext.enq(MemDataF { data: extend(msg.data), first: False, last: msg.last, tag: 0 });
	 Clear:  mpEngine.clear();
	 Opcode:         opcode <= truncate(msg.data);
	 StartBlock: startBlock <= extend(msg.data);
	 NumBlocks:   numBlocks <= extend(msg.data);
	 Start: begin
		   mpEngine.start(extend(msg.data));
		   needleLenReg <= msg.data;
		   requestFifo.enq(pack(NvmeIoCommand {
		      opcode: opcode,
		      flags: 0,
		      requestId: requestId,
		      startBlock: extend(startBlock),
		      numBlocks: numBlocks,
		      dsm: 'h71 // FIXME copied value from nvme.cpp, but where did this come from?
		      }));
		   requestId <= requestId + 1;
		end
      endcase
   endrule
   rule rl_response;
      let r <- toGet(responseFifo).get();
      NvmeIoResponse response = unpack(r);
      Bit#(8) sct = truncate(response.statusCodeType);

      MsgToSoftware msg = MsgToSoftware { tag: TransferDone, data: { sct, response.statusCode }, last: True};
      outmsgTagProbe <= msg.tag;
      outmsgDataProbe <= msg.data;
      msgToSoftwareFifo.enq(extend(pack(msg)));
   endrule
   rule rl_match;
      let loc <- toGet(mpEngine.locdone).get();
      MsgToSoftware msg = MsgToSoftware { tag: LocDone, data: truncate(pack(loc)), last: loc == -1 };
      outmsgTagProbe <= msg.tag;
      outmsgDataProbe <= msg.data;
      msgToSoftwareFifo.enq(extend(pack(msg)));
   endrule

   AxiStreamSlave#(32) msgFromSoftwareStream <- mkAxiStream(msgFromSoftwareFifo);
   AxiStreamMaster#(32) msgToSoftwareStream <- mkAxiStream(msgToSoftwareFifo);
   AxiStreamSlave#(PcieDataBusWidth) dataFromNvmeStream <- mkAxiStream(dataFromNvmeFifo);
   AxiStreamMaster#(PcieDataBusWidth) dataToNvmeStream <- mkAxiStream(dataToNvmeFifo);
   AxiStreamMaster#(SizeOf#(NvmeIoCommand)) requestStream <- mkAxiStream(requestFifo);
   AxiStreamSlave#(SizeOf#(NvmeIoResponse)) responseStream <- mkAxiStream(responseFifo);

   interface AxiStreamSlave msgFromSoftware = msgFromSoftwareStream;
   interface AxiStreamMaster msgToSoftware = msgToSoftwareStream;
   interface AxiStreamSlave dataFromNvme = dataFromNvmeStream;
   interface AxiStreamMaster dataToNvme = dataToNvmeStream;
   interface AxiStreamMaster request = requestStream;
   interface AxiStreamSlave response = responseStream;

endmodule

module mkNvmeSearch#(NvmeIndication ind, NvmeDriverIndication driverInd, NvmeTrace trace, MemServerPortalIndication bramIndication,
	       StringSearchResponse searchIndication)(NvmeSearch);

   let nvme <- mkNvme(ind, driverInd, trace, bramIndication);

   MemReadEngine#(DataBusWidth,DataBusWidth,2,3) re <- mkMemReadEngine();

`ifndef NVME_ACCELERATOR_INTERFACE
   Reg#(Bit#(32))                       dataCounter <- mkReg(0);
   FIFOF#(Bit#(32))                  dataLengthFifo <- mkFIFOF();
   FIFOF#(MemDataF#(PcieDataBusWidth))     fifoToMp <- mkFIFOF();
   let                                 needleLenReg <- mkReg(0);
   MPStreamEngine#(PcieDataBusWidth,DataBusWidth)    mpEngine <- mkMPStreamEngine();
   mkConnection(re.readServers[0].data, mpEngine.needle);
   mkConnection(re.readServers[1].data, mpEngine.mpNext);
   mkConnection(toPipeOut(fifoToMp), mpEngine.haystack);

   Reg#(Bool) firstReg <- mkReg(True);
   rule rl_count_data_to_mp;
      let data <- toGet(nvme.dataFromNvme).get();
      if (dataLengthFifo.notEmpty()) begin
	 data.last = (dataCounter+fromInteger(valueOf(PcieDataBusWidth)/8)) >= dataLengthFifo.first;
	 let md = MemDataF {data: data.data, last: data.last, first: firstReg, tag: 0};
	 firstReg <= data.last;
	 fifoToMp.enq(md);
      end
      dataCounter <= dataCounter + 1;
   endrule

   rule rl_locdone;
      let loc <- toGet(mpEngine.locdone).get();
      searchIndication.strstrLoc(pack(loc));
   endrule
`endif

   interface NvmeRequest                request = nvme.request;
   interface NvmeDriverRequest    driverRequest = nvme.driverRequest;
   interface MemServerPortalRequest bramRequest = nvme.bramRequest;
   interface NvmeTrace                    trace = nvme.trace;
   interface NvmePins                      pins = nvme.pins;
   interface StringSearchRequest searchRequest;
      method Action setSearchString(Bit#(32) needleSglId, Bit#(32) mpNextSglId, Bit#(32) needleLen);
`ifndef NVME_ACCELERATOR_INTERFACE
	 mpEngine.clear();
	 needleLenReg <= needleLen;

	 let burstLen = fromInteger(valueOf(DataBusWidth)/8);
	 let mask = burstLen - 1;
	 needleLen = (needleLen + mask) & ~mask;
	 re.readServers[0].request.put(MemengineCmd {sglId: needleSglId, base: 0, burstLen: burstLen, len: needleLen, tag: 0});
	 re.readServers[1].request.put(MemengineCmd {sglId: mpNextSglId, base: 0, burstLen: burstLen, len: needleLen*4, tag: 0});
`endif
      endmethod
      method Action startSearch(Bit#(32) haystackLen);
`ifndef NVME_ACCELERATOR_INTERFACE
	 mpEngine.start(needleLenReg);
	 dataLengthFifo.enq(haystackLen);
`endif
      endmethod
   endinterface
   interface Clock portalClockSource = nvme.portalClockSource;
   interface Vector dmaReadClient = append(nvme.dmaReadClient, vec(re.dmaClient));
   interface Vector dmaWriteClient = nvme.dmaWriteClient;
endmodule


Adding display statements to RVUart

Adding display statements to RVUart

import ClientServer::*;
import RS232::*;
import Vector::*;
import GetPut::*;
import Vector::*;
import BuildVector::*;
import Ehr::*;

import Abstraction::*;

interface RVUart#(numeric type cores);
  // Internal connections
  interface UncachedMemServer memifc;

  // external connections for rx/tx (to be connected to a UART
  (* prefix = "" *)
  interface RS232 uart_pins;
  //method Action rx (Bit#(1) x);
  // method Bit#(1) tx;
  method Bit#(16) divisor;
  method Vector#(cores, Bool) receiveInterrupt;
endinterface

module mkRVUart_RV32#(Bit#(16) divisor)(RVUart#(1))
    provisos (NumAlias#(internalAddrSize, 8));
  // Layout of memory interface (mostly derived by SiFive Freedom E300)
  // Address   Name     Description
  // 0x0000    txData   Transmit data register
  // 0x0004    rxData   Receive data register
  // 0x0008    txCtrl   Transmit control register
  // 0x000C    rxCtrl   Receive control register
  // 0x0010    div      Baud rate divisor
  Bit#(internalAddrSize) txDataAddr = 'h0;
  Bit#(internalAddrSize) rxDataAddr = 'h4;
  Bit#(internalAddrSize) txCtrlAddr = 'h8;
  Bit#(internalAddrSize) rxCtrlAddr = 'hC;
  Bit#(internalAddrSize) divAddr    = 'h10;

  // TODO: Make a circular ring buffer for that we can then pass to connectal for
  //       memory mapped interface
  // ie. txDataRing 0x000 -> index_1[31:24], index_2[23:16], index_3[15:8], index_4[7:0]
  //     txTailPtr  0x004 -> ptr to whats next in the ring buffer
  Ehr#(2, Maybe#(Tuple2#(Bool, Bit#(internalAddrSize)))) pendingReq <- mkEhr(tagged Invalid);

  // BSV specific UART configuration
  // BSV UART implementation does a few things
  // its interface:
  // interface UART#(numeric type depth);
  //   interface RS232          rs232;
  //     method sout = rXmitDataOut;
  //     method sin  = rRecvData._write;
  //   interface Get#(Bit#(8))  tx;
  //     method ActionValue#(Bit#(8)) get;
  //   interface Put#(Bit#(8))  rx;
  //     method Action put(x)
  // Get and Put have FiFos attached to the ends of them
  Reg#(Bit#(16)) divReg <- mkReg(divisor);
  UART#(16) uart <- mkUART(8, NONE, STOP_1, divReg);
  // Data registers
  Reg#(Maybe#(Bit#(8))) txDataReg <- mkReg(tagged Invalid);
  Reg#(Maybe#(Bit#(8))) rxDataReg <- mkReg(tagged Invalid);
  Reg#(Bit#(32)) txCtrlReg <- mkReg(0);
  Reg#(Bit#(32)) rxCtrlReg <- mkReg(0);

  Ehr#(2, Bool) interruptReg <- mkEhr(False);

  rule doTxData (txDataReg matches tagged Valid .x);
    // There is an implicit guard on the Fifo for uart.put
    uart.rx.put(x);
    txDataReg <= tagged Invalid;
  endrule

  rule doRxData (rxDataReg matches tagged Invalid .x);
    // There is an implicit guard on the Fifo for uart.get
    let data <- uart.tx.get;
    rxDataReg <= Valid(data);
    interruptReg[0] <= True;
  endrule

  interface UncachedMemServer memifc;
    interface Put request;
      method Action put(UncachedMemReq req) if (!isValid(pendingReq[1]));
        if (req.write) begin
          $display("memory write: %h, data: %h", req.addr, req.data);
          case (truncate(req.addr))
            txDataAddr: begin
                          txDataReg <= tagged Valid(truncate(req.data));
                        end
            rxDataAddr: noAction;
            txCtrlAddr: txCtrlReg  <= req.data;
            rxCtrlAddr: rxCtrlReg  <= req.data;
            divAddr:    divReg     <= truncate(req.data);
            default: noAction;
          endcase
          pendingReq[1] <= tagged Valid tuple2(True, truncate(req.addr));
        end else begin
          pendingReq[1] <= tagged Valid tuple2(False, truncate(req.addr));
        end
      endmethod
    endinterface
    interface Get response;
      method ActionValue#(UncachedMemResp) get if (pendingReq[0] matches tagged Valid .reqTuple);
        Bool write = tpl_1(reqTuple);
        Bit#(internalAddrSize) addr = tpl_2(reqTuple);
        Bit#(32) retVal = 0;
        $display("memory read: %h", addr);
        case (truncate(addr))
          txDataAddr: begin
                        retVal = 0;
                        if (txDataReg matches tagged Valid .x) begin
                          retVal = {1'b1, '0, x};
                        end
                      end
          rxDataAddr: begin
                        retVal = 0;
                        if (rxDataReg matches tagged Valid .x) begin
                          retVal = {1'b1, '0, x};
                          rxDataReg <= tagged Invalid;
                          end
                      end
          txCtrlAddr: retVal = txCtrlReg;
          rxCtrlAddr: retVal = rxCtrlReg;
          divAddr:    retVal = {'0, divReg};
          default:    retVal = 0;
        endcase
        pendingReq[0] <= tagged Invalid;
        return UncachedMemResp{ write: write, data: write? 0: retVal };
      endmethod
    endinterface
  endinterface

  interface RS232 uart_pins = uart.rs232;
  method Bit#(16) divisor = divReg;
  method Vector#(1, Bool) receiveInterrupt = vec(interruptReg[0]);

endmodule

import ClientServer::*;
import RS232::*;
import Vector::*;
import GetPut::*;
import Vector::*;
import BuildVector::*;
import Ehr::*;

import Abstraction::*;

interface RVUart#(numeric type cores);
  // Internal connections
  interface UncachedMemServer memifc;

  // external connections for rx/tx (to be connected to a UART
  (* prefix = "" *)
  interface RS232 uart_pins;
  //method Action rx (Bit#(1) x);
  // method Bit#(1) tx;
  method Bit#(16) divisor;
  method Vector#(cores, Bool) receiveInterrupt;
endinterface

module mkRVUart_RV32#(Bit#(16) divisor)(RVUart#(1))
    provisos (NumAlias#(internalAddrSize, 8));
  // Layout of memory interface (mostly derived by SiFive Freedom E300)
  // Address   Name     Description
  // 0x0000    txData   Transmit data register
  // 0x0004    rxData   Receive data register
  // 0x0008    txCtrl   Transmit control register
  // 0x000C    rxCtrl   Receive control register
  // 0x0010    div      Baud rate divisor
  Bit#(internalAddrSize) txDataAddr = 'h0;
  Bit#(internalAddrSize) rxDataAddr = 'h4;
  Bit#(internalAddrSize) txCtrlAddr = 'h8;
  Bit#(internalAddrSize) rxCtrlAddr = 'hC;
  Bit#(internalAddrSize) divAddr    = 'h10;

  // TODO: Make a circular ring buffer for that we can then pass to connectal for
  //       memory mapped interface
  // ie. txDataRing 0x000 -> index_1[31:24], index_2[23:16], index_3[15:8], index_4[7:0]
  //     txTailPtr  0x004 -> ptr to whats next in the ring buffer
  Ehr#(2, Maybe#(Tuple2#(Bool, Bit#(internalAddrSize)))) pendingReq <- mkEhr(tagged Invalid);

  // BSV specific UART configuration
  // BSV UART implementation does a few things
  // its interface:
  // interface UART#(numeric type depth);
  //   interface RS232          rs232;
  //     method sout = rXmitDataOut;
  //     method sin  = rRecvData._write;
  //   interface Get#(Bit#(8))  tx;
  //     method ActionValue#(Bit#(8)) get;
  //   interface Put#(Bit#(8))  rx;
  //     method Action put(x)
  // Get and Put have FiFos attached to the ends of them
  Reg#(Bit#(16)) divReg <- mkReg(divisor);
  UART#(16) uart <- mkUART(8, NONE, STOP_1, divReg);
  // Data registers
  Reg#(Maybe#(Bit#(8))) txDataReg <- mkReg(tagged Invalid);
  Reg#(Maybe#(Bit#(8))) rxDataReg <- mkReg(tagged Invalid);
  Reg#(Bit#(32)) txCtrlReg <- mkReg(0);
  Reg#(Bit#(32)) rxCtrlReg <- mkReg(0);

  Ehr#(2, Bool) interruptReg <- mkEhr(False);

  rule doTxData (txDataReg matches tagged Valid .x);
    // There is an implicit guard on the Fifo for uart.put
    uart.rx.put(x);
    txDataReg <= tagged Invalid;
  endrule

  rule doRxData (rxDataReg matches tagged Invalid .x);
    // There is an implicit guard on the Fifo for uart.get
    let data <- uart.tx.get;
    rxDataReg <= Valid(data);
    interruptReg[0] <= True;
  endrule

  interface UncachedMemServer memifc;
    interface Put request;
      method Action put(UncachedMemReq req) if (!isValid(pendingReq[1]));
        if (req.write) begin
          case (truncate(req.addr))
            txDataAddr: begin
                          txDataReg <= tagged Valid(truncate(req.data));
                        end
            rxDataAddr: noAction;
            txCtrlAddr: txCtrlReg  <= req.data;
            rxCtrlAddr: rxCtrlReg  <= req.data;
            divAddr:    divReg     <= truncate(req.data);
            default: noAction;
          endcase
          pendingReq[1] <= tagged Valid tuple2(True, truncate(req.addr));
        end else begin
          pendingReq[1] <= tagged Valid tuple2(False, truncate(req.addr));
        end
      endmethod
    endinterface
    interface Get response;
      method ActionValue#(UncachedMemResp) get if (pendingReq[0] matches tagged Valid .reqTuple);
        Bool write = tpl_1(reqTuple);
        Bit#(internalAddrSize) addr = tpl_2(reqTuple);
        Bit#(32) retVal = 0;
        case (truncate(addr))
          txDataAddr: begin
                        retVal = 0;
                        if (txDataReg matches tagged Valid .x) begin
                          retVal = {1'b1, '0, x};
                        end
                      end
          rxDataAddr: begin
                        retVal = 0;
                        if (rxDataReg matches tagged Valid .x) begin
                          retVal = {1'b1, '0, x};
                          rxDataReg <= tagged Invalid;
                          end
                      end
          txCtrlAddr: retVal = txCtrlReg;
          rxCtrlAddr: retVal = rxCtrlReg;
          divAddr:    retVal = {'0, divReg};
          default:    retVal = 0;
        endcase
        pendingReq[0] <= tagged Invalid;
        return UncachedMemResp{ write: write, data: write? 0: retVal };
      endmethod
    endinterface
  endinterface

  interface RS232 uart_pins = uart.rs232;
  method Bit#(16) divisor = divReg;
  method Vector#(1, Bool) receiveInterrupt = vec(interruptReg[0]);

endmodule


switched to read_servers interface of MemreadEngine, test first and last fields

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

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import FIFO::*;
import FIFOF::*;
import Vector::*;
import BuildVector::*;
import GetPut::*;
import ClientServer::*;

import Pipe::*;
import MemTypes::*;
import MemreadEngine::*;
import HostInterface::*;

interface ReadTestRequest;
   method Action startRead(Bit#(32) pointer, Bit#(32) numBytes, Bit#(32) burstLen, Bit#(32) iterCnt);
endinterface

interface ReadTest;
   interface ReadTestRequest request;
   interface Vector#(1,MemReadClient#(DataBusWidth)) dmaClient;
endinterface

interface ReadTestIndication;
   method Action readDone(Bit#(32) mismatchCount);
endinterface

typedef 14 NumOutstandingRequests;
typedef TMul#(NumOutstandingRequests,TMul#(32,4)) BufferSizeBytes;
module mkReadTest#(ReadTestIndication indication) (ReadTest);

   Reg#(SGLId)   pointer <- mkReg(0);
   Reg#(Bit#(32))       numBytes <- mkReg(0);
   Reg#(Bit#(BurstLenSize)) burstLenBytes <- mkReg(0);
   Reg#(Bit#(32))  itersToFinish <- mkReg(0);
   Reg#(Bit#(32))   itersToStart <- mkReg(0);
   Reg#(Bit#(32))        bytesRead <- mkReg(0);
   Reg#(Bit#(32)) mismatchCounts <- mkReg(0);
   MemreadEngine#(DataBusWidth,NumOutstandingRequests,1)        re <- mkMemreadEngineBuff(valueOf(BufferSizeBytes));
   FIFO#(Bit#(32)) checkDoneFifo <- mkFIFO();

   rule start (itersToStart > 0);
      $display("Test: request.put");
      re.read_servers[0].cmdServer.request.put(MemengineCmd{sglId:pointer, base:0, len:numBytes, tag:0, burstLen:burstLenBytes});
      itersToStart <= itersToStart-1;
   endrule

   Reg#(Bit#(DataBusWidth)) vReg <- mkReg(0);
   Reg#(Bit#(DataBusWidth)) vExpectedReg <- mkReg(0);
   Reg#(Bool)               validReg <- mkReg(False);
   Reg#(Bit#(32))           bytesToRead <- mkReg(0);
   Reg#(Bool)               lastReg <- mkReg(False);
   rule check;
      // first pipeline stage
      if (re.read_servers[0].memDataPipe.notEmpty()) begin
	 let md <- toGet(re.read_servers[0].memDataPipe).get;
	 $display("md v=%h tag=%d first=%d last=%d", md.data, md.tag, md.first, md.last);
	 let v = md.data;
	 let rval = bytesRead/4;
	 function Bit#(32) expectedVal(Integer i); return rval+fromInteger(i); endfunction
	 let expectedV = pack(genWith(expectedVal));
	 vReg <= v;
	 vExpectedReg <= expectedV;
	 validReg <= True;
	 let next_bytesRead = bytesRead + fromInteger(valueOf(DataBusWidth))/8;
	 let next_bytesToRead = bytesToRead - fromInteger(valueOf(DataBusWidth))/8;
	 let last = (bytesToRead <= fromInteger(valueOf(DataBusWidth))/8);
	 //$display("check next_bytesRead=%d next_bytesToRead=%d last=%d", next_bytesRead, next_bytesToRead, last);
	 if (last) begin
	    next_bytesRead = 0;
	    next_bytesToRead = numBytes;
	 end
	 lastReg <= last;
	 bytesRead <= next_bytesRead;
	 bytesToRead <= next_bytesToRead;
      end
      else begin
	 validReg <= False;
      end

      // second pipeline stage
      if (validReg) begin
	 let v = vReg;
	 let expectedV = vExpectedReg;
	 let misMatch = v != expectedV;
	 mismatchCounts <= mismatchCounts + (misMatch ? 1 : 0);
	 //$display("Test: check new=%x numBytes=%x bytesRead=%x misMatch=%x read=%x expect=%x", new_bytesRead, numBytes, bytesRead, misMatch, v, expectedV);
	 if (lastReg) begin
	    checkDoneFifo.enq(mismatchCounts);
	 end
      end
   endrule

   rule finish if (itersToFinish > 0);
      $display("Test: response.get itersToFinish %x", itersToFinish);
      let mc <- toGet(checkDoneFifo).get();
      let rv <- re.read_servers[0].cmdServer.response.get;
      if (itersToFinish == 1) begin
	 indication.readDone(mismatchCounts);
      end
      itersToFinish <= itersToFinish - 1;
   endrule

   interface dmaClient = vec(re.dmaClient);
   interface ReadTestRequest request;
      method Action startRead(Bit#(32) rp, Bit#(32) nb, Bit#(32) bl, Bit#(32) ic) if (itersToStart == 0 && itersToFinish == 0);
         $display("startRead pointer=%x numBytes %x burstLen %x iteration %x", rp, nb, bl, ic);
	 pointer <= rp;
	 numBytes  <= nb;
	 bytesToRead <= nb;
	 burstLenBytes  <= truncate(bl);
	 itersToFinish <= ic;
	 itersToStart <= ic;
	 mismatchCounts <= 0;
	 bytesRead <= 0;
      endmethod
   endinterface
endmodule

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

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import FIFO::*;
import FIFOF::*;
import Vector::*;
import BuildVector::*;
import GetPut::*;
import ClientServer::*;

import Pipe::*;
import MemTypes::*;
import MemreadEngine::*;
import HostInterface::*;

interface ReadTestRequest;
   method Action startRead(Bit#(32) pointer, Bit#(32) numBytes, Bit#(32) burstLen, Bit#(32) iterCnt);
endinterface

interface ReadTest;
   interface ReadTestRequest request;
   interface Vector#(1,MemReadClient#(DataBusWidth)) dmaClient;
endinterface

interface ReadTestIndication;
   method Action readDone(Bit#(32) mismatchCount);
endinterface

typedef 14 NumOutstandingRequests;
typedef TMul#(NumOutstandingRequests,TMul#(32,4)) BufferSizeBytes;
module mkReadTest#(ReadTestIndication indication) (ReadTest);

   Reg#(SGLId)   pointer <- mkReg(0);
   Reg#(Bit#(32))       numBytes <- mkReg(0);
   Reg#(Bit#(BurstLenSize)) burstLenBytes <- mkReg(0);
   Reg#(Bit#(32))  itersToFinish <- mkReg(0);
   Reg#(Bit#(32))   itersToStart <- mkReg(0);
   Reg#(Bit#(32))        bytesRead <- mkReg(0);
   Reg#(Bit#(32)) mismatchCounts <- mkReg(0);
   MemreadEngine#(DataBusWidth,NumOutstandingRequests,1)        re <- mkMemreadEngineBuff(valueOf(BufferSizeBytes));
   FIFO#(Bit#(32)) checkDoneFifo <- mkFIFO();

   rule start (itersToStart > 0);
      $display("Test: request.put");
      re.readServers[0].request.put(MemengineCmd{sglId:pointer, base:0, len:numBytes, tag:0, burstLen:burstLenBytes});
      itersToStart <= itersToStart-1;
   endrule

   Reg#(Bit#(DataBusWidth)) vReg <- mkReg(0);
   Reg#(Bit#(DataBusWidth)) vExpectedReg <- mkReg(0);
   Reg#(Bool)               validReg <- mkReg(False);
   Reg#(Bit#(32))           bytesToRead <- mkReg(0);
   Reg#(Bool)               lastReg <- mkReg(False);
   rule check;
      // first pipeline stage
      if (re.dataPipes[0].notEmpty()) begin
	 let v <- toGet(re.dataPipes[0]).get;
	 let rval = bytesRead/4;
	 function Bit#(32) expectedVal(Integer i); return rval+fromInteger(i); endfunction
	 let expectedV = pack(genWith(expectedVal));
	 vReg <= v;
	 vExpectedReg <= expectedV;
	 validReg <= True;
	 let next_bytesRead = bytesRead + fromInteger(valueOf(DataBusWidth))/8;
	 let next_bytesToRead = bytesToRead - fromInteger(valueOf(DataBusWidth))/8;
	 let last = (bytesToRead <= fromInteger(valueOf(DataBusWidth))/8);
	 //$display("check next_bytesRead=%d next_bytesToRead=%d last=%d", next_bytesRead, next_bytesToRead, last);
	 if (last) begin
	    next_bytesRead = 0;
	    next_bytesToRead = numBytes;
	 end
	 lastReg <= last;
	 bytesRead <= next_bytesRead;
	 bytesToRead <= next_bytesToRead;
      end
      else begin
	 validReg <= False;
      end

      // second pipeline stage
      if (validReg) begin
	 let v = vReg;
	 let expectedV = vExpectedReg;
	 let misMatch = v != expectedV;
	 mismatchCounts <= mismatchCounts + (misMatch ? 1 : 0);
	 //$display("Test: check new=%x numBytes=%x bytesRead=%x misMatch=%x read=%x expect=%x", new_bytesRead, numBytes, bytesRead, misMatch, v, expectedV);
	 if (lastReg) begin
	    checkDoneFifo.enq(mismatchCounts);
	 end
      end
   endrule

   rule finish if (itersToFinish > 0);
      $display("Test: response.get itersToFinish %x", itersToFinish);
      let mc <- toGet(checkDoneFifo).get();
      let rv <- re.readServers[0].response.get;
      if (itersToFinish == 1) begin
	 indication.readDone(mismatchCounts);
      end
      itersToFinish <= itersToFinish - 1;
   endrule

   interface dmaClient = vec(re.dmaClient);
   interface ReadTestRequest request;
      method Action startRead(Bit#(32) rp, Bit#(32) nb, Bit#(32) bl, Bit#(32) ic) if (itersToStart == 0 && itersToFinish == 0);
         $display("startRead pointer=%x numBytes %x burstLen %x iteration %x", rp, nb, bl, ic);
	 pointer <= rp;
	 numBytes  <= nb;
	 bytesToRead <= nb;
	 burstLenBytes  <= truncate(bl);
	 itersToFinish <= ic;
	 itersToStart <= ic;
	 mismatchCounts <= 0;
	 bytesRead <= 0;
      endmethod
   endinterface
endmodule


delete unused interfaces

delete unused interfaces

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

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import Vector::*;
import GetPut::*;
import Connectable :: *;
import Clocks :: *;
import FIFO::*;
import Portal::*;
import HostInterface::*;
import CtrlMux::*;
import PS7LIB::*;
import PPS7LIB::*;
import ConnectalClocks::*;
import BlueScopeEventPIO::*;
import ParallellaLib::*;
import PParallellaLIB::*;
import AxiMasterSlave::*;
import AxiGather::*;

module mkConnectalTop#(HostType host)(ConnectalTop#(PhysAddrWidth,64,ParallellaPins,1));

   ParallellaLib plib <- mkParallella();
   Axi3Slave#(32,32,12) parctrl <- mkAxiDmaSlave(plib.maxi);
   Axi3Master#(32,64,6) parmaster <- mkAxiDmaNaster(plib.saxi);
   mkConnection(host.ps7.m_axi_gp[1].client, parslave);
   mkConnection(parmaster, host.ps7.m_axi_hp[3].client);

   interface interrupt = getInterruptVector(portals);
   interface slave = ctrl_mux;
   interface masters = dma.masters;
   interface pins = pins;

endmodule : mkConnectalTop

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

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import Vector::*;
import GetPut::*;
import Connectable :: *;
import Clocks :: *;
import FIFO::*;
import Portal::*;
import HostInterface::*;
import CtrlMux::*;
import MemTypes::*;
import MemServer::*;
import MMU::*;
import PS7LIB::*;
import PPS7LIB::*;
import MemServerRequest::*;
import MMURequest::*;
import MemServerIndication::*;
import MMUIndication::*;
import XilinxCells::*;
import ConnectalXilinxCells::*;
import ConnectalClocks::*;
import BlueScopeEventPIO::*;
import ParallellaLib::*;
import PParallellaLIB::*;
import extraXilinxCells::*;
import AxiMasterSlave::*;
import AxiGather::*;

module mkConnectalTop#(HostType host)(ConnectalTop#(PhysAddrWidth,64,ParallellaPins,1));

   ParallellaLib plib <- mkParallella();
   Axi3Slave#(32,32,12) parctrl <- mkAxiDmaSlave(plib.maxi);
   Axi3Master#(32,64,6) parmaster <- mkAxiDmaNaster(plib.saxi);
   mkConnection(host.ps7.m_axi_gp[1].client, parslave);
   mkConnection(parmaster, host.ps7.m_axi_hp[3].client);

   interface interrupt = getInterruptVector(portals);
   interface slave = ctrl_mux;
   interface masters = dma.masters;
   interface pins = pins;

endmodule : mkConnectalTop