add defaultReset to de5pins

add defaultReset to de5pins

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

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

import AlteraExtra::*;
import ALTERA_SI570_WRAPPER::*;
import AlteraEthPhy::*;
import AlteraMacWrap::*;

(* always_ready, always_enabled *)
interface DE5Pins;
`ifdef BOARD_de5
   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 Reset deleteme_unused_reset;
`endif
endinterface

function DE5Pins mkDE5Pins(Clock defaultClock, Reset defaultReset, De5Clocks clocks, EthPhyIfc phys, De5Leds leds, De5SfpCtrl#(4) sfpctrl, De5Buttons#(4) buttons) =
   interface DE5Pins;
`ifdef BOARD_de5
      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);
         clocks.set_clk_50(b4a);
      endmethod
      method serial_tx_data = phys.serial_tx;
      method serial_rx = phys.serial_rx;
      method sfp = clocks.set_clk_644;
      interface i2c = clocks.i2c;
      interface led = leds.led_out;
      interface led_bracket = leds.led_out;
      interface sfpctrl = sfpctrl;
      interface buttons = buttons.pins;
      interface deleteme_unused_clock = defaultClock;
      interface deleteme_unused_clock2 = clocks.clock_50;
      interface deleteme_unused_reset = defaultReset;
`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;
   method Action set_clk_50(Bit#(1) clk);
   method Action set_clk_644(Bit#(1) clk);
endinterface

module mkDe5Clocks(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

   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;
   method set_clk_50 = iclock_50.inputclock;
   method set_clk_644 = iclock_644.inputclock;
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 (Vector#(nPorts, Bit#(1)) v);
   method Action mod0_presnt_n (Vector#(nPorts, Bit#(1)) v);
   method Action 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(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::*;
import AlteraEthPhy::*;
import AlteraMacWrap::*;

(* always_ready, always_enabled *)
interface DE5Pins;
`ifdef BOARD_de5
   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 Reset deleteme_unused_reset;
`endif
endinterface

function DE5Pins mkDE5Pins(Clock defaultClock, De5Clocks clocks, EthPhyIfc phys, De5Leds leds, De5SfpCtrl#(4) sfpctrl, De5Buttons#(4) buttons) =
   interface DE5Pins;
`ifdef BOARD_de5
      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);
         clocks.set_clk_50(b4a);
      endmethod
      method serial_tx_data = phys.serial_tx;
      method serial_rx = phys.serial_rx;
      method sfp = clocks.set_clk_644;
      interface i2c = clocks.i2c;
      interface led = leds.led_out;
      interface led_bracket = leds.led_out;
      interface sfpctrl = sfpctrl;
      interface buttons = buttons.pins;
      interface deleteme_unused_clock = defaultClock;
      interface deleteme_unused_clock2 = clocks.clock_50;
      //interface deleteme_unused_reset = defaultReset;
   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;
   method Action set_clk_50(Bit#(1) clk);
   method Action set_clk_644(Bit#(1) clk);
endinterface

module mkDe5Clocks(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

   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;
   method set_clk_50 = iclock_50.inputclock;
   method set_clk_644 = iclock_644.inputclock;
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 (Vector#(nPorts, Bit#(1)) v);
   method Action mod0_presnt_n (Vector#(nPorts, Bit#(1)) v);
   method Action 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(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


Paxos: clean up

Paxos: clean up

// Copyright (c) 2016 Cornell University.

// 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 AcceptorTable::*;
import ClientServer::*;
import Connectable::*;
import DbgTypes::*;
import DstMacTable::*;
import DropTable::*;
import Ethernet::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;
import MemTypes::*;
import PaxosTypes::*;
import Pipe::*;
import RegFile::*;
import RoleTable::*;
import RoundTable::*;
import SequenceTable::*;
import Vector::*;
import BuildVector::*;
import ConnectalTypes::*;

interface Ingress;
   interface MemWriteClient#(`DataBusWidth) writeClient;
   interface PipeOut#(PacketInstance) eventPktSend;
   method IngressPipelineDbgRec dbg;
   method Action datapath_id_reg_write(Bit#(64) datapath);
   method Action instance_reg_write(Bit#(16) instance_);
   method Action vround_reg_write(Bit#(InstanceSize) inst, Bit#(RoundSize) round);
   method Action round_reg_write(Bit#(16) r);
   method Action role_reg_write(Role r);
   method Action sequenceTable_add_entry(Bit#(16) msgtype, SequenceTblActionT action_);
   method Action acceptorTable_add_entry(Bit#(16) msgtype, AcceptorTblActionT action_);
   method Action dmacTable_add_entry(Bit#(48) mac, Bit#(9) port);
endinterface

module mkIngress#(Vector#(numClients, MetadataClient) mdc)(Ingress);
   let verbose = True;
   Reg#(Bit#(64)) fwdCount <- mkReg(0);
   FIFOF#(PacketInstance) currPacketFifo <- mkFIFOF;
   FIFO#(MetadataRequest) inReqFifo <- mkFIFO;
   FIFO#(MetadataResponse) outRespFifo <- mkFIFO;

   Vector#(numClients, MetadataServer) metadataServers = newVector;
   for (Integer i=0; i<valueOf(numClients); i=i+1) begin
      metadataServers[i] = (interface MetadataServer;
         interface Put request = toPut(inReqFifo);
         interface Get response = toGet(outRespFifo);
      endinterface);
   end
   mkConnection(mdc, metadataServers);

   // Request/Response Fifos
   FIFO#(MetadataRequest) dmacReqFifo <- mkFIFO;
   FIFO#(MetadataRequest) roleReqFifo <- mkFIFO;
   FIFO#(MetadataRequest) roundReqFifo <- mkFIFO;
   FIFO#(MetadataRequest) sequenceReqFifo <- mkFIFO;
   FIFO#(MetadataRequest) acceptorReqFifo <- mkFIFO;
   // FIFO#(MetadataRequest) dropRequestFifo <- mkFIFO;
   FIFO#(MetadataResponse) dmacRespFifo <- mkFIFO;
   FIFO#(MetadataResponse) roleRespFifo <- mkFIFO;
   FIFO#(MetadataResponse) roundRespFifo <- mkFIFO;
   FIFO#(MetadataResponse) sequenceRespFifo <- mkFIFO;
   FIFO#(MetadataResponse) acceptorRespFifo <- mkFIFO;
   // FIFO#(MetadataResponse) dropResponseFifo <- mkFIFO;

   // Tables
   DstMacTable dstMacTable <- mkDstMacTable(toGPClient(dmacReqFifo, dmacRespFifo));
   RoleTable roleTable <- mkRoleTable(toGPClient(roleReqFifo, roleRespFifo));
   RoundTable roundTable <- mkRoundTable(toGPClient(roundReqFifo, roundRespFifo));
   SequenceTable sequenceTable <- mkSequenceTable(toGPClient(sequenceReqFifo, sequenceRespFifo));
   AcceptorTable acceptorTable <- mkAcceptorTable(toGPClient(acceptorReqFifo, acceptorRespFifo));
   //DropTable dropTable <- mkDropTable();//roundTable.next1);

   // BasicBlocks
   BasicBlockForward bb_fwd <- mkBasicBlockForward();
   BasicBlockIncreaseInstance bb_increase_instance <- mkBasicBlockIncreaseInstance();
   BasicBlockHandle1A bb_handle_1a <- mkBasicBlockHandle1A();
   BasicBlockHandle2A bb_handle_2a <- mkBasicBlockHandle2A();
   BasicBlockDrop bb_handle_drop <- mkBasicBlockDrop();
   BasicBlockRound bb_read_round <- mkBasicBlockRound();
   BasicBlockRole bb_read_role <- mkBasicBlockRole();

   // Registers
   FIFO#(RoundRegRequest) roundRegReqFifo <- mkFIFO;
   FIFO#(RoleRegRequest) roleRegReqFifo <- mkFIFO;
   FIFO#(DatapathIdRegRequest) datapathIdRegReqFifo <- mkFIFO;
   FIFO#(InstanceRegRequest) instanceRegReqFifo <- mkFIFO;
   FIFO#(VRoundRegRequest) vroundRegReqFifo <- mkFIFO;
   FIFO#(ValueRegRequest) valueRegReqFifo <- mkFIFO;

   FIFO#(RoundRegResponse) roundRegRespFifo <- mkFIFO;
   FIFO#(RoleRegResponse) roleRegRespFifo <- mkFIFO;
   FIFO#(DatapathIdRegResponse) datapathIdRegRespFifo <- mkFIFO;
   FIFO#(InstanceRegResponse) instanceRegRespFifo <- mkFIFO;
   FIFO#(VRoundRegResponse) vroundRegRespFifo <- mkFIFO;
   FIFO#(ValueRegResponse) valueRegRespFifo <- mkFIFO;

   RegIfc#(Bit#(InstanceSize), Bit#(RoundSize)) roundReg <- mkP4Reg(vec(bb_read_round.regClient, toGPClient(roundRegReqFifo, roundRegRespFifo)));
   RegIfc#(Bit#(1), Role) roleReg <- mkP4Reg(vec(bb_read_role.regClient, toGPClient(roleRegReqFifo, roleRegRespFifo)));
   RegIfc#(Bit#(1), Bit#(64)) datapathIdReg <- mkP4Reg(vec(bb_handle_1a.regClient_datapath_id, bb_handle_2a.regClient_datapath_id, toGPClient(datapathIdRegReqFifo, datapathIdRegRespFifo)));
   RegIfc#(Bit#(1), Bit#(16)) instanceReg <- mkP4Reg(vec(bb_increase_instance.regClient, toGPClient(instanceRegReqFifo, instanceRegRespFifo)));
   RegIfc#(Bit#(InstanceSize), Bit#(RoundSize)) vroundReg <- mkP4Reg(vec(bb_handle_1a.regClient_vround, bb_handle_2a.regClient_vround, toGPClient(vroundRegReqFifo, vroundRegRespFifo)));
   RegIfc#(Bit#(InstanceSize), Bit#(ValueSize)) valueReg <- mkP4Reg(vec(bb_handle_1a.regClient_value, bb_handle_2a.regClient_value, toGPClient(valueRegReqFifo, valueRegRespFifo)));

   // Connect Table with BasicBlock
   mkConnection(dstMacTable.next_control_state_0, bb_fwd.prev_control_state);
   mkConnection(sequenceTable.next_control_state_0, bb_increase_instance.prev_control_state);
   mkConnection(acceptorTable.next_control_state_0, bb_handle_1a.prev_control_state);
   mkConnection(acceptorTable.next_control_state_1, bb_handle_2a.prev_control_state);
   mkConnection(acceptorTable.next_control_state_2, bb_handle_drop.prev_control_state);
   mkConnection(roundTable.next_control_state_0, bb_read_round.prev_control_state);
   mkConnection(roleTable.next_control_state_0, bb_read_role.prev_control_state);

   // Control Flow
   rule start_control_state;
      let v <- toGet(inReqFifo).get;
      case (v) matches
         tagged DefaultRequest {pkt: .pkt, meta: .meta} : begin
            if (isValid(meta.valid_ipv4)) begin
               MetadataRequest req = tagged DstMacLookupRequest {pkt: pkt, meta: meta};
               dmacReqFifo.enq(req);
            end
         end
      endcase
   endrule

   rule dmac_tbl_next_control_state;
      let v <- toGet(dmacRespFifo).get;
      $display("(%0d) dmac_tbl next control state", $time);
      case (v) matches
         tagged DstMacResponse {pkt: .pkt, meta: .meta}: begin
            if (isValid(meta.valid_paxos)) begin
               MetadataRequest req = tagged RoleLookupRequest {pkt: pkt, meta: meta};
               roleReqFifo.enq(req);
            end
         end
      endcase
   endrule

   rule role_tbl_next_control_state;
      let v <- toGet(roleRespFifo).get;
      case (v) matches
         tagged RoleResponse {pkt: .pkt, meta: .meta}: begin
            if (meta.switch_metadata$role matches tagged Valid .role) begin
               case (role) matches
                  ACCEPTOR: begin
                     $display("(%0d) Role: Acceptor %h", $time, pkt.id);
                     MetadataRequest req = tagged RoundTblRequest {pkt: pkt, meta: meta};
                     roundReqFifo.enq(req);
                  end
                  COORDINATOR: begin
                     $display("(%0d) Role: Coordinator %h", $time, pkt.id);
                     MetadataRequest req = tagged SequenceTblRequest {pkt: pkt, meta: meta};
                     sequenceReqFifo.enq(req);
                  end
               endcase
            end
         end
      endcase
   endrule

   rule sequence_tbl_next_control_state;
      let v <- toGet(sequenceRespFifo).get;
      $display("(%0d) sequence tbl response", $time);
      case (v) matches
         tagged SequenceTblResponse {pkt: .pkt, meta: .meta}: begin
            currPacketFifo.enq(pkt);
            $display("(%0d) Sequence: fwd %h", $time, pkt.id);
            //if (v.p4_action == 1) begin
            //   MetadataRequest req = tagged ForwardQueueRequest {};
            //end
         end
      endcase
   endrule

   rule round_tbl_next_control_state;
      let v <- toGet(roundRespFifo).get;
      $display("(%0d) round table response", $time);
      case (v) matches
         tagged RoundTblResponse {pkt: .pkt, meta: .meta}: begin
            if (meta.paxos_packet_meta$round matches tagged Valid .round) begin
               if (round <= fromMaybe(?, meta.paxos$rnd)) begin
                  $display("(%0d) Round: Acceptor %h, round=%h, rnd=%h", $time, pkt.id, round, meta.paxos$rnd);
                  MetadataRequest req = tagged AcceptorTblRequest {pkt: pkt, meta: meta};
                  acceptorReqFifo.enq(req);
               end
            end
            else
               $display("(%0d) Invalid round", $time);
         end
      endcase
   endrule

   rule acceptor_tbl_next_control_state;
      let v <- toGet(acceptorRespFifo).get;
      $display("(%0d) acceptor table response", $time);
      case (v) matches
         tagged AcceptorTblResponse {pkt: .pkt, meta: .meta}: begin
            //MetadataRequest req = tagged ForwardQueueRequest {};
            currPacketFifo.enq(pkt);
         end
      endcase
   endrule

   interface writeClient = dstMacTable.writeClient;
   interface eventPktSend = toPipeOut(currPacketFifo);
   method IngressPipelineDbgRec dbg();
      return IngressPipelineDbgRec {
         fwdCount: fwdCount
      };
   endmethod
   method Action round_reg_write(Bit#(16) round);
      RoundRegRequest req = RoundRegRequest {addr: 0, data: round, write: True};
      roundRegReqFifo.enq(req);
   endmethod
   method Action role_reg_write(Role role);
      RoleRegRequest req = RoleRegRequest {addr: 0, data: role, write: True};
      roleRegReqFifo.enq(req);
   endmethod
   method Action datapath_id_reg_write(Bit#(64) datapath);
      DatapathIdRegRequest req = DatapathIdRegRequest {addr: 0, data: datapath, write: True};
      datapathIdRegReqFifo.enq(req);
   endmethod
   method Action instance_reg_write(Bit#(16) instance_);
      InstanceRegRequest req = InstanceRegRequest {addr: 0, data: instance_, write: True};
      instanceRegReqFifo.enq(req);
   endmethod
   method Action vround_reg_write(Bit#(InstanceSize) inst, Bit#(RoundSize) round);
      VRoundRegRequest req = VRoundRegRequest {addr: inst, data: round, write: True};
      vroundRegReqFifo.enq(req);
   endmethod
   method sequenceTable_add_entry = sequenceTable.add_entry;
   method acceptorTable_add_entry = acceptorTable.add_entry;
   method dmacTable_add_entry = dstMacTable.add_entry;
endmodule

// Copyright (c) 2016 Cornell University.

// 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 AcceptorTable::*;
import ClientServer::*;
import Connectable::*;
import DbgTypes::*;
import DstMacTable::*;
import DropTable::*;
import Ethernet::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;
import MemTypes::*;
import PaxosTypes::*;
import Pipe::*;
import RegFile::*;
import RoleTable::*;
import RoundTable::*;
import SequenceTable::*;
import Vector::*;
import BuildVector::*;
import ConnectalTypes::*;

interface Ingress;
   interface MemWriteClient#(`DataBusWidth) writeClient;
   interface PipeOut#(PacketInstance) eventPktSend;
   method IngressPipelineDbgRec dbg;
   method Action datapath_id_reg_write(Bit#(64) datapath);
   method Action instance_reg_write(Bit#(16) instance_);
   method Action vround_reg_write(Bit#(InstanceSize) inst, Bit#(RoundSize) round);
   method Action round_reg_write(Bit#(16) r);
   method Action role_reg_write(Role r);
   method Action sequenceTable_add_entry(Bit#(16) msgtype, SequenceTblActionT action_);
   method Action acceptorTable_add_entry(Bit#(16) msgtype, AcceptorTblActionT action_);
   method Action dmacTable_add_entry(Bit#(48) mac, Bit#(9) port);
endinterface

module mkIngress#(Vector#(numClients, MetadataClient) mdc)(Ingress);
   let verbose = True;
   Reg#(Bit#(64)) fwdCount <- mkReg(0);
   FIFOF#(PacketInstance) currPacketFifo <- mkFIFOF;
   FIFO#(MetadataRequest) inReqFifo <- mkFIFO;
   FIFO#(MetadataResponse) outRespFifo <- mkFIFO;

   Vector#(numClients, MetadataServer) metadataServers = newVector;
   for (Integer i=0; i<valueOf(numClients); i=i+1) begin
      metadataServers[i] = (interface MetadataServer;
         interface Put request = toPut(inReqFifo);
         interface Get response = toGet(outRespFifo);
      endinterface);
   end
   mkConnection(mdc, metadataServers);

   // Request/Response Fifos
   FIFO#(MetadataRequest) dmacReqFifo <- mkFIFO;
   FIFO#(MetadataRequest) roleReqFifo <- mkFIFO;
   FIFO#(MetadataRequest) roundReqFifo <- mkFIFO;
   FIFO#(MetadataRequest) sequenceReqFifo <- mkFIFO;
   FIFO#(MetadataRequest) acceptorReqFifo <- mkFIFO;
   // FIFO#(MetadataRequest) dropRequestFifo <- mkFIFO;
   FIFO#(MetadataResponse) dmacRespFifo <- mkFIFO;
   FIFO#(MetadataResponse) roleRespFifo <- mkFIFO;
   FIFO#(MetadataResponse) roundRespFifo <- mkFIFO;
   FIFO#(MetadataResponse) sequenceRespFifo <- mkFIFO;
   FIFO#(MetadataResponse) acceptorRespFifo <- mkFIFO;
   // FIFO#(MetadataResponse) dropResponseFifo <- mkFIFO;

   // MetadataClients
   function MetadataClient toMetadataClient(FIFO#(MetadataRequest) reqFifo,
                                            FIFO#(MetadataResponse) respFifo);
      MetadataClient ret_ifc;
      ret_ifc = (interface MetadataClient;
         interface Get request = toGet(reqFifo);
         interface Put response = toPut(respFifo);
      endinterface);
      return ret_ifc;
   endfunction

   // Tables
   DstMacTable dstMacTable <- mkDstMacTable(toMetadataClient(dmacReqFifo, dmacRespFifo));
   RoleTable roleTable <- mkRoleTable(toMetadataClient(roleReqFifo, roleRespFifo));
   RoundTable roundTable <- mkRoundTable(toMetadataClient(roundReqFifo, roundRespFifo));
   SequenceTable sequenceTable <- mkSequenceTable(toMetadataClient(sequenceReqFifo, sequenceRespFifo));
   AcceptorTable acceptorTable <- mkAcceptorTable(toMetadataClient(acceptorReqFifo, acceptorRespFifo));
   //DropTable dropTable <- mkDropTable();//roundTable.next1);

   // BasicBlocks
   BasicBlockForward bb_fwd <- mkBasicBlockForward();
   BasicBlockIncreaseInstance bb_increase_instance <- mkBasicBlockIncreaseInstance();
   BasicBlockHandle1A bb_handle_1a <- mkBasicBlockHandle1A();
   BasicBlockHandle2A bb_handle_2a <- mkBasicBlockHandle2A();
   BasicBlockDrop bb_handle_drop <- mkBasicBlockDrop();
   BasicBlockRound bb_read_round <- mkBasicBlockRound();
   BasicBlockRole bb_read_role <- mkBasicBlockRole();

   // Registers
   FIFO#(RoundRegRequest) roundRegReqFifo <- mkFIFO;
   FIFO#(RoleRegRequest) roleRegReqFifo <- mkFIFO;
   FIFO#(DatapathIdRegRequest) datapathIdRegReqFifo <- mkFIFO;
   FIFO#(InstanceRegRequest) instanceRegReqFifo <- mkFIFO;
   FIFO#(VRoundRegRequest) vroundRegReqFifo <- mkFIFO;
   FIFO#(ValueRegRequest) valueRegReqFifo <- mkFIFO;

   FIFO#(RoundRegResponse) roundRegRespFifo <- mkFIFO;
   FIFO#(RoleRegResponse) roleRegRespFifo <- mkFIFO;
   FIFO#(DatapathIdRegResponse) datapathIdRegRespFifo <- mkFIFO;
   FIFO#(InstanceRegResponse) instanceRegRespFifo <- mkFIFO;
   FIFO#(VRoundRegResponse) vroundRegRespFifo <- mkFIFO;
   FIFO#(ValueRegResponse) valueRegRespFifo <- mkFIFO;

   function RoundRegClient toRoundRegClient(FIFO#(RoundRegRequest) reqFifo,
                                            FIFO#(RoundRegResponse) respFifo);
      RoundRegClient ret_ifc;
      ret_ifc = (interface RoundRegClient;
         interface Get request = toGet(reqFifo);
         interface Put response = toPut(respFifo);
      endinterface);
      return ret_ifc;
   endfunction

   function RoleRegClient toRoleRegClient(FIFO#(RoleRegRequest) reqFifo,
                                          FIFO#(RoleRegResponse) respFifo);
      RoleRegClient ret_ifc;
      ret_ifc = (interface RoleRegClient;
         interface Get request = toGet(reqFifo);
         interface Put response = toPut(respFifo);
      endinterface);
      return ret_ifc;
   endfunction

   Client#(RoundRegRequest, RoundRegResponse) round2 = toGPClient(roundRegReqFifo, roundRegRespFifo);

   RegIfc#(Bit#(InstanceSize), Bit#(RoundSize)) roundReg <- mkP4Reg(vec(bb_read_round.regClient, toRoundRegClient(roundRegReqFifo, roundRegRespFifo)));
   RegIfc#(Bit#(1), Role) roleReg <- mkP4Reg(vec(bb_read_role.regClient, toRoleRegClient(roleRegReqFifo, roleRegRespFifo)));
   RegIfc#(Bit#(1), Bit#(64)) datapathIdReg <- mkP4Reg(vec(bb_handle_1a.regClient_datapath_id, bb_handle_2a.regClient_datapath_id));
   RegIfc#(Bit#(1), Bit#(16)) instanceReg <- mkP4Reg(vec(bb_increase_instance.regClient));
   RegIfc#(Bit#(InstanceSize), Bit#(RoundSize)) vroundReg <- mkP4Reg(vec(bb_handle_1a.regClient_vround, bb_handle_2a.regClient_vround));
   RegIfc#(Bit#(InstanceSize), Bit#(ValueSize)) valueReg <- mkP4Reg(vec(bb_handle_1a.regClient_value, bb_handle_2a.regClient_value));

   // Connect Table with BasicBlock
   mkConnection(dstMacTable.next_control_state_0, bb_fwd.prev_control_state);
   mkConnection(sequenceTable.next_control_state_0, bb_increase_instance.prev_control_state);
   mkConnection(acceptorTable.next_control_state_0, bb_handle_1a.prev_control_state);
   mkConnection(acceptorTable.next_control_state_1, bb_handle_2a.prev_control_state);
   mkConnection(acceptorTable.next_control_state_2, bb_handle_drop.prev_control_state);
   mkConnection(roundTable.next_control_state_0, bb_read_round.prev_control_state);
   mkConnection(roleTable.next_control_state_0, bb_read_role.prev_control_state);

   // Control Flow
   rule start_control_state;
      let v <- toGet(inReqFifo).get;
      case (v) matches
         tagged DefaultRequest {pkt: .pkt, meta: .meta} : begin
            if (isValid(meta.valid_ipv4)) begin
               MetadataRequest req = tagged DstMacLookupRequest {pkt: pkt, meta: meta};
               dmacReqFifo.enq(req);
            end
         end
      endcase
   endrule

   rule dmac_tbl_next_control_state;
      let v <- toGet(dmacRespFifo).get;
      $display("(%0d) dmac_tbl next control state", $time);
      case (v) matches
         tagged DstMacResponse {pkt: .pkt, meta: .meta}: begin
            if (isValid(meta.valid_paxos)) begin
               MetadataRequest req = tagged RoleLookupRequest {pkt: pkt, meta: meta};
               roleReqFifo.enq(req);
            end
         end
      endcase
   endrule

   rule role_tbl_next_control_state;
      let v <- toGet(roleRespFifo).get;
      case (v) matches
         tagged RoleResponse {pkt: .pkt, meta: .meta}: begin
            if (meta.switch_metadata$role matches tagged Valid .role) begin
               case (role) matches
                  ACCEPTOR: begin
                     $display("(%0d) Role: Acceptor %h", $time, pkt.id);
                     MetadataRequest req = tagged RoundTblRequest {pkt: pkt, meta: meta};
                     roundReqFifo.enq(req);
                  end
                  COORDINATOR: begin
                     $display("(%0d) Role: Coordinator %h", $time, pkt.id);
                     MetadataRequest req = tagged SequenceTblRequest {pkt: pkt, meta: meta};
                     sequenceReqFifo.enq(req);
                  end
               endcase
            end
         end
      endcase
   endrule

   rule sequence_tbl_next_control_state;
      let v <- toGet(sequenceRespFifo).get;
      $display("(%0d) sequence tbl response", $time);
      case (v) matches
         tagged SequenceTblResponse {pkt: .pkt, meta: .meta}: begin
            currPacketFifo.enq(pkt);
            $display("(%0d) Sequence: fwd %h", $time, pkt.id);
            //if (v.p4_action == 1) begin
            //   MetadataRequest req = tagged ForwardQueueRequest {};
            //end
         end
      endcase
   endrule

   rule round_tbl_next_control_state;
      let v <- toGet(roundRespFifo).get;
      $display("(%0d) round table response", $time);
      case (v) matches
         tagged RoundTblResponse {pkt: .pkt, meta: .meta}: begin
            if (meta.paxos_packet_meta$round matches tagged Valid .round) begin
               if (round <= fromMaybe(?, meta.paxos$rnd)) begin
                  $display("(%0d) Round: Acceptor %h, round=%h, rnd=%h", $time, pkt.id, round, meta.paxos$rnd);
                  MetadataRequest req = tagged AcceptorTblRequest {pkt: pkt, meta: meta};
                  acceptorReqFifo.enq(req);
               end
            end
            else
               $display("(%0d) Invalid round", $time);
         end
      endcase
   endrule

   rule acceptor_tbl_next_control_state;
      let v <- toGet(acceptorRespFifo).get;
      $display("(%0d) acceptor table response", $time);
      case (v) matches
         tagged AcceptorTblResponse {pkt: .pkt, meta: .meta}: begin
            //MetadataRequest req = tagged ForwardQueueRequest {};
            currPacketFifo.enq(pkt);
         end
      endcase
   endrule

   interface writeClient = dstMacTable.writeClient;
   interface eventPktSend = toPipeOut(currPacketFifo);
   method IngressPipelineDbgRec dbg();
      return IngressPipelineDbgRec {
         fwdCount: fwdCount
      };
   endmethod
   method Action round_reg_write(Bit#(16) round);
      RoundRegRequest req = RoundRegRequest {addr: 0, data: round, write: True};
      roundRegReqFifo.enq(req);
   endmethod
   method Action role_reg_write(Role role);
      RoleRegRequest req = RoleRegRequest {addr: 0, data: role, write: True};
      roleRegReqFifo.enq(req);
   endmethod
   method Action datapath_id_reg_write(Bit#(64) datapath);
      DatapathIdRegRequest req = DatapathIdRegRequest {addr: 0, data: datapath, write: True};
      datapathIdRegReqFifo.enq(req);
   endmethod
   method Action instance_reg_write(Bit#(16) instance_);
      InstanceRegRequest req = InstanceRegRequest {addr: 0, data: instance_, write: True};
      instanceRegReqFifo.enq(req);
   endmethod
   method Action vround_reg_write(Bit#(InstanceSize) inst, Bit#(RoundSize) round);
      VRoundRegRequest req = VRoundRegRequest {addr: inst, data: round, write: True};
      vroundRegReqFifo.enq(req);
   endmethod
   method sequenceTable_add_entry = sequenceTable.add_entry;
   method acceptorTable_add_entry = acceptorTable.add_entry;
   method dmacTable_add_entry = dstMacTable.add_entry;
endmodule


enable pipelined reads/write in mkSlaveMux and mkMemSlaveMux

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

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

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

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

import Vector::*;
import GetPut::*;
import FIFOF::*;
import SpecialFIFOs::*;
import FIFO::*;

import Portal::*;
import Directory::*;
import MemTypes::*;
import RegFileA::*;

module mkInterruptMux#(Vector#(numPortals,ReadOnly#(Bool)) inputs) (ReadOnly#(Bool))
   provisos(Add#(nz, TLog#(numPortals), 4),
	    Add#(1, a__, numPortals));

   function Bool my_read(ReadOnly#(Bool) x);
      return x._read;
   endfunction

   function Bool my_or(Bool a, Bool b);
      return a || b;
   endfunction

   method Bool _read;
      return fold(my_or,map(my_read,inputs));
   endmethod

endmodule

module mkSlaveMux#(Directory#(aw,aw,dataWidth) dir,
		   Vector#(numPortals,MemPortal#(aw,dataWidth)) portals) (MemSlave#(addrWidth,dataWidth))
   provisos(Add#(1,numPortals,numInputs),
	    Add#(a__,TLog#(numInputs),4));

   Vector#(numInputs, MemSlave#(aw,dataWidth)) ifcs = cons(dir.portalIfc.slave,map(getSlave, portals));
   let port_sel_low = valueOf(aw);
   let port_sel_high = valueOf(TAdd#(3,aw));
   function Bit#(4) psel(Bit#(addrWidth) a);
      return a[port_sel_high:port_sel_low];
   endfunction
   function Bit#(aw) asel(Bit#(addrWidth) a);
      return a[(port_sel_low-1):0];
   endfunction

   FIFO#(MemRequest#(aw)) req_ars <- mkSizedFIFO(1);
   FIFO#(void) req_ar_fifo <- mkSizedFIFO(1);
   FIFO#(Bit#(TLog#(numInputs))) rs <- mkFIFO();

   FIFO#(MemRequest#(aw)) req_aws <- mkSizedFIFO(1);
   FIFO#(void) req_aw_fifo <- mkSizedFIFO(1);
   FIFO#(Bit#(TLog#(numInputs))) ws <- mkFIFO();

   rule req_aw;
      let req <- toGet(req_aws).get;
      ifcs[ws.first].write_server.writeReq.put(req);
   endrule

   rule req_ar;
      let req <- toGet(req_ars).get;
      ifcs[rs.first].read_server.readReq.put(req);
   endrule

   interface MemWriteServer write_server;
      interface Put writeReq;
	 method Action put(MemRequest#(addrWidth) req);
	    req_aws.enq(MemRequest{addr:asel(req.addr), burstLen:req.burstLen, tag:req.tag});
	    if (req.burstLen > 1) $display("**** \n\n mkSlaveMux.writeReq len=%d \n\n ****", req.burstLen);
	    req_aw_fifo.enq(?);
	    ws.enq(truncate(psel(req.addr)));
	    //$display("mkSlaveMux.writeReq addr=%h aw=%d psel=%h", req.addr, valueOf(aw), psel(req.addr));
	 endmethod
      endinterface
      interface Put writeData;
	 method Action put(ObjectData#(dataWidth) wdata);
	    ifcs[ws.first].write_server.writeData.put(wdata);
	 endmethod
      endinterface
      interface Get writeDone;
	 method ActionValue#(Bit#(6)) get();
	    let rv <- ifcs[ws.first].write_server.writeDone.get();
	    req_aw_fifo.deq;
	    ws.deq();
	    return rv;
	 endmethod
      endinterface
   endinterface
   interface MemReadServer read_server;
      interface Put readReq;
	 method Action put(MemRequest#(addrWidth) req);
	    req_ars.enq(MemRequest{addr:asel(req.addr), burstLen:req.burstLen, tag:req.tag});
	    req_ar_fifo.enq(?);
	    rs.enq(truncate(psel(req.addr)));
	    if (req.burstLen > 1) $display("**** \n\n mkSlaveMux.readReq len=%d \n\n ****", req.burstLen);
	    //$display("mkSlaveMux.readReq addr=%h aw=%d psel=%h", req.addr, valueOf(aw), psel(req.addr));
	 endmethod
      endinterface
      interface Get readData;
	 method ActionValue#(ObjectData#(dataWidth)) get();
	    let rv <- ifcs[rs.first].read_server.readData.get();
	    req_ar_fifo.deq;
	    rs.deq();
	    //$display("mkSlaveMux.readData rs=%d data=%h", rs.first, rv.data);
	    return rv;
	 endmethod
      endinterface
   endinterface

endmodule

module mkMemSlaveMux#(Vector#(numSlaves,MemSlave#(aw,dataWidth)) slaves) (MemSlave#(addrWidth,dataWidth))
   provisos(Add#(selWidth,aw,addrWidth),
	    Add#(a__, TLog#(numSlaves), selWidth)
      );

   Vector#(numSlaves, MemSlave#(aw,dataWidth)) ifcs = take(slaves);
   let port_sel_low = valueOf(aw);
   let port_sel_high = valueOf(TSub#(addrWidth,1));
   function Bit#(selWidth) psel(Bit#(addrWidth) a);
      return a[port_sel_high:port_sel_low];
   endfunction
   function Bit#(aw) asel(Bit#(addrWidth) a);
      return a[(port_sel_low-1):0];
   endfunction

   FIFO#(MemRequest#(aw)) req_ars <- mkSizedFIFO(1);
   FIFO#(void) req_ar_fifo <- mkSizedFIFO(1);
   FIFO#(Bit#(TLog#(numSlaves))) rs <- mkFIFO();

   FIFO#(MemRequest#(aw)) req_aws <- mkSizedFIFO(1);
   FIFO#(void) req_aw_fifo <- mkSizedFIFO(1);
   FIFO#(Bit#(TLog#(numSlaves))) ws <- mkFIFO();

   rule req_aw;
      let req <- toGet(req_aws).get;
      ifcs[ws.first].write_server.writeReq.put(req);
   endrule

   rule req_ar;
      let req <- toGet(req_ars).get;
      ifcs[rs.first].read_server.readReq.put(req);
   endrule

   interface MemWriteServer write_server;
      interface Put writeReq;
	 method Action put(MemRequest#(addrWidth) req);
	    req_aws.enq(MemRequest{addr:asel(req.addr), burstLen:req.burstLen, tag:req.tag});
	    req_aw_fifo.enq(?);
	    if (req.burstLen > 1) $display("**** \n\n mkMemSlaveMux.writeReq len=%d \n\n ****", req.burstLen);
	    //$display("mkMemSlaveMux.writeReq addr=%h selWidth=%d aw=%d psel=%h", req.addr, valueOf(selWidth), valueOf(aw), psel(req.addr));
	    ws.enq(truncate(psel(req.addr)));
	 endmethod
      endinterface
      interface Put writeData;
	 method Action put(ObjectData#(dataWidth) wdata);
	    //$display("mkMemSlaveMux.writeData aw=%d ws=%d data=%h", valueOf(aw), ws.first, wdata.data);
	    ifcs[ws.first].write_server.writeData.put(wdata);
	 endmethod
      endinterface
      interface Get writeDone;
	 method ActionValue#(Bit#(6)) get();
	    let rv <- ifcs[ws.first].write_server.writeDone.get();
	    req_aw_fifo.deq;
	    ws.deq();
	    return rv;
	 endmethod
      endinterface
   endinterface
   interface MemReadServer read_server;
      interface Put readReq;
	 method Action put(MemRequest#(addrWidth) req);
	    req_ars.enq(MemRequest{addr:asel(req.addr), burstLen:req.burstLen, tag:req.tag});
	    req_ar_fifo.enq(?);
	    //$display("mkMemSlaveMux.readReq addr=%h aw=%d psel=%h", req.addr, valueOf(aw), psel(req.addr));
	    if (req.burstLen > 1) $display("**** \n\n mkMemSlaveMux.readReq len=%d \n\n ****", req.burstLen);
	    rs.enq(truncate(psel(req.addr)));
	 endmethod
      endinterface
      interface Get readData;
	 method ActionValue#(ObjectData#(dataWidth)) get();
	    let rv <- ifcs[rs.first].read_server.readData.get();
	    //$display("mkMemSlaveMux.readData aw=%d rs=%d data=%h", valueOf(aw), rs.first, rv.data);
	    //if (rv.last) begin
	       req_ar_fifo.deq;
	       rs.deq();
	    //end
	    return rv;
	 endmethod
      endinterface
   endinterface

endmodule

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

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

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

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

import Vector::*;
import GetPut::*;
import FIFOF::*;
import SpecialFIFOs::*;
import FIFO::*;

import Portal::*;
import Directory::*;
import MemTypes::*;
import RegFileA::*;

module mkInterruptMux#(Vector#(numPortals,ReadOnly#(Bool)) inputs) (ReadOnly#(Bool))
   provisos(Add#(nz, TLog#(numPortals), 4),
	    Add#(1, a__, numPortals));

   function Bool my_read(ReadOnly#(Bool) x);
      return x._read;
   endfunction

   function Bool my_or(Bool a, Bool b);
      return a || b;
   endfunction

   method Bool _read;
      return fold(my_or,map(my_read,inputs));
   endmethod

endmodule

module mkSlaveMux#(Directory#(aw,aw,dataWidth) dir,
		   Vector#(numPortals,MemPortal#(aw,dataWidth)) portals) (MemSlave#(addrWidth,dataWidth))
   provisos(Add#(1,numPortals,numInputs),
	    Add#(a__,TLog#(numInputs),4));

   Vector#(numInputs, MemSlave#(aw,dataWidth)) ifcs = cons(dir.portalIfc.slave,map(getSlave, portals));
   let port_sel_low = valueOf(aw);
   let port_sel_high = valueOf(TAdd#(3,aw));
   function Bit#(4) psel(Bit#(addrWidth) a);
      return a[port_sel_high:port_sel_low];
   endfunction
   function Bit#(aw) asel(Bit#(addrWidth) a);
      return a[(port_sel_low-1):0];
   endfunction

   FIFO#(MemRequest#(aw)) req_ars <- mkSizedFIFO(1);
   FIFO#(void) req_ar_fifo <- mkSizedFIFO(1);
   Reg#(Bit#(TLog#(numInputs))) rs <- mkReg(0);

   FIFO#(MemRequest#(aw)) req_aws <- mkSizedFIFO(1);
   FIFO#(void) req_aw_fifo <- mkSizedFIFO(1);
   Reg#(Bit#(TLog#(numInputs))) ws <- mkReg(0);

   rule req_aw;
      let req <- toGet(req_aws).get;
      ifcs[ws].write_server.writeReq.put(req);
   endrule

   rule req_ar;
      let req <- toGet(req_ars).get;
      ifcs[rs].read_server.readReq.put(req);
   endrule

   interface MemWriteServer write_server;
      interface Put writeReq;
	 method Action put(MemRequest#(addrWidth) req);
	    req_aws.enq(MemRequest{addr:asel(req.addr), burstLen:req.burstLen, tag:req.tag});
	    req_aw_fifo.enq(?);
	    ws <= truncate(psel(req.addr));
	 endmethod
      endinterface
      interface Put writeData;
	 method Action put(ObjectData#(dataWidth) wdata);
	    ifcs[ws].write_server.writeData.put(wdata);
	 endmethod
      endinterface
      interface Get writeDone;
	 method ActionValue#(Bit#(6)) get();
	    let rv <- ifcs[ws].write_server.writeDone.get();
	    req_aw_fifo.deq;
	    return rv;
	 endmethod
      endinterface
   endinterface
   interface MemReadServer read_server;
      interface Put readReq;
	 method Action put(MemRequest#(addrWidth) req);
	    req_ars.enq(MemRequest{addr:asel(req.addr), burstLen:req.burstLen, tag:req.tag});
	    req_ar_fifo.enq(?);
	    rs <= truncate(psel(req.addr));
	 endmethod
      endinterface
      interface Get readData;
	 method ActionValue#(ObjectData#(dataWidth)) get();
	    let rv <- ifcs[rs].read_server.readData.get();
	    req_ar_fifo.deq;
	    return rv;
	 endmethod
      endinterface
   endinterface

endmodule

module mkMemSlaveMux#(Vector#(numSlaves,MemSlave#(aw,dataWidth)) slaves) (MemSlave#(addrWidth,dataWidth))
   provisos(Add#(selWidth,aw,addrWidth),
	    Add#(a__, TLog#(numSlaves), selWidth)
      );

   Vector#(numSlaves, MemSlave#(aw,dataWidth)) ifcs = take(slaves);
   let port_sel_low = valueOf(aw);
   let port_sel_high = valueOf(TSub#(addrWidth,1));
   function Bit#(selWidth) psel(Bit#(addrWidth) a);
      return a[port_sel_high:port_sel_low];
   endfunction
   function Bit#(aw) asel(Bit#(addrWidth) a);
      return a[(port_sel_low-1):0];
   endfunction

   FIFO#(MemRequest#(aw)) req_ars <- mkSizedFIFO(1);
   FIFO#(void) req_ar_fifo <- mkSizedFIFO(1);
   Reg#(Bit#(TLog#(numSlaves))) rs <- mkReg(0);

   FIFO#(MemRequest#(aw)) req_aws <- mkSizedFIFO(1);
   FIFO#(void) req_aw_fifo <- mkSizedFIFO(1);
   Reg#(Bit#(TLog#(numSlaves))) ws <- mkReg(0);

   rule req_aw;
      let req <- toGet(req_aws).get;
      ifcs[ws].write_server.writeReq.put(req);
   endrule

   rule req_ar;
      let req <- toGet(req_ars).get;
      ifcs[rs].read_server.readReq.put(req);
   endrule

   interface MemWriteServer write_server;
      interface Put writeReq;
	 method Action put(MemRequest#(addrWidth) req);
	    req_aws.enq(MemRequest{addr:asel(req.addr), burstLen:req.burstLen, tag:req.tag});
	    req_aw_fifo.enq(?);
	    $display("mkMemSlaveMux.writeReq addr=%h", req.addr);
	    ws <= truncate(psel(req.addr));
	 endmethod
      endinterface
      interface Put writeData;
	 method Action put(ObjectData#(dataWidth) wdata);
	    $display("mkMemSlaveMux.writeData data=%h", wdata.data);

	    ifcs[ws].write_server.writeData.put(wdata);
	 endmethod
      endinterface
      interface Get writeDone;
	 method ActionValue#(Bit#(6)) get();
	    let rv <- ifcs[ws].write_server.writeDone.get();
	    req_aw_fifo.deq;
	    return rv;
	 endmethod
      endinterface
   endinterface
   interface MemReadServer read_server;
      interface Put readReq;
	 method Action put(MemRequest#(addrWidth) req);
	    req_ars.enq(MemRequest{addr:asel(req.addr), burstLen:req.burstLen, tag:req.tag});
	    req_ar_fifo.enq(?);
	    rs <= truncate(psel(req.addr));
	 endmethod
      endinterface
      interface Get readData;
	 method ActionValue#(ObjectData#(dataWidth)) get();
	    let rv <- ifcs[rs].read_server.readData.get();
	    req_ar_fifo.deq;
	    return rv;
	 endmethod
      endinterface
   endinterface

endmodule


add fetch and searchResult

add fetch and searchResult

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

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

/* This module solves the maximum common subsequence problem.
 * It finds the longest subsequence of characters present in both input strings
 * the subsequence does not have to be contiguous and the characters can have different locations
 * and offsets in the two strings, just so long as they occur in the same order
 *
 *  To initialize, load string A with request setupA, and wait for indication setup complete
 * Then load string B with request setupB, and wait for indication setup complete
 * To start the unit, signal start, and wait for searchResult, which will tell you the length
 * To retreive the result, use fetch and wait for fetchComplete
 */

/* First pass implements Hirschberg Algorithm A and the fetch call returns the L matrix
 */
interface MaxcommonsubseqRequest;
   method Action setupA(Bit#(32) strPointer, Bit#(32) strLen);
   method Action setupB(Bit#(32) strPointer, Bit#(32) strLen);
   method Action fetch(Bit#(32) strPointer, Bit#(32) strLen);
   method Action start();
endinterface

interface MaxcommonsubseqIndication;
   method Action searchResult(Int#(32) v);
   method Action setupAComplete();
   method Action setupBComplete();
   method Action fetchComplete();
endinterface

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

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

module mkMaxcommonsubseqRequest#(MaxcommonsubseqIndication indication,
			DmaReadServer#(busWidth)   setupA_read_server,
			DmaReadServer#(busWidth)   setupB_read_server,
			DmaWriteServer#(busWidth)   fetch_write_server )(MaxcommonsubseqRequest)

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

  Reg#(Bit#(32)) aLenReg <- mkReg(0);
  Reg#(Bit#(32)) bLenReg <- mkReg(0);
  Reg#(Bit#(32)) rLenReg <- mkReg(0);
  Reg#(Bit#(32)) ii <- mkReg(0);
   Reg#(Char) aData <- mkReg(0);
   Reg#(Char) bData <- mkReg(0);
   BRAM2Port#(StringIdx, Char) strA  <- mkBRAM2Server(defaultValue);
   BRAM2Port#(StringIdx, Char) strB <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) matL <- mkBRAM2Server(defaultValue);

   BRAMReadClient#(StringIdx,busWidth) n2a <- mkBRAMReadClient(strA.portB);
   mkConnection(n2a.dmaClient, setupA_read_server);
   BRAMReadClient#(StringIdx,busWidth) n2b <- mkBRAMReadClient(strB.portB);
   mkConnection(n2b.dmaClient, setupB_read_server);
   BRAMWriteClient#(LIdx, 16) l2n <- mkBRAMWriteClient(matL.portB);

   FIFOF#(void) aReady <- mkFIFOF;
   FIFOF#(void) bReady <- mkFIFOF;
   FIFOF#(void) mReady <- mkFIFOF;
   Stmt splice =
   seq while(True)
   seq
      action
	 let ra <- aReady.deq();
	 $display("Splice A Ready");
      endaction
      action
	 let rb <- bReady.deq();
	 $display("Splice B Ready");
      endaction
      if (aLenReg > bLenReg)
	 rLenReg <= aLenReg;
      else
	 rLenReg <= bLenReg;
      for (ii <= 0; ii < rLenReg; ii <= ii + 1)
	 seq
	    $display("Splice ii %d ", ii);
	    strA.portA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: truncate(ii), datain: 0});
	    strB.portA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: truncate(ii), datain: 0});
	    action
	       let left <- strA.portA.response.get();
	       let right <- strB.portA.response.get();
	       aData <= left;
	       bData <= right;
	    endaction
	    $display("aData %d bData %d", aData, bData);
	    matL.portA.request.put(BRAMRequest{write: True, responseOnWrite: False, address: truncate(ii), datain: {aData, bData}});
	 endseq
      indication.searchResult(unpack(rLenReg));
   endseq
   endseq;

   // create BRAM Write client for matL

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

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

   rule finish_fetch;
      $display("finish fetch");
      let x <- l2n.finish;
      indication.fetchComplete();
   endrule

   mkAutoFSM(splice);

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

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

   method Action fetch(Bit#(32) strPointer, Bit#(32) strLen);
      rLenReg <= strLen;
      l2n.start(strPointer, 0, pack(truncate(strLen)), 0);
   endmethod

   method Action start();
   endmethod

endmodule

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

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

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

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

import FIFO::*;
import FIFOF::*;
import SpecialFIFOs::*;
import GetPut::*;
import StmtFSM::*;
//import Vector::*;
import BRAM::*;
//import Gearbox::*;
import Connectable::*;

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

/* This module solves the maximum common subsequence problem.
 * It finds the longest subsequence of characters present in both input strings
 * the subsequence does not have to be contiguous and the characters can have different locations
 * and offsets in the two strings, just so long as they occur in the same order
 *
 *  To initialize, load string A with request setupA, and wait for indication setup complete
 * Then load string B with request setupB, and wait for indication setup complete
 * To start the unit, signal start, and wait for searchResult, which will tell you the length
 * To retreive the result, use fetch and wait for fetchComplete
 */

/* First pass implements Hirschberg Algorithm A and the fetch call returns the L matrix
 */
interface MaxcommonsubseqRequest;
   method Action setupA(Bit#(32) strPointer, Bit#(32) strLen);
   method Action setupB(Bit#(32) strPointer, Bit#(32) strLen);
   method Action fetch(Bit#(32) strPointer, Bit#(32) strLen);
   method Action start();
endinterface

interface MaxcommonsubseqIndication;
   method Action searchResult(Int#(32) v);
   method Action setupAComplete();
   method Action setupBComplete();
   method Action fetchComplete();
endinterface

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

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

module mkMaxcommonsubseqRequest#(MaxcommonsubseqIndication indication,
			DmaReadServer#(busWidth)   setupA_read_server,
			DmaReadServer#(busWidth)   setupB_read_server,
			DmaWriteServer#(busWidth)   fetch_write_server )(MaxcommonsubseqRequest)

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

  Reg#(Bit#(32)) aLenReg <- mkReg(0);
  Reg#(Bit#(32)) bLenReg <- mkReg(0);
  Reg#(Bit#(32)) rLenReg <- mkReg(0);
  Reg#(Bit#(32)) ii <- mkReg(0);

   BRAM2Port#(StringIdx, Char) strA  <- mkBRAM2Server(defaultValue);
   BRAM2Port#(StringIdx, Char) strB <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) matL <- mkBRAM2Server(defaultValue);

   BRAMReadClient#(StringIdx,busWidth) n2a <- mkBRAMReadClient(strA.portB);
   mkConnection(n2a.dmaClient, setupA_read_server);
   BRAMReadClient#(StringIdx,busWidth) n2b <- mkBRAMReadClient(strB.portB);
   mkConnection(n2b.dmaClient, setupB_read_server);
   BRAMWriteClient#(LIdx, 16) l2n <- mkBRAMWriteClient(matL.portB);

   FIFOF#(void) aReady <- mkFIFOF;
   FIFOF#(void) bReady <- mkFIFOF;
   FIFOF#(void) mReady <- mkFIFOF;
   Stmt splice =
   seq while(True)
   seq
      action
	 let ra <- aReady.deq();
	 $display("Splice A Ready");
      endaction
      action
	 let rb <- bReady.deq();
	 $display("Splice B Ready");
      endaction
      if (aLenReg > bLenReg)
	 rLenReg <= aLenReg;
      else
	 rLenReg <= bLenReg;
      for (ii <= 0; ii < rLenReg; ii <= ii + 1)
	 seq
	    $display("Splice ii %d ", ii);
	    strA.portA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: truncate(ii), datain: 0});
	    strB.portA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: truncate(ii), datain: 0});
	    action
	       let left <- strA.portA.response.get();
	       let right <- strA.portB.response.get();
	    matL.portA.request.put(BRAMRequest{write: True, responseOnWrite: False, address: truncate(ii), datain: {left, right}});
	    endaction
	 endseq
      indication.searchResult(0);
   endseq
   endseq;

   // create BRAM Write client for matL

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

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

   rule finish_fetch;
      $display("finish fetch");
      let x <- l2n.finish;
      indication.fetchComplete();
   endrule

   mkAutoFSM(splice);

   method Action setupA(Bit#(32) strPointer, Bit#(32) strLen);
      aLenReg <= strLen;
      n2a.start(strPointer, 0, pack(truncate(strLen)), 0);
   endmethod

   method Action setupB(Bit#(32) strPointer, Bit#(32) strLen);
      bLenReg <= strLen;
      n2b.start(strPointer, 0, pack(truncate(strLen)), 0);
   endmethod

   method Action fetch(Bit#(32) strPointer, Bit#(32) strLen);
      rLenReg <= strLen;
      l2n.start(strPointer, 0, pack(truncate(strLen)), 0);
   endmethod

   method Action start();
   endmethod

endmodule


change interface type to Bits#(64)

change interface type to Bits#(64)

// 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 XilinxCells::*;
import XbsvXilinxCells::*;
import Gearbox::*;
import Pipe::*;
import FIFO::*;
import BRAMFIFO::*;
import Vector::*;
import Clocks::*;
import DefaultValue::*;

import extraXilinxCells::*;

(* always_enabled *)
interface FMComms1DACPins;
   method Bit#(14) io_dac_data_p();
   method Bit#(14) io_dac_data_n();
   method Action io_dac_dco_p(Bit#(1) v);
   method Action io_dac_dco_n(Bit#(1) v);
endinterface

typedef struct {
   Bit#(16) data_i;
   Bit#(16) data_q;
   } OIQ deriving (Bits);

interface FMComms1DAC;
   interface FMComms1DACPins pins;
   interface PipeIn#(Bit#(64)) dac;
endinterface

/* This module drives an Analog Devices FMComms1
 * evaluation board Digital to Analog Converter, it accepts
 * the data as a PipeIn type on the default clock.
 * The FMComms1 supplies the DAC clock as a differential pair
 *
 * Output is double data rate, with clock supplied by the FMComms1
 * Output data is 14 bits twos-complement or offset binary
 *
 * Differential outputs are converted from single ended by using Xilinx OBUFDS
 * cells. The clock is converted to single ended by an IBUFGDS cell
 *
 * DDR data is convered from SDR using ODDR cells
 * At this point, the data is a 14 bit in-phase data signal,
 * plus a 14 bit quadrature signal, interleaved
 *
 * The SDR data is a 32-bit OIQ datatype
 *
 * The 32-bit data is converted from 64-bits by a Gearbox
 *
 * Clock conversion happens 64-bits wide using a SyncBRAMFIFO, which
 * presents a PipeIn channel to the rest of the logic.
 */

module mkFMComms1DAC(FMComms1DAC);

   Clock def_clock <- exposeCurrentClock;
   Reset def_reset <- exposeCurrentReset;
   Wire#(Bit#(1)) dac_dco_p <- mkDWire(0);
   Wire#(Bit#(1)) dac_dco_n <- mkDWire(0);

   Clock dac_dco <- mkClockIBUFDS(dac_dco_p, dac_dco_n);
   Reset dac_reset <- mkAsyncReset(3, def_reset, dac_dco);

   SyncFIFOIfc#(Vector#(2, OIQ)) outfifo <- mkSyncBRAMFIFO(128, def_clock, def_reset, dac_dco, dac_reset);

   Gearbox#(2, 1, OIQ) gb <- mkNto1Gearbox(dac_dco, dac_reset, dac_dco, dac_reset);
   ODDRParams#(Bit#(14)) oddrparams = defaultValue;
   oddrparams.ddr_clk_edge = "SAME_EDGE_PIPELINED";

   ODDR#(Bit#(14)) dac_ddr <- mkODDR(oddrparams, clocked_by dac_dco);

   Vector#(14, Wire#(Bit#(1))) dac_ddr_data <- replicateM(mkDWire(0));

   Vector#(14, DiffOut) dac_out = newVector;

   for (Integer i = 0; i < 14; i = i + 1)
      dac_out[i] <- mkxOBUFDS(dac_ddr_data[i]);

   rule senddown_gb;
      outfifo.deq();
      gb.enq(outfifo.first());
   endrule

   rule senddown_oddr;
      let d = gb.first;
      gb.deq();
      dac_ddr.d1(d[0].data_i[15:2]);
      dac_ddr.d2(d[0].data_q[15:2]);
   endrule

   function Bit#(1) foo_p(DiffOut v);
      return (v.read_p());
   endfunction

   function Bit#(1) foo_n(DiffOut v);
      return (v.read_n());
   endfunction

   function Bit#(14) get_p(Vector#(14, DiffOut) v);
      return(pack(map(foo_p, v)));
   endfunction

   function Bit#(14) get_n(Vector#(14, DiffOut) v);
      return(pack(map(foo_n, v)));
   endfunction

   interface FMComms1DACPins pins;

      method Bit#(14) io_dac_data_p();
         return(get_p(dac_out));
      endmethod

      method Bit#(14) io_dac_data_n();
         return(get_n(dac_out));
      endmethod

      method Action io_dac_dco_p(Bit#(1) v);
	 dac_dco_p <= v;
      endmethod

      method Action io_dac_dco_n(Bit#(1) v);
	 dac_dco_n <= v;
      endmethod

   endinterface

   interface PipeIn dac;

      method Action enq(Bit#(64) v);
	 outfifo.enq(pack(unpack(v)));
      endmethod

      method Bool notFull() = outfifo.notFull;

   endinterface

endmodule

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

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

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

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

import XilinxCells::*;
import XbsvXilinxCells::*;
import Gearbox::*;
import Pipe::*;
import FIFO::*;
import BRAMFIFO::*;
import Vector::*;
import Clocks::*;
import DefaultValue::*;

import extraXilinxCells::*;

(* always_enabled *)
interface FMComms1DACPins;
   method Bit#(14) io_dac_data_p();
   method Bit#(14) io_dac_data_n();
   method Action io_dac_dco_p(Bit#(1) v);
   method Action io_dac_dco_n(Bit#(1) v);
endinterface

typedef struct {
   Bit#(16) data_i;
   Bit#(16) data_q;
   } OIQ deriving (Bits);

interface FMComms1DAC;
   interface FMComms1DACPins pins;
   interface PipeIn#(Vector#(2, OIQ)) dac;
endinterface

/* This module drives an Analog Devices FMComms1
 * evaluation board Digital to Analog Converter, it accepts
 * the data as a PipeIn type on the default clock.
 * The FMComms1 supplies the DAC clock as a differential pair
 *
 * Output is double data rate, with clock supplied by the FMComms1
 * Output data is 14 bits twos-complement or offset binary
 *
 * Differential outputs are converted from single ended by using Xilinx OBUFDS
 * cells. The clock is converted to single ended by an IBUFGDS cell
 *
 * DDR data is convered from SDR using ODDR cells
 * At this point, the data is a 14 bit in-phase data signal,
 * plus a 14 bit quadrature signal, interleaved
 *
 * The SDR data is a 32-bit OIQ datatype
 *
 * The 32-bit data is converted from 64-bits by a Gearbox
 *
 * Clock conversion happens 64-bits wide using a SyncBRAMFIFO, which
 * presents a PipeIn channel to the rest of the logic.
 */

module mkFMComms1DAC(FMComms1DAC);

   Clock def_clock <- exposeCurrentClock;
   Reset def_reset <- exposeCurrentReset;
   Wire#(Bit#(1)) dac_dco_p <- mkDWire(0);
   Wire#(Bit#(1)) dac_dco_n <- mkDWire(0);

   Clock dac_dco <- mkClockIBUFDS(dac_dco_p, dac_dco_n);
   Reset dac_reset <- mkAsyncReset(3, def_reset, dac_dco);

   SyncFIFOIfc#(Vector#(2, OIQ)) outfifo <- mkSyncBRAMFIFO(128, def_clock, def_reset, dac_dco, dac_reset);

   Gearbox#(2, 1, OIQ) gb <- mkNto1Gearbox(dac_dco, dac_reset, dac_dco, dac_reset);
   ODDRParams#(Bit#(14)) oddrparams = defaultValue;
   oddrparams.ddr_clk_edge = "SAME_EDGE_PIPELINED";

   ODDR#(Bit#(14)) dac_ddr <- mkODDR(oddrparams, clocked_by dac_dco);

   Vector#(14, Wire#(Bit#(1))) dac_ddr_data <- replicateM(mkDWire(0));

   Vector#(14, DiffOut) dac_out = newVector;

   for (Integer i = 0; i < 14; i = i + 1)
      dac_out[i] <- mkxOBUFDS(dac_ddr_data[i]);

   rule senddown_gb;
      outfifo.deq();
      gb.enq(outfifo.first());
   endrule

   rule senddown_oddr;
      let d = gb.first;
      gb.deq();
      dac_ddr.d1(d[0].data_i[15:2]);
      dac_ddr.d2(d[0].data_q[15:2]);
   endrule

   function Bit#(1) foo_p(DiffOut v);
      return (v.read_p());
   endfunction

   function Bit#(1) foo_n(DiffOut v);
      return (v.read_n());
   endfunction

   function Bit#(14) get_p(Vector#(14, DiffOut) v);
      return(pack(map(foo_p, v)));
   endfunction

   function Bit#(14) get_n(Vector#(14, DiffOut) v);
      return(pack(map(foo_n, v)));
   endfunction

   interface FMComms1DACPins pins;

      method Bit#(14) io_dac_data_p();
         return(get_p(dac_out));
      endmethod

      method Bit#(14) io_dac_data_n();
         return(get_n(dac_out));
      endmethod

      method Action io_dac_dco_p(Bit#(1) v);
	 dac_dco_p <= v;
      endmethod

      method Action io_dac_dco_n(Bit#(1) v);
	 dac_dco_n <= v;
      endmethod

   endinterface

   interface PipeIn dac;

      method Action enq(Vector#(2, OIQ) v);
	 outfifo.enq(v);
      endmethod

      method Bool notFull() = outfifo.notFull;

   endinterface

endmodule