replace for loop with readVReg

replace for loop with readVReg

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

import PriorityEncoder::*;

typedef 32 SIZE;

typedef struct {
    valueType v;
    priorityType p;
} Node#(type valueType, type priorityType) deriving(Bits, Eq);

instance DefaultValue#(Node#(Bit#(size_t), Bit#(size_t)));
    defaultValue = Node {
        v : 0,
        p : maxBound
    };
endinstance

interface MinPriorityQueue#(type valueType, type priorityType);
    interface Put#(Node#(valueType, priorityType)) insert_req;
    interface Get#(void) insert_res;
    method ActionValue#(Node#(valueType, priorityType)) first();
    method Action deq();
    method Action clear();
    method Action displayQueue();
endinterface

function Int#(2) compare (Node#(Bit#(size_t), Bit#(size_t)) x,
                          Node#(Bit#(size_t), Bit#(size_t)) y);
    if (x.p > y.p)
        return 1;
    else if (x.p == y.p)
        return 0;
    else
        return -1;
endfunction

module mkMinPriorityQueue (MinPriorityQueue#(Bit#(size_t), Bit#(size_t)));
    FIFO#(Node#(Bit#(size_t), Bit#(size_t)))
        insert_req_fifo <- mkSizedFIFO(valueof(SIZE));
    FIFO#(void) insert_res_fifo <- mkBypassFIFO;

    PE#(SIZE) priority_encoder <- mkPEncoder;

    Vector#(SIZE, Reg#(Node#(Bit#(size_t), Bit#(size_t))))
                   sorted_list <- replicateM(mkReg(defaultValue));
    Vector#(SIZE, Reg#(Bit#(1))) b_vector <- replicateM(mkReg(0));
    Reg#(Node#(Bit#(size_t), Bit#(size_t))) node_to_insert <- mkReg(defaultValue);
    Reg#(Bit#(TLog#(SIZE))) location_to_insert <- mkReg(0);
    Reg#(Bit#(TLog#(SIZE))) curr_size <- mkReg(0);

    Reg#(Bit#(1)) insert_in_progress <- mkReg(0);

    Vector#(SIZE, FIFO#(void)) create_bit_vector_fifo <- replicateM(mkFIFO);
    FIFO#(void) find_correct_location_fifo <- mkPipelineFIFO;
    Vector#(SIZE, FIFO#(void))
        insert_in_correct_location_fifo <- replicateM(mkBypassFIFO);

    Reg#(Bit#(64)) count <- mkReg(0);
    rule counter;
        count <= count + 1;
    endrule

    for (Integer i = 0; i < valueof(SIZE); i = i + 1)
    begin
        rule create_bit_vector_rule (insert_in_progress == 1);
            let x <- toGet(create_bit_vector_fifo[i]).get;
            if (i == 0)
                find_correct_location_fifo.enq(?);
            if (compare(sorted_list[i], node_to_insert) > 0)
                b_vector[i] <= 1;
            else
                b_vector[i] <= 0;
        endrule
    end

    rule find_correct_location_rule (insert_in_progress == 1);
        let x <- toGet(find_correct_location_fifo).get;
        priority_encoder.oht.put(pack(readVReg(b_vector)));
    endrule

    rule get_correct_location_rule (insert_in_progress == 1);
        let x <- toGet(priority_encoder.bin).get;
        case (x) matches
            tagged Valid .index : insert_in_correct_location_fifo[index].enq(?);
        endcase
    endrule

    for (Integer i = 0; i < valueof(SIZE); i = i + 1)
    begin
        rule insert_in_correct_location_rule (insert_in_progress == 1);
            let y <- toGet(insert_in_correct_location_fifo[i]).get;
            for (Integer j = i; j < valueof(SIZE)-1; j = j + 1)
                sorted_list[j + 1] <= sorted_list[j];
            sorted_list[i] <= node_to_insert;
            insert_in_progress <= 0;
            curr_size <= curr_size + 1;
            insert_res_fifo.enq(?);
        endrule
    end

    rule handle_insert_req (insert_in_progress == 0);
        let req <- toGet(insert_req_fifo).get;
        node_to_insert <= req;
        insert_in_progress <= 1;
        for (Integer i = 0; i < valueof(SIZE); i = i + 1)
            create_bit_vector_fifo[i].enq(?);
    endrule

    method ActionValue#(Node#(Bit#(size_t), Bit#(size_t))) first()
                                               if (curr_size > 0);
        return sorted_list[0];
    endmethod

    method Action deq() if (insert_in_progress == 0 && curr_size > 0);
        for (Integer i = 0; i < valueof(SIZE)-1; i = i + 1)
            sorted_list[i] <= sorted_list[i + 1];
        sorted_list[valueof(SIZE)-1] <= defaultValue;
        curr_size <= curr_size - 1;
    endmethod

    method Action clear() if (insert_in_progress == 0 && curr_size > 0);
        writeVReg(sorted_list, defaultValue);
        curr_size <= 0;
    endmethod

    method Action displayQueue();
        for (Integer i = 0; i < valueof(SIZE); i = i + 1)
            $display("(%d %d)", sorted_list[i].v, sorted_list[i].p);
    endmethod

    interface Put insert_req = toPut(insert_req_fifo);
    interface Get insert_res = toGet(insert_res_fifo);
endmodule

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

import PriorityEncoder::*;

typedef 32 SIZE;

typedef struct {
    valueType v;
    priorityType p;
} Node#(type valueType, type priorityType) deriving(Bits, Eq);

instance DefaultValue#(Node#(Bit#(size_t), Bit#(size_t)));
    defaultValue = Node {
        v : 0,
        p : maxBound
    };
endinstance

interface MinPriorityQueue#(type valueType, type priorityType);
    interface Put#(Node#(valueType, priorityType)) insert_req;
    interface Get#(void) insert_res;
    method ActionValue#(Node#(valueType, priorityType)) first();
    method Action deq();
    method Action clear();
    method Action displayQueue();
endinterface

function Int#(2) compare (Node#(Bit#(size_t), Bit#(size_t)) x,
                          Node#(Bit#(size_t), Bit#(size_t)) y);
    if (x.p > y.p)
        return 1;
    else if (x.p == y.p)
        return 0;
    else
        return -1;
endfunction

module mkMinPriorityQueue (MinPriorityQueue#(Bit#(size_t), Bit#(size_t)));
    FIFO#(Node#(Bit#(size_t), Bit#(size_t)))
        insert_req_fifo <- mkSizedFIFO(valueof(SIZE));
    FIFO#(void) insert_res_fifo <- mkBypassFIFO;

    PE#(SIZE) priority_encoder <- mkPEncoder;

    Vector#(SIZE, Reg#(Node#(Bit#(size_t), Bit#(size_t))))
                   sorted_list <- replicateM(mkReg(defaultValue));
    Vector#(SIZE, Reg#(Bit#(1))) b_vector <- replicateM(mkReg(0));
    Reg#(Node#(Bit#(size_t), Bit#(size_t))) node_to_insert <- mkReg(defaultValue);
    Reg#(Bit#(TLog#(SIZE))) location_to_insert <- mkReg(0);
    Reg#(Bit#(TLog#(SIZE))) curr_size <- mkReg(0);

    Reg#(Bit#(1)) insert_in_progress <- mkReg(0);

    Vector#(SIZE, FIFO#(void)) create_bit_vector_fifo <- replicateM(mkFIFO);
    FIFO#(void) find_correct_location_fifo <- mkPipelineFIFO;
    Vector#(SIZE, FIFO#(void))
        insert_in_correct_location_fifo <- replicateM(mkBypassFIFO);

    Reg#(Bit#(64)) count <- mkReg(0);
    rule counter;
        count <= count + 1;
    endrule

    for (Integer i = 0; i < valueof(SIZE); i = i + 1)
    begin
        rule create_bit_vector_rule (insert_in_progress == 1);
            let x <- toGet(create_bit_vector_fifo[i]).get;
            if (i == 0)
                find_correct_location_fifo.enq(?);
            if (compare(sorted_list[i], node_to_insert) > 0)
                b_vector[i] <= 1;
            else
                b_vector[i] <= 0;
        endrule
    end

    rule find_correct_location_rule (insert_in_progress == 1);
        let x <- toGet(find_correct_location_fifo).get;
        Bit#(SIZE) temp = 0;
        for (Integer i = 0; i < valueof(SIZE); i = i + 1)
        begin
            temp[i] = b_vector[i];
        end
        priority_encoder.oht.put(temp);
    endrule

    rule get_correct_location_rule (insert_in_progress == 1);
        let x <- toGet(priority_encoder.bin).get;
        case (x) matches
            tagged Valid .index : insert_in_correct_location_fifo[index].enq(?);
        endcase
    endrule

    for (Integer i = 0; i < valueof(SIZE); i = i + 1)
    begin
        rule insert_in_correct_location_rule (insert_in_progress == 1);
            let y <- toGet(insert_in_correct_location_fifo[i]).get;
            for (Integer j = i; j < valueof(SIZE)-1; j = j + 1)
                sorted_list[j + 1] <= sorted_list[j];
            sorted_list[i] <= node_to_insert;
            insert_in_progress <= 0;
            curr_size <= curr_size + 1;
            insert_res_fifo.enq(?);
        endrule
    end

    rule handle_insert_req (insert_in_progress == 0);
        let req <- toGet(insert_req_fifo).get;
        node_to_insert <= req;
        insert_in_progress <= 1;
        for (Integer i = 0; i < valueof(SIZE); i = i + 1)
            create_bit_vector_fifo[i].enq(?);
    endrule

    method ActionValue#(Node#(Bit#(size_t), Bit#(size_t))) first()
                                               if (curr_size > 0);
        return sorted_list[0];
    endmethod

    method Action deq() if (insert_in_progress == 0 && curr_size > 0);
        for (Integer i = 0; i < valueof(SIZE)-1; i = i + 1)
            sorted_list[i] <= sorted_list[i + 1];
        sorted_list[valueof(SIZE)-1] <= defaultValue;
        curr_size <= curr_size - 1;
    endmethod

    method Action clear() if (insert_in_progress == 0 && curr_size > 0);
        for (Integer i = 0; i < valueof(SIZE); i = i + 1)
            sorted_list[i] <= defaultValue;
        curr_size <= 0;
    endmethod

    method Action displayQueue();
        for (Integer i = 0; i < valueof(SIZE); i = i + 1)
            $display("(%d %d)", sorted_list[i].v, sorted_list[i].p);
    endmethod

    interface Put insert_req = toPut(insert_req_fifo);
    interface Get insert_res = toGet(insert_res_fifo);
endmodule


rtruncate in BsimTopPcie was the wrong answer

// 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 Connectable       :: *;
import Xilinx            :: *;
import RegFile           :: *;
import GetPut            :: *;

import Portal            :: *;
import Leds              :: *;
import Top               :: *;
import AxiSlaveEngine    :: *;
import PortalEngine      :: *;

module mkBsimTop(Empty);

   RegFile#(Bit#(11), Bit#(192)) tlp_trace <- mkRegFileFullLoad("testdata.dat");

   PortalTop#(40,64,Empty)  portalTop <- mkPortalTop;
   AxiSlaveEngine#(64) axiSlaveEngine <- mkAxiSlaveEngine(unpack(0));
   PortalEngine          portalEngine <- mkPortalEngine(unpack(0));

   mkConnection(portalTop.m_axi, axiSlaveEngine.slave3);
   mkConnection(portalEngine.portal, portalTop.ctrl);

   Reg#(Bit#(11)) ptr <- mkReg(1);
   Bool dump = True;

   rule read_trace if (ptr+1 != 0);
      ptr <= ptr+1;

      let lineitem = tlp_trace.sub(ptr);
      Bit#(160) dataline = truncate(lineitem);

      Bit#(8) portnum = dataline[159:152] >> 1;
      Bit#(4) tlpsof  = dataline[155:152] & 4'b1;
      Bit#(8) pkttype = dataline[127:120] & 8'h1f;

      Bit#(32) seqno  = lineitem[191:160];

      // TX == to host
      // RX == from host
      // qq == request
      // pp == response

      Bool rx = False;
      Bool tx = False;
      Bool cc = False;
      Bool pp = False;
      Bool qq = False;

      if (portnum == 4) begin
	 rx = True;
	 if (dump)
            $write("RX");
      end
      else if (portnum == 8) begin
	 tx = True;
	 if (dump)
            $write("TX");
      end
      else begin
	 if (dump)
	    $write("__");
      end

      if (tlpsof == 0) begin
	 cc = True;
	 if (dump)
            $write("cc: ");
      end
      else if (pkttype == 10) begin
	 pp = True;
	 if (dump)
            $write("pp: ");
      end
      else begin
	 qq = True;
	 if (dump)
	    $write("qq: ");
      end

      if (dump) begin
	 $write("JJ ");
	 $write("%h ", seqno);
	 $display("%h", dataline);
      end

      // NOTE: as long as the ctrl interface doesn't support bursts, this decoding is sufficient

      // RXqq: portal request
      // TXpp: portal indication
      // TXqq: DMA request
      // RXpp: DMA response
      // RXcc: DMA read data
      // TXcc: DMA write data

      // function Bit#(153) rtrunc(Bit#(160) x);
      // 	 return x[159:7];
      // endfunction

      if (rx && qq)
	 portalEngine.tlp_in.put(unpack(truncate(dataline)));
      else if (tx && pp)
	 let _x0 <- portalEngine.tlp_out.get;
      else if (tx && qq)
	 let _x1 <- tpl_1(axiSlaveEngine.tlps).get;
      else if (rx && pp)
	 tpl_2(axiSlaveEngine.tlps).put(unpack(truncate(dataline)));
      else if (rx && cc)
	 tpl_2(axiSlaveEngine.tlps).put(unpack(truncate(dataline)));
      else if (tx && cc)
	 let _x2 <- tpl_1(axiSlaveEngine.tlps).get;

   endrule

   rule quit if (ptr+1 == 0);
      $finish;
   endrule

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 Vector            :: *;
import Connectable       :: *;
import Xilinx            :: *;
import RegFile           :: *;
import GetPut            :: *;

import Portal            :: *;
import Leds              :: *;
import Top               :: *;
import AxiSlaveEngine    :: *;
import PortalEngine      :: *;

module mkBsimTop(Empty);

   RegFile#(Bit#(11), Bit#(192)) tlp_trace <- mkRegFileFullLoad("testdata.dat");

   PortalTop#(40,64,Empty)  portalTop <- mkPortalTop;
   AxiSlaveEngine#(64) axiSlaveEngine <- mkAxiSlaveEngine(unpack(0));
   PortalEngine          portalEngine <- mkPortalEngine(unpack(0));

   mkConnection(portalTop.m_axi, axiSlaveEngine.slave3);
   mkConnection(portalEngine.portal, portalTop.ctrl);

   Reg#(Bit#(11)) ptr <- mkReg(1);
   Bool dump = True;

   rule read_trace if (ptr+1 != 0);
      ptr <= ptr+1;

      let lineitem = tlp_trace.sub(ptr);
      Bit#(160) dataline = truncate(lineitem);

      Bit#(8) portnum = dataline[159:152] >> 1;
      Bit#(4) tlpsof  = dataline[155:152] & 4'b1;
      Bit#(8) pkttype = dataline[127:120] & 8'h1f;

      Bit#(32) seqno  = lineitem[191:160];

      // TX == to host
      // RX == from host
      // qq == request
      // pp == response

      Bool rx = False;
      Bool tx = False;
      Bool cc = False;
      Bool pp = False;
      Bool qq = False;

      if (portnum == 4) begin
	 rx = True;
	 if (dump)
            $write("RX");
      end
      else if (portnum == 8) begin
	 tx = True;
	 if (dump)
            $write("TX");
      end
      else begin
	 if (dump)
	    $write("__");
      end

      if (tlpsof == 0) begin
	 cc = True;
	 if (dump)
            $write("cc: ");
      end
      else if (pkttype == 10) begin
	 pp = True;
	 if (dump)
            $write("pp: ");
      end
      else begin
	 qq = True;
	 if (dump)
	    $write("qq: ");
      end

      if (dump) begin
	 $write("JJ ");
	 $write("%h ", seqno);
	 $display("%h", dataline);
      end

      // NOTE: as long as the ctrl interface doesn't support bursts, this decoding is sufficient

      // RXqq: portal request
      // TXpp: portal indication
      // TXqq: DMA request
      // RXpp: DMA response
      // RXcc: DMA read data
      // TXcc: DMA write data

      function Bit#(153) rtrunc(Bit#(160) x);
	 return x[159:7];
      endfunction

      if (rx && qq)
	 portalEngine.tlp_in.put(unpack(rtrunc(dataline)));
      else if (tx && pp)
	 let _x0 <- portalEngine.tlp_out.get;
      else if (tx && qq)
	 let _x1 <- tpl_1(axiSlaveEngine.tlps).get;
      else if (rx && pp)
	 tpl_2(axiSlaveEngine.tlps).put(unpack(rtrunc(dataline)));
      else if (rx && cc)
	 tpl_2(axiSlaveEngine.tlps).put(unpack(rtrunc(dataline)));
      else if (tx && cc)
	 let _x2 <- tpl_1(axiSlaveEngine.tlps).get;

   endrule

   rule quit if (ptr+1 == 0);
      $finish;
   endrule

endmodule


update SimpleMatchTable with actionRam

update SimpleMatchTable with actionRam

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

/*
* SimpleMatchTable, which:
* - uses low order bits in input keys as indices to internal table
* - implements the same interface as cuckoo hashtable
* - is used for development and debugging purposes only
*/

import BRAM::*;
import Connectable::*;
import FIFOF::*;
import Pipe::*;
import SpecialFIFOs::*;

import Types::*;
import SimpleCAM::*;

interface MatchTable_port_mapping;
   interface PipeIn#(MatchInput_port_mapping) phv_in;
   interface PipeOut#(ActionSpec_port_mapping) action_data;
   interface Put#(MatchSpec_port_mapping) put_entry;
   interface Get#(Maybe#(MatchSpec_port_mapping)) get_entry;
endinterface

interface MatchTable_bd;
   interface PipeIn#(MatchInput_bd) phv_in;
   interface PipeOut#(ActionSpec_bd) action_data;
   interface Put#(MatchSpec_bd) put_entry;
   interface Get#(Maybe#(MatchSpec_bd)) get_entry;
endinterface

// Input: MatchInput
// Input: MatchSpec
// Output: ActionSpec
(* synthesize *)
module mkMatchTable_port_mapping(MatchTable_port_mapping);

   Reg#(Bit#(32)) cycle <- mkReg(0);
   FIFOF#(MatchInput_port_mapping) fifo_in_port_mapping <- mkSizedFIFOF(1);
   FIFOF#(ActionSpec_port_mapping) fifo_out_action_data <- mkSizedFIFOF(1);

   CAM#(16, Bit#(9), Bit#(9)) cam <- mkCAM();

   BRAM_Config cfg = defaultValue;
   cfg.latency = 1;
   BRAM2Port#(Bit#(9), Bit#(16)) actionRam <- mkBRAM2Server(cfg);

   rule every1;
      cycle <= cycle + 1;
   endrule

   rule cam_lookup;
      let v <- toGet(fifo_in_port_mapping).get;
      $display("%x: match table get_phv %x", cycle, v);
      cam.readPort.request.put(pack(v));
   endrule

   rule action_param_lookup;
      let v <- cam.readPort.response.get;

   rule action_param_output;
      $display("%x: match table domatch %x", cycle, v);
      // either match or not match
      if (isValid(v)) begin
         fifo_out_action_data.enq(ActionSpec_port_mapping{bd:0});
      end
      else begin
         $display("packet match missed");
      end
   endrule

   interface Put put_entry;
      method Action put(MatchSpec_port_mapping e);
         cam.writePort.put(tuple2(pack(e), pack(e)));
      endmethod
   endinterface

   interface PipeIn phv_in = toPipeIn(fifo_in_port_mapping);
   interface PipeOut action_data = toPipeOut(fifo_out_action_data);
endmodule

(* synthesize *)
module mkMatchTable_bd(MatchTable_bd);

   FIFOF#(MatchInput_bd) fifo_in_bd <- mkSizedFIFOF(1);
   FIFOF#(ActionSpec_bd) fifo_out_action_data <- mkSizedFIFOF(1);

   CAM#(16, Bit#(16), Bit#(16)) cam <- mkCAM();

   rule get_phv;
      let v <- toGet(fifo_in_bd).get;
      cam.readPort.request.put(pack(v));
   endrule

   rule getMatchResult;
      let v <- cam.readPort.response.get;
      fifo_out_action_data.enq(ActionSpec_bd{vrf:0});
   endrule

   interface Put put_entry;
      method Action put(MatchSpec_bd e);
         cam.writePort.put(tuple2(pack(e), pack(e)));
      endmethod
   endinterface

   interface PipeIn phv_in = toPipeIn(fifo_in_bd);
   interface PipeOut action_data = toPipeOut(fifo_out_action_data);
endmodule

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

/*
* SimpleMatchTable, which:
* - uses low order bits in input keys as indices to internal table
* - implements the same interface as cuckoo hashtable
* - is used for development and debugging purposes only
*/

import BRAM::*;
import Connectable::*;
import FIFOF::*;
import Pipe::*;
import SpecialFIFOs::*;

import Types::*;
import SimpleCAM::*;

typedef 16 BramAddrWidth;

interface MatchTable_port_mapping;
   interface PipeIn#(MatchInput_port_mapping) phv_in;
   interface PipeOut#(ActionSpec_port_mapping) action_data;
   interface Put#(MatchSpec_port_mapping) put_entry;
   interface Get#(Maybe#(MatchSpec_port_mapping)) get_entry;
endinterface

interface MatchTable_bd;
   interface PipeIn#(MatchInput_bd) phv_in;
   interface PipeOut#(ActionSpec_bd) action_data;
   interface Put#(MatchSpec_bd) put_entry;
   interface Get#(Maybe#(MatchSpec_bd)) get_entry;
endinterface

// Input: MatchInput
// Input: MatchSpec
// Output: ActionSpec
(* synthesize *)
module mkMatchTable_port_mapping(MatchTable_port_mapping);

   FIFOF#(MatchInput_port_mapping) fifo_in_port_mapping <- mkSizedFIFOF(1);
   FIFOF#(ActionSpec_port_mapping) fifo_out_action_data <- mkSizedFIFOF(1);

   FIFOF#(Bit#(9)) match_cfFifo <- mkSizedFIFOF(1);

   CAM#(16, Bit#(9), Bit#(9)) cam <- mkCAM();
   Reg#(Bit#(32)) cycle <- mkReg(0);

   rule every1;
      cycle <= cycle + 1;
   endrule

   rule get_phv;
      let v <- toGet(fifo_in_port_mapping).get;
      $display("%x: match table get_phv %x", cycle, v);
      match_cfFifo.enq(1);
   endrule

   rule doMatch;
      let v <- toGet(match_cfFifo).get;
      $display("%x: match table domatch %x", cycle, v);
      cam.readPort.request.put(v);
   endrule

   rule getMatchResult;
      let entry <- cam.readPort.response.get;
      $display("%x: match table domatch %x", cycle, entry);
      fifo_out_action_data.enq(ActionSpec_port_mapping{bd:0});
   endrule

   interface Put put_entry;
      method Action put(MatchSpec_port_mapping e);
         cam.writePort.put(tuple2(zeroExtend(pack(e)), pack(e)));
      endmethod
   endinterface

   interface PipeIn phv_in = toPipeIn(fifo_in_port_mapping);
   interface PipeOut action_data = toPipeOut(fifo_out_action_data);
endmodule

(* synthesize *)
module mkMatchTable_bd(MatchTable_bd);

   FIFOF#(MatchInput_bd) fifo_in_bd <- mkSizedFIFOF(1);
   FIFOF#(ActionSpec_bd) fifo_out_action_data <- mkSizedFIFOF(1);

   FIFOF#(Bit#(16)) match_cfFifo <- mkSizedFIFOF(1);

   CAM#(16, Bit#(16), Bit#(16)) cam <- mkCAM();

   rule get_phv;
      let v <- toGet(fifo_in_bd).get;
      match_cfFifo.enq(1);
   endrule

   rule doMatch;
      let v <- toGet(match_cfFifo).get;
      cam.readPort.request.put(zeroExtend(v));
   endrule

   rule getMatchResult;
      let entry <- cam.readPort.response.get;
      fifo_out_action_data.enq(ActionSpec_bd{vrf:0});
   endrule

   interface Put put_entry;
      method Action put(MatchSpec_bd e);
         cam.writePort.put(tuple2(pack(e), pack(e)));
      endmethod
   endinterface

   interface PipeIn phv_in = toPipeIn(fifo_in_bd);
   interface PipeOut action_data = toPipeOut(fifo_out_action_data);
endmodule


added instance ToGet

added instance ToGet

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

interface PipeOut#(type a);
   method a first();
   method Action deq();
   method Bool notEmpty();
endinterface

typeclass PipeInOut#(type a, type b);
   function PipeOut#(a) toPipeOut(b in);
endtypeclass

typeclass MkPipeInOut#(type a, type b);
   module mkPipeOut#(b in)(PipeOut#(a));
endtypeclass

instance PipeInOut#(a, FIFOF#(a));
   function PipeOut#(a) toPipeOut(FIFOF#(a) in);
      return (interface PipeOut#(a);
		 method first = in.first;
		 method deq = in.deq;
		 method notEmpty = in.notEmpty;
	      endinterface);
   endfunction
endinstance

instance PipeInOut#(Vector#(n,a), MIMO#(k,n,sz,a));
   function PipeOut#(Vector#(n,a)) toPipeOut(MIMO#(k,n,sz,a) in);
      return (interface PipeOut#(a);
		 method first = in.first;
		 method Action deq() if (in.deqReadyN(fromInteger(valueOf(n))));
		    in.deq(fromInteger(valueOf(n)));
		 endmethod
		 method Bool notEmpty();
		    return in.deqReadyN(fromInteger(valueOf(n)));
		 endmethod
	      endinterface);
   endfunction
endinstance

instance MkPipeInOut#(a, Get#(a))
   provisos (Bits#(a, asz));
   module mkPipeOut#(Get#(a) in)(PipeOut#(a));
      FIFOF#(a) fifo <- mkFIFOF();
      rule connect;
	 let v <- in.get();
	 fifo.enq(v);
      endrule
      return toPipeOut(fifo);
   endmodule
endinstance

instance ToGet #(PipeOut #(a), a);
   function Get #(a) toGet (PipeOut #(a) po);
      return (interface Get;
                 method ActionValue #(a) get ();
                    po.deq ();
                    return po.first ();
                 endmethod
              endinterface);
   endfunction
endinstance

instance Connectable#(PipeOut#(a),Put#(a));
   module mkConnection#(PipeOut#(a) in, Put#(a) out)(Empty);
      rule connect;
	 let v = in.first;
	 in.deq();
	 out.put(v);
      endrule
   endmodule
endinstance

module mkUnfunnel#(PipeOut#(Vector#(m,a)) in)(PipeOut#(Vector#(mk, a)))
   provisos (Mul#(m, k, mk),
	     Bits#(a, asz),
	     Add#(1, b__, asz),
	     Add#(2, c__, mk),
	     Add#(d__, m, mk),
	     Add#(asz, m, e__),
	     Add#(asz, mk, f__));
   let m = fromInteger(valueOf(m));
   let mk = fromInteger(valueOf(mk));

   MIMOConfiguration cfg = defaultValue();
   MIMO#(m, mk, mk, a) mimo <- mkMIMO(cfg);
   rule consumer if (mimo.enqReadyN(m));
      Vector#(m, a) v = in.first();
      in.deq();
      mimo.enq(m, v);
   endrule

   method Vector#(mk, a) first() if (mimo.deqReadyN(mk));
      return mimo.first();
   endmethod
   method Action deq() if (mimo.deqReadyN(mk));
      mimo.deq(mk);
   endmethod
   method notEmpty();
      return mimo.deqReadyN(mk);
   endmethod
endmodule

module mkForkVector#(PipeOut#(a) inpipe)(Vector#(n, PipeOut#(a)))
   provisos (Bits#(a, asz));
   Vector#(n, FIFOF#(a)) fifos <- replicateM(mkFIFOF());
   rule forkelts;
      let v = inpipe.first();
      inpipe.deq;
      for (Integer i = 0; i < valueOf(n); i = i + 1) begin
	 fifos[i].enq(v);
      end
   endrule
   return map(toPipeOut, fifos);
endmodule

module mkJoin#(function c f(a av, b bv), PipeOut#(a) apipe, PipeOut#(b) bpipe)(PipeOut#(c));
   method c first();
      let av = apipe.first();
      let bv = bpipe.first();
      return f(av, bv);
   endmethod
   method Action deq();
      apipe.deq();
      bpipe.deq();
   endmethod
   method Bool notEmpty();
      return apipe.notEmpty() && bpipe.notEmpty();
   endmethod
endmodule

module mkJoinVector#(function b f(Vector#(n, a) av), Vector#(n, PipeOut#(a)) apipes)(PipeOut#(b))
   provisos (Bits#(Vector#(n,a),vasz));
   method b first();
      function a getfirst(PipeOut#(a) pipein); return pipein.first(); endfunction
      Vector#(n,a) vec = map(getfirst, apipes);
      return f(vec);
   endmethod
   method Action deq();
      function a getfirst(PipeOut#(a) pipein); return pipein.first(); endfunction
      for (Integer i = 0; i < valueOf(n); i = i + 1)
	 apipes[i].deq();
   endmethod
   method Bool notEmpty();
      function Bool getNotEmpty(PipeOut#(a) pipein); return pipein.notEmpty(); endfunction
      function Bool myand(Bool a, Bool b); return a && b; endfunction
      return foldl(myand, True, map(getNotEmpty, apipes));
   endmethod
endmodule

module mkMap#(function b f(a av), PipeOut#(a) apipe)(PipeOut#(b));
   method b first();
      let av = apipe.first();
      return f(av);
   endmethod
   method Action deq();
      apipe.deq();
   endmethod
   method Bool notEmpty();
      return apipe.notEmpty();
   endmethod
endmodule

typedef (function Module #(PipeOut #(tb)) mkPipeOut(PipeOut#(ta) ifc)) MkPipeOut#(type ta, type tb);

typeclass ReducePipe#( numeric type n, type a);
   module [Module] mkReducePipe (MkPipeOut#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(n,a)) inpipe,
				 PipeOut#(a) ifc);
endtypeclass
instance ReducePipe#(1, a);
   module [Module] mkReducePipe (MkPipeOut#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(1,a)) inpipe,
				 PipeOut#(a) ifc);
      let pipe <- mkMap(head, inpipe);
      return pipe;
   endmodule
endinstance
instance ReducePipe#(2, a);
   module [Module] mkReducePipe (MkPipeOut#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(2,a)) inpipe,
				 PipeOut#(a) ifc);
      function Tuple2#(a,a) foo(Vector#(2,a) invec); return tuple2(invec[0], invec[1]); endfunction
      PipeOut#(Tuple2#(a,a)) zippipe <- mkMap(foo, inpipe);
      let pipe <- combinepipe(zippipe);
      return pipe;
   endmodule
endinstance

instance ReducePipe#(n, a)
   provisos (Add#(TDiv#(n,2), a__, n),
	     Bits#(Vector#(TDiv#(n,2), a), b__),
	     ReducePipe#(TDiv#(n,2),a));
   module [Module] mkReducePipe (MkPipeOut#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(n,a)) inpipe,
				 PipeOut#(a) ifc);
      FIFOF#(Vector#(TDiv#(n,2),a)) infifo0 <- mkFIFOF;
      FIFOF#(Vector#(TDiv#(n,2),a)) infifo1 <- mkFIFOF;
      rule splitinput;
	 let v = inpipe.first();
	 inpipe.deq();
	 infifo0.enq(takeAt(0, v));
	 infifo1.enq(takeAt(valueOf(TDiv#(n,2)), v));
      endrule
      PipeOut#(Vector#(TDiv#(n,2),a)) inpipe0 = toPipeOut(infifo0);
      PipeOut#(Vector#(TDiv#(n,2),a)) inpipe1 = toPipeOut(infifo1);

      PipeOut#(a) p0 <- mkReducePipe(combinepipe, inpipe0);
      PipeOut#(a) p1 <- mkReducePipe(combinepipe, inpipe1);

      PipeOut#(Tuple2#(a,a)) tplpipe = (interface PipeOut;
					method Tuple2#(a,a) first(); return tuple2(p0.first, p1.first); endmethod
					method Action deq(); p0.deq(); p1.deq(); endmethod
					method notEmpty(); return p0.notEmpty() && p1.notEmpty(); endmethod
					endinterface);
      PipeOut#(a) outpipe <- combinepipe(tplpipe);
      return outpipe;
   endmodule
endinstance

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

interface PipeOut#(type a);
   method a first();
   method Action deq();
   method Bool notEmpty();
endinterface

typeclass PipeInOut#(type a, type b);
   function PipeOut#(a) toPipeOut(b in);
endtypeclass

typeclass MkPipeInOut#(type a, type b);
   module mkPipeOut#(b in)(PipeOut#(a));
endtypeclass

instance PipeInOut#(a, FIFOF#(a));
   function PipeOut#(a) toPipeOut(FIFOF#(a) in);
      return (interface PipeOut#(a);
		 method first = in.first;
		 method deq = in.deq;
		 method notEmpty = in.notEmpty;
	      endinterface);
   endfunction
endinstance

instance PipeInOut#(Vector#(n,a), MIMO#(k,n,sz,a));
   function PipeOut#(Vector#(n,a)) toPipeOut(MIMO#(k,n,sz,a) in);
      return (interface PipeOut#(a);
		 method first = in.first;
		 method Action deq() if (in.deqReadyN(fromInteger(valueOf(n))));
		    in.deq(fromInteger(valueOf(n)));
		 endmethod
		 method Bool notEmpty();
		    return in.deqReadyN(fromInteger(valueOf(n)));
		 endmethod
	      endinterface);
   endfunction
endinstance

instance MkPipeInOut#(a, Get#(a))
   provisos (Bits#(a, asz));
   module mkPipeOut#(Get#(a) in)(PipeOut#(a));
      FIFOF#(a) fifo <- mkFIFOF();
      rule connect;
	 let v <- in.get();
	 fifo.enq(v);
      endrule
      return toPipeOut(fifo);
   endmodule
endinstance

instance Connectable#(PipeOut#(a),Put#(a));
   module mkConnection#(PipeOut#(a) in, Put#(a) out)(Empty);
      rule connect;
	 let v = in.first;
	 in.deq();
	 out.put(v);
      endrule
   endmodule
endinstance

module mkUnfunnel#(PipeOut#(Vector#(m,a)) in)(PipeOut#(Vector#(mk, a)))
   provisos (Mul#(m, k, mk),
	     Bits#(a, asz),
	     Add#(1, b__, asz),
	     Add#(2, c__, mk),
	     Add#(d__, m, mk),
	     Add#(asz, m, e__),
	     Add#(asz, mk, f__));
   let m = fromInteger(valueOf(m));
   let mk = fromInteger(valueOf(mk));

   MIMOConfiguration cfg = defaultValue();
   MIMO#(m, mk, mk, a) mimo <- mkMIMO(cfg);
   rule consumer if (mimo.enqReadyN(m));
      Vector#(m, a) v = in.first();
      in.deq();
      mimo.enq(m, v);
   endrule

   method Vector#(mk, a) first() if (mimo.deqReadyN(mk));
      return mimo.first();
   endmethod
   method Action deq() if (mimo.deqReadyN(mk));
      mimo.deq(mk);
   endmethod
   method notEmpty();
      return mimo.deqReadyN(mk);
   endmethod
endmodule

module mkForkVector#(PipeOut#(a) inpipe)(Vector#(n, PipeOut#(a)))
   provisos (Bits#(a, asz));
   Vector#(n, FIFOF#(a)) fifos <- replicateM(mkFIFOF());
   rule forkelts;
      let v = inpipe.first();
      inpipe.deq;
      for (Integer i = 0; i < valueOf(n); i = i + 1) begin
	 fifos[i].enq(v);
      end
   endrule
   return map(toPipeOut, fifos);
endmodule

module mkJoin#(function c f(a av, b bv), PipeOut#(a) apipe, PipeOut#(b) bpipe)(PipeOut#(c));
   method c first();
      let av = apipe.first();
      let bv = bpipe.first();
      return f(av, bv);
   endmethod
   method Action deq();
      apipe.deq();
      bpipe.deq();
   endmethod
   method Bool notEmpty();
      return apipe.notEmpty() && bpipe.notEmpty();
   endmethod
endmodule

module mkJoinVector#(function b f(Vector#(n, a) av), Vector#(n, PipeOut#(a)) apipes)(PipeOut#(b))
   provisos (Bits#(Vector#(n,a),vasz));
   method b first();
      function a getfirst(PipeOut#(a) pipein); return pipein.first(); endfunction
      Vector#(n,a) vec = map(getfirst, apipes);
      return f(vec);
   endmethod
   method Action deq();
      function a getfirst(PipeOut#(a) pipein); return pipein.first(); endfunction
      for (Integer i = 0; i < valueOf(n); i = i + 1)
	 apipes[i].deq();
   endmethod
   method Bool notEmpty();
      function Bool getNotEmpty(PipeOut#(a) pipein); return pipein.notEmpty(); endfunction
      function Bool myand(Bool a, Bool b); return a && b; endfunction
      return foldl(myand, True, map(getNotEmpty, apipes));
   endmethod
endmodule

module mkMap#(function b f(a av), PipeOut#(a) apipe)(PipeOut#(b));
   method b first();
      let av = apipe.first();
      return f(av);
   endmethod
   method Action deq();
      apipe.deq();
   endmethod
   method Bool notEmpty();
      return apipe.notEmpty();
   endmethod
endmodule

typedef (function Module #(PipeOut #(tb)) mkPipeOut(PipeOut#(ta) ifc)) MkPipeOut#(type ta, type tb);

typeclass ReducePipe#( numeric type n, type a);
   module [Module] mkReducePipe (MkPipeOut#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(n,a)) inpipe,
				 PipeOut#(a) ifc);
endtypeclass
instance ReducePipe#(1, a);
   module [Module] mkReducePipe (MkPipeOut#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(1,a)) inpipe,
				 PipeOut#(a) ifc);
      let pipe <- mkMap(head, inpipe);
      return pipe;
   endmodule
endinstance
instance ReducePipe#(2, a);
   module [Module] mkReducePipe (MkPipeOut#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(2,a)) inpipe,
				 PipeOut#(a) ifc);
      function Tuple2#(a,a) foo(Vector#(2,a) invec); return tuple2(invec[0], invec[1]); endfunction
      PipeOut#(Tuple2#(a,a)) zippipe <- mkMap(foo, inpipe);
      let pipe <- combinepipe(zippipe);
      return pipe;
   endmodule
endinstance

instance ReducePipe#(n, a)
   provisos (Add#(TDiv#(n,2), a__, n),
	     Bits#(Vector#(TDiv#(n,2), a), b__),
	     ReducePipe#(TDiv#(n,2),a));
   module [Module] mkReducePipe (MkPipeOut#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(n,a)) inpipe,
				 PipeOut#(a) ifc);
      FIFOF#(Vector#(TDiv#(n,2),a)) infifo0 <- mkFIFOF;
      FIFOF#(Vector#(TDiv#(n,2),a)) infifo1 <- mkFIFOF;
      rule splitinput;
	 let v = inpipe.first();
	 inpipe.deq();
	 infifo0.enq(takeAt(0, v));
	 infifo1.enq(takeAt(valueOf(TDiv#(n,2)), v));
      endrule
      PipeOut#(Vector#(TDiv#(n,2),a)) inpipe0 = toPipeOut(infifo0);
      PipeOut#(Vector#(TDiv#(n,2),a)) inpipe1 = toPipeOut(infifo1);

      PipeOut#(a) p0 <- mkReducePipe(combinepipe, inpipe0);
      PipeOut#(a) p1 <- mkReducePipe(combinepipe, inpipe1);

      PipeOut#(Tuple2#(a,a)) tplpipe = (interface PipeOut;
					method Tuple2#(a,a) first(); return tuple2(p0.first, p1.first); endmethod
					method Action deq(); p0.deq(); p1.deq(); endmethod
					method notEmpty(); return p0.notEmpty() && p1.notEmpty(); endmethod
					endinterface);
      PipeOut#(a) outpipe <- combinepipe(tplpipe);
      return outpipe;
   endmodule
endinstance


Fixed SPI.bsv comments

Fixed SPI.bsv comments

// This is a simple SPI Master module.
// This has only been tested with cpol == 0 and cpha == 0

// For information about SPI, check wikipedia:
//   https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus

(* always_ready, always_enabled *)
interface SPIMasterPins;
    // serial clock
    (* prefix = "", result = "spi_sclk" *)
    method Bit#(1) sclk;
    // master-out slave-in
    (* prefix = "", result = "spi_mosi" *)
    method Bit#(1) mosi;
    // master-in slave-out
    (* prefix = "" *)
    method Action miso((* port = "spi_miso" *)Bit#(1) x);
    // active-low chip select
    (* prefix = "", result = "spi_ncs" *)
    method Bit#(1) ncs;
    interface Clock deleteme_unused_clock;
endinterface

interface SPIMaster;
    // configuration
    method Action setSclkDiv(Bit#(16) d);
    method Action setNcs(Bit#(1) new_ncs);
    // Warning: mkSPIMaster untested for cpol == 1
    method Action setCpol(Bit#(1) new_cpol); // idle value of clock
    // Warning: mkSPIMaster untesetd for cpha == 1
    method Action setCpha(Bit#(1) new_cpha); // which clock transition captures data
                                             // cpha = 0 => odd transitions (1st, 3rd, etc.)
                                             // cpha = 1 => even transitions (2nd, 4th, etc.)
    // status
    method Bool isChipSelectEnabled();
    // data
    method Action put(Bit#(8) x);
    method ActionValue#(Bit#(8)) get();
    // pins
    (* prefix = "" *)
    interface SPIMasterPins pins;
endinterface

module mkSPIMaster(SPIMaster);
    let clock <- exposeCurrentClock();
    // registers for the interface pins
    Reg#(Bit#(1)) sclkReg <- mkReg(0);
    Reg#(Bit#(16)) sclkDiv <- mkReg(1);
    Wire#(Bit#(1)) misoWire <- mkDWire(0);
    Reg#(Bit#(1)) misoReg <- mkReg(0);
    Reg#(Bit#(1)) ncsReg <- mkReg(1);
    // MSB gets shifted out
    Reg#(Bit#(8)) shiftReg <- mkReg(0);

    // SPI configuration
    Reg#(Bit#(1)) cpol <- mkReg(0);
    Reg#(Bit#(1)) cpha <- mkReg(0);

    // 17 ticks per SPI cycle, between each tick is a clock transition
    Reg#(Bool) running <- mkReg(False);
    Reg#(Bool) resultReady <- mkReg(False);
    Reg#(Bit#(5)) tickCount <- mkReg(0);
    // sclkReg determines how many mini ticks make up a tick
    Reg#(Bit#(16)) miniTickCount <- mkReg(0);

    (* fire_when_enabled, no_implicit_conditions *)
    rule run(running);
        let nextMiniTickCount = miniTickCount + 1;
        if ((nextMiniTickCount == sclkDiv) || sclkDiv == 0) begin
            miniTickCount <= 0;
            if (tickCount == 16) begin
                // done
                running <= False;
                resultReady <= True;
                tickCount <= 0;
            end else begin
                // tick clock
                sclkReg <= ~sclkReg;
                // increment tickCount
                tickCount <= tickCount + 1;
                // either capture input or shift output
                if (tickCount[0] == cpha) begin
                    // capture input
                    misoReg <= misoWire;
                end else begin
                    // shift output
                    if (tickCount == 0) begin
                        // but never on the first tick
                    end else begin
                        shiftReg <= {shiftReg[6:0], misoReg};
                    end
                end
            end
        end else begin
            miniTickCount <= nextMiniTickCount;
        end
    endrule

    method Action setSclkDiv(Bit#(16) d) if (ncsReg == 1);
        sclkDiv <= d;
    endmethod
    method Action setNcs(Bit#(1) new_ncs);
        ncsReg <= new_ncs;
    endmethod
    method Action setCpol(Bit#(1) new_cpol) if (ncsReg == 1);
        cpol <= new_cpol;
    endmethod
    method Action setCpha(Bit#(1) new_cpha) if (ncsReg == 1);
        cpha <= new_cpha;
    endmethod

    method Bool isChipSelectEnabled();
        return ncsReg == 0;
    endmethod

    method Action put(Bit#(8) x) if (!running);
        resultReady <= False;
        running <= True;
        tickCount <= 0;
        miniTickCount <= 0;
        shiftReg <= x;
    endmethod
    method ActionValue#(Bit#(8)) get() if (resultReady);
        resultReady <= False;
        return shiftReg;
    endmethod

    interface SPIMasterPins pins;
        method Bit#(1) sclk;
            return sclkReg;
        endmethod
        method Bit#(1) mosi;
            return running ? shiftReg[7] : 1;
        endmethod
        method Action miso(Bit#(1) x);
            misoWire <= x;
        endmethod
        method Bit#(1) ncs;
            return ncsReg;
        endmethod
        interface Clock deleteme_unused_clock = clock;
    endinterface
endmodule

// This is a simple SPI Master module.
// This is sever;y

// For information about SPI, check wikipedia:
//   https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus

(* always_ready, always_enabled *)
interface SPIMasterPins;
    // serial clock
    (* prefix = "", result = "spi_sclk" *)
    method Bit#(1) sclk;
    // master-out slave-in
    (* prefix = "", result = "spi_mosi" *)
    method Bit#(1) mosi;
    // master-in slave-out
    (* prefix = "" *)
    method Action miso((* port = "spi_miso" *)Bit#(1) x);
    // active-low chip select
    (* prefix = "", result = "spi_ncs" *)
    method Bit#(1) ncs;
    interface Clock deleteme_unused_clock;
endinterface

interface SPIMaster;
    // configuration
    method Action setSclkDiv(Bit#(16) d);
    method Action setNcs(Bit#(1) new_ncs);
    // Warning: mkSPIMaster untested for cpol == 1
    method Action setCpol(Bit#(1) new_cpol); // idle value of clock
    // Warning: mkSPIMaster untesetd for cpha == 1
    method Action setCpha(Bit#(1) new_cpha); // which clock transition captures data
                                             // cpha = 0 => odd transitions (1st, 3rd, etc.)
                                             // cpha = 1 => even transitions (2nd, 4th, etc.)
    // status
    method Bool isChipSelectEnabled();
    // data
    method Action put(Bit#(8) x);
    method ActionValue#(Bit#(8)) get();
    // pins
    (* prefix = "" *)
    interface SPIMasterPins pins;
endinterface

module mkSPIMaster(SPIMaster);
    let clock <- exposeCurrentClock();
    // registers for the interface pins
    Reg#(Bit#(1)) sclkReg <- mkReg(0);
    Reg#(Bit#(16)) sclkDiv <- mkReg(1);
    Wire#(Bit#(1)) misoWire <- mkDWire(0);
    Reg#(Bit#(1)) misoReg <- mkReg(0);
    Reg#(Bit#(1)) ncsReg <- mkReg(1);
    // MSB gets shifted out
    Reg#(Bit#(8)) shiftReg <- mkReg(0);

    // SPI configuration
    Reg#(Bit#(1)) cpol <- mkReg(0);
    Reg#(Bit#(1)) cpha <- mkReg(0);

    // 17 ticks per SPI cycle, between each tick is a clock transition
    Reg#(Bool) running <- mkReg(False);
    Reg#(Bool) resultReady <- mkReg(False);
    Reg#(Bit#(5)) tickCount <- mkReg(0);
    // sclkReg determines how many mini ticks make up a tick
    Reg#(Bit#(16)) miniTickCount <- mkReg(0);

    (* fire_when_enabled, no_implicit_conditions *)
    rule run(running);
        let nextMiniTickCount = miniTickCount + 1;
        if ((nextMiniTickCount == sclkDiv) || sclkDiv == 0) begin
            miniTickCount <= 0;
            if (tickCount == 16) begin
                // done
                running <= False;
                resultReady <= True;
                tickCount <= 0;
            end else begin
                // tick clock
                sclkReg <= ~sclkReg;
                // increment tickCount
                tickCount <= tickCount + 1;
                // either capture input or shift output
                if (tickCount[0] == cpha) begin
                    // capture input
                    misoReg <= misoWire;
                end else begin
                    // shift output
                    if (tickCount == 0) begin
                        // but never on the first tick
                    end else begin
                        shiftReg <= {shiftReg[6:0], misoReg};
                    end
                end
            end
        end else begin
            miniTickCount <= nextMiniTickCount;
        end
    endrule

    method Action setSclkDiv(Bit#(16) d) if (ncsReg == 1);
        sclkDiv <= d;
    endmethod
    method Action setNcs(Bit#(1) new_ncs);
        ncsReg <= new_ncs;
    endmethod
    method Action setCpol(Bit#(1) new_cpol) if (ncsReg == 1);
        cpol <= new_cpol;
    endmethod
    method Action setCpha(Bit#(1) new_cpha) if (ncsReg == 1);
        cpha <= new_cpha;
    endmethod

    method Bool isChipSelectEnabled();
        return ncsReg == 0;
    endmethod

    method Action put(Bit#(8) x) if (!running);
        resultReady <= False;
        running <= True;
        tickCount <= 0;
        miniTickCount <= 0;
        shiftReg <= x;
    endmethod
    method ActionValue#(Bit#(8)) get() if (resultReady);
        resultReady <= False;
        return shiftReg;
    endmethod

    interface SPIMasterPins pins;
        method Bit#(1) sclk;
            return sclkReg;
        endmethod
        method Bit#(1) mosi;
            return running ? shiftReg[7] : 1;
        endmethod
        method Action miso(Bit#(1) x);
            misoWire <= x;
        endmethod
        method Bit#(1) ncs;
            return ncsReg;
        endmethod
        interface Clock deleteme_unused_clock = clock;
    endinterface
endmodule


connect zynq mpsoc interrupt line

connect zynq mpsoc interrupt line

// 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.
`include "ConnectalProjectConfig.bsv"
import BuildVector::*;
import Clocks::*;
import DefaultValue::*;
import GetPut::*;
import Connectable::*;
import ConnectableWithTrace::*;
import Bscan::*;
import Vector::*;
import XilinxCells::*;
import ConnectalXilinxCells::*;
import ConnectalClocks::*;
import AxiMasterSlave::*;
import Axi4MasterSlave::*;
import AxiDma::*;
import AxiBits::*;
import MemTypes::*;
import Platform::*;
import ZYNQ_ULTRA::*;

(* always_ready, always_enabled *)
interface Bidir#(numeric type data_width);
    method Action             i(Bit#(data_width) v);
    method Bit#(data_width)   o();
    method Bit#(data_width)   t();
endinterface

interface ZynqPins;
endinterface

interface PS8LIB;
    (* prefix="" *)
    interface Vector#(1, PsultraMaxigp)     m_axi_gp;
    method Action                             interrupt(Bit#(1) v);
    interface Vector#(4, Clock) plclk;
    interface Clock portalClock;
    interface Reset portalReset;
    interface Clock derivedClock;
    interface Reset derivedReset;
endinterface

module mkPS8LIB#(Clock axiClock)(PS8LIB);
   // B2C converts a bit to a clock, enabling us to break the apparent cycle
   Vector#(4, B2C) b2c <- replicateM(mkB2C());

   // need the bufg here to reduce clock skew
   module mkBufferedClock#(Integer i)(Clock); let c <- mkClockBUFG(clocked_by b2c[i].c); return c; endmodule
   module mkBufferedReset#(Integer i)(Reset); let r <- mkResetBUFG(clocked_by b2c[i].c, reset_by b2c[i].r); return r; endmodule
   Vector#(4, Clock) fclk <- genWithM(mkBufferedClock);
   Vector#(4, Reset) freset <- genWithM(mkBufferedReset);

`ifndef TOP_SOURCES_PORTAL_CLOCK
   Clock single_clock = fclk[0];
`ifdef ZYNQ_NO_RESET
   freset[0]          = noReset;
`endif
   let single_reset   = freset[0];
`else
   //Clock axiClockBuf <- mkClockBUFG(clocked_by axiClock);
   Clock axiClockBuf = axiClock;
   Clock single_clock = axiClockBuf;
   Reset axiResetUnbuffered <- mkSyncReset(10, freset[0], single_clock);
   Reset axiReset <- mkResetBUFG(clocked_by axiClockBuf, reset_by axiResetUnbuffered);
   let single_reset   = axiReset;
`endif

   ClockGenerator7Params clockParams = defaultValue;
   // input clock 200MHz for speed grade -2, 100MHz for speed grade -1
   // fpll needs to be in the range 600MHz - 1200MHz for either input clock
   //
   // fclkin = 1e9 / mainClockPeriod
   // fpll = 1e9 = mult_f * 1e9 / mainClockPeriod
   // mult_f = mainClockPeriod
   //
   // fclkout0 = 1e9 / divide_f = 1e9 / derivedClockPeriod
   // divide_f = derivedClockPeriod
   //
   clockParams.clkfbout_mult_f       = mainClockPeriod;
   clockParams.clkfbout_phase     = 0.0;
   clockParams.clkfbout_phase     = 0.0;
   clockParams.clkin1_period      = mainClockPeriod;
   clockParams.clkout0_divide_f   = derivedClockPeriod;
   clockParams.clkout0_duty_cycle = 0.5;
   clockParams.clkout0_phase      = 0.0000;
   clockParams.clkout0_buffer     = True;
   clockParams.clkin_buffer = False;
   ClockGenerator7   clockGen <- mkClockGenerator7(clockParams, clocked_by single_clock, reset_by single_reset);
   let derived_clock = clockGen.clkout0;
   let derived_reset_unbuffered <- mkSyncReset(10, single_reset, derived_clock);
   let derived_reset <- mkResetBUFG(clocked_by derived_clock, reset_by derived_reset_unbuffered);

   ZYNQ_ULTRA::PS8 psu <- ZYNQ_ULTRA::mkPS8(single_clock, single_clock);

   // this rule connects the pl_clk wires to the clock net via B2C
   for (Integer i = 0; i < 1; i = i + 1) begin
      ReadOnly#(Bit#(1)) fclkb;
      ReadOnly#(Bit#(1)) fclkresetnb;
      fclkb       <- mkNullCrossingWire(b2c[i].c, psu.pl.clk0);
      fclkresetnb <- mkNullCrossingWire(b2c[i].c, psu.pl.resetn0);
`ifndef BSV_POSITIVE_RESET
      let resetValue = 0;
`else
      let resetValue = 1;
`endif
      rule b2c_rule1;
	 b2c[i].inputclock(fclkb[i]);
	 b2c[i].inputreset(fclkresetnb[i] == 0 ? resetValue : ~resetValue);
      endrule
   end

    interface m_axi_gp = vec(psu.maxigp0);
    interface plclk = fclk;
`ifndef TOP_SOURCES_PORTAL_CLOCK
    interface portalClock = fclk[0];
    interface portalReset = freset[0];
`else
    interface portalClock = axiClockBuf;
    interface portalReset = axiReset;
`endif
    interface derivedClock = derived_clock;
    interface derivedReset = derived_reset;
    method Action interrupt(Bit#(1) v);
       psu.pl.ps_irq0(v);
    endmethod
endmodule

interface PsultraAruser;
    method Action      aruser(Bit#(5) v);
    method Action      awuser(Bit#(5) v);
endinterface

instance ToAxi4MasterBits#(Axi4MasterBits#(40,128,16,PsultraAruser), PsultraMaxigp);
function Axi4MasterBits#(40,128,16,PsultraAruser) toAxi4MasterBits(PsultraMaxigp m);
   return (interface Axi4MasterBits#(40,128,16,PsultraAruser);
      method araddr = m.araddr;
	   method arburst = m.arburst;
	   method arcache = m.arcache;
           method aresetn = 0;
	   method arid = m.arid;
	   method arlen = m.arlen;
	   method arlock = extend(m.arlock);
	   method arprot = m.arprot;
	   method arqos = m.arqos;
	   method arready = m.arready;
	   method arsize = m.arsize;
	   method arvalid = m.arvalid;
	   method awaddr = m.awaddr;
	   method awburst = m.awburst;
	   method awcache = m.awcache;
	   method awid = m.awid;
	   method awlen = m.awlen;
	   method awlock = extend(m.awlock);
	   method awprot = m.awprot;
	   method awqos = m.awqos;
	   method awready = m.awready;
	   method awsize = m.awsize;
	   method awvalid = m.awvalid;
	   method bid = m.bid;
	   method bready = m.bready;
	   method bresp = m.bresp;
	   method bvalid = m.bvalid;
	   method rdata = m.rdata;
	   method rid = m.rid;
	   method rlast = m.rlast;
	   method rready = m.rready;
	   method rresp = m.rresp;
	   method rvalid = m.rvalid;
	   method wdata = m.wdata;
	   //method wid = m.wid;
	   method wlast = m.wlast;
	   method wready = m.wready;
	   method wstrb = m.wstrb;
	   method wvalid = m.wvalid;
	 interface extra = ?;
	 endinterface);
   endfunction: toAxi4MasterBits
endinstance

instance ConnectableWithTrace#(PS8LIB, Platform, traceType);
   module mkConnectionWithTrace#(PS8LIB psu, Platform top, traceType readout)(Empty);
      Axi4MasterBits#(40,128,16,PsultraAruser) master = toAxi4MasterBits(psu.m_axi_gp[0]);
      PhysMemMaster#(32,32) physMemMaster <- mkPhysMemMaster(master);
      mkConnection(physMemMaster, top.slave);
   endmodule
endinstance

// 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.
`include "ConnectalProjectConfig.bsv"
import BuildVector::*;
import Clocks::*;
import DefaultValue::*;
import GetPut::*;
import Connectable::*;
import ConnectableWithTrace::*;
import Bscan::*;
import Vector::*;
import XilinxCells::*;
import ConnectalXilinxCells::*;
import ConnectalClocks::*;
import AxiMasterSlave::*;
import Axi4MasterSlave::*;
import AxiDma::*;
import AxiBits::*;
import MemTypes::*;
import Platform::*;
import ZYNQ_ULTRA::*;

(* always_ready, always_enabled *)
interface Bidir#(numeric type data_width);
    method Action             i(Bit#(data_width) v);
    method Bit#(data_width)   o();
    method Bit#(data_width)   t();
endinterface

interface ZynqPins;
endinterface

interface PS8LIB;
    (* prefix="" *)
    interface Vector#(1, PsultraMaxigp)     m_axi_gp;
    method Action                             interrupt(Bit#(1) v);
    interface Vector#(4, Clock) plclk;
    interface Clock portalClock;
    interface Reset portalReset;
    interface Clock derivedClock;
    interface Reset derivedReset;
endinterface

module mkPS8LIB#(Clock axiClock)(PS8LIB);
   // B2C converts a bit to a clock, enabling us to break the apparent cycle
   Vector#(4, B2C) b2c <- replicateM(mkB2C());

   // need the bufg here to reduce clock skew
   module mkBufferedClock#(Integer i)(Clock); let c <- mkClockBUFG(clocked_by b2c[i].c); return c; endmodule
   module mkBufferedReset#(Integer i)(Reset); let r <- mkResetBUFG(clocked_by b2c[i].c, reset_by b2c[i].r); return r; endmodule
   Vector#(4, Clock) fclk <- genWithM(mkBufferedClock);
   Vector#(4, Reset) freset <- genWithM(mkBufferedReset);

`ifndef TOP_SOURCES_PORTAL_CLOCK
   Clock single_clock = fclk[0];
`ifdef ZYNQ_NO_RESET
   freset[0]          = noReset;
`endif
   let single_reset   = freset[0];
`else
   //Clock axiClockBuf <- mkClockBUFG(clocked_by axiClock);
   Clock axiClockBuf = axiClock;
   Clock single_clock = axiClockBuf;
   Reset axiResetUnbuffered <- mkSyncReset(10, freset[0], single_clock);
   Reset axiReset <- mkResetBUFG(clocked_by axiClockBuf, reset_by axiResetUnbuffered);
   let single_reset   = axiReset;
`endif

   ClockGenerator7Params clockParams = defaultValue;
   // input clock 200MHz for speed grade -2, 100MHz for speed grade -1
   // fpll needs to be in the range 600MHz - 1200MHz for either input clock
   //
   // fclkin = 1e9 / mainClockPeriod
   // fpll = 1e9 = mult_f * 1e9 / mainClockPeriod
   // mult_f = mainClockPeriod
   //
   // fclkout0 = 1e9 / divide_f = 1e9 / derivedClockPeriod
   // divide_f = derivedClockPeriod
   //
   clockParams.clkfbout_mult_f       = mainClockPeriod;
   clockParams.clkfbout_phase     = 0.0;
   clockParams.clkfbout_phase     = 0.0;
   clockParams.clkin1_period      = mainClockPeriod;
   clockParams.clkout0_divide_f   = derivedClockPeriod;
   clockParams.clkout0_duty_cycle = 0.5;
   clockParams.clkout0_phase      = 0.0000;
   clockParams.clkout0_buffer     = True;
   clockParams.clkin_buffer = False;
   ClockGenerator7   clockGen <- mkClockGenerator7(clockParams, clocked_by single_clock, reset_by single_reset);
   let derived_clock = clockGen.clkout0;
   let derived_reset_unbuffered <- mkSyncReset(10, single_reset, derived_clock);
   let derived_reset <- mkResetBUFG(clocked_by derived_clock, reset_by derived_reset_unbuffered);

   ZYNQ_ULTRA::PS8 psu <- ZYNQ_ULTRA::mkPS8(single_clock, single_clock);

   // this rule connects the pl_clk wires to the clock net via B2C
   for (Integer i = 0; i < 1; i = i + 1) begin
      ReadOnly#(Bit#(1)) fclkb;
      ReadOnly#(Bit#(1)) fclkresetnb;
      fclkb       <- mkNullCrossingWire(b2c[i].c, psu.pl.clk0);
      fclkresetnb <- mkNullCrossingWire(b2c[i].c, psu.pl.resetn0);
`ifndef BSV_POSITIVE_RESET
      let resetValue = 0;
`else
      let resetValue = 1;
`endif
      rule b2c_rule1;
	 b2c[i].inputclock(fclkb[i]);
	 b2c[i].inputreset(fclkresetnb[i] == 0 ? resetValue : ~resetValue);
      endrule
   end

    interface m_axi_gp = vec(psu.maxigp0);
    interface plclk = fclk;
`ifndef TOP_SOURCES_PORTAL_CLOCK
    interface portalClock = fclk[0];
    interface portalReset = freset[0];
`else
    interface portalClock = axiClockBuf;
    interface portalReset = axiReset;
`endif
    interface derivedClock = derived_clock;
    interface derivedReset = derived_reset;
    method Action interrupt(Bit#(1) v);
       //psu.irq.f2p({19'b0, v});
    endmethod
endmodule

interface PsultraAruser;
    method Action      aruser(Bit#(5) v);
    method Action      awuser(Bit#(5) v);
endinterface

instance ToAxi4MasterBits#(Axi4MasterBits#(40,128,16,PsultraAruser), PsultraMaxigp);
function Axi4MasterBits#(40,128,16,PsultraAruser) toAxi4MasterBits(PsultraMaxigp m);
   return (interface Axi4MasterBits#(40,128,16,PsultraAruser);
      method araddr = m.araddr;
	   method arburst = m.arburst;
	   method arcache = m.arcache;
           method aresetn = 0;
	   method arid = m.arid;
	   method arlen = m.arlen;
	   method arlock = extend(m.arlock);
	   method arprot = m.arprot;
	   method arqos = m.arqos;
	   method arready = m.arready;
	   method arsize = m.arsize;
	   method arvalid = m.arvalid;
	   method awaddr = m.awaddr;
	   method awburst = m.awburst;
	   method awcache = m.awcache;
	   method awid = m.awid;
	   method awlen = m.awlen;
	   method awlock = extend(m.awlock);
	   method awprot = m.awprot;
	   method awqos = m.awqos;
	   method awready = m.awready;
	   method awsize = m.awsize;
	   method awvalid = m.awvalid;
	   method bid = m.bid;
	   method bready = m.bready;
	   method bresp = m.bresp;
	   method bvalid = m.bvalid;
	   method rdata = m.rdata;
	   method rid = m.rid;
	   method rlast = m.rlast;
	   method rready = m.rready;
	   method rresp = m.rresp;
	   method rvalid = m.rvalid;
	   method wdata = m.wdata;
	   //method wid = m.wid;
	   method wlast = m.wlast;
	   method wready = m.wready;
	   method wstrb = m.wstrb;
	   method wvalid = m.wvalid;
	 interface extra = ?;
	 endinterface);
   endfunction: toAxi4MasterBits
endinstance

instance ConnectableWithTrace#(PS8LIB, Platform, traceType);
   module mkConnectionWithTrace#(PS8LIB psu, Platform top, traceType readout)(Empty);
      Axi4MasterBits#(40,128,16,PsultraAruser) master = toAxi4MasterBits(psu.m_axi_gp[0]);
      PhysMemMaster#(32,32) physMemMaster <- mkPhysMemMaster(master);
      mkConnection(physMemMaster, top.slave);
   endmodule
endinstance


added $display in case burstLen is invalid

Change-Id: I4dd38ee06b869d5b7190af70234f5b36b4632845

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

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

interface MemreadEngine#(numeric type dataWidth);
   method Action start(ObjectPointer pointer, Bit#(ObjectOffsetSize) base, Bit#(32) readLen, Bit#(32) burstLen);
   method ActionValue#(Bool) finish();
   interface ObjectReadClient#(dataWidth) dmaClient;
endinterface

module mkMemreadEngine#(Integer cmdQDepth, FIFOF#(Bit#(dataWidth)) f) (MemreadEngine#(dataWidth))
   provisos (Div#(dataWidth,8,dataWidthBytes),
	     Mul#(dataWidthBytes,8,dataWidth),
	     Log#(dataWidthBytes,beatShift));

   Reg#(Bit#(32))             reqLen <- mkReg(0);
   Reg#(Bit#(32))            respCnt <- mkReg(0);

   Reg#(Bit#(32))                off <- mkReg(0);
   Reg#(Bit#(ObjectOffsetSize)) base <- mkReg(0);

   Reg#(ObjectPointer)       pointer <- mkReg(0);
   Reg#(Bit#(8))            burstLen <- mkReg(0);

   FIFOF#(Bool)                   ff <- mkSizedFIFOF(1);
   FIFO#(Bit#(32))                wf <- mkSizedFIFO(cmdQDepth);

   let beat_shift = fromInteger(valueOf(beatShift));

   method Action start(ObjectPointer p, Bit#(ObjectOffsetSize) b, Bit#(32) rl, Bit#(32) bl) if (off >= reqLen);
      dynamicAssert(bl[31:8]==0, "mkMemreadEngine::start");
      dynamicAssert(bl[7:0]!=0, "mkMemreadEngine::start");
      if (bl[31:8] != 0 || bl[7:0] == 0)
	 $display("MemreadEngine.start burstLen %d out of range [0-255]", bl);
      reqLen   <= rl;
      off      <= 0;
      pointer  <= p;
      burstLen <= truncate(bl);
      base     <= b;
      //$display("mkMemreadEngine.start p=%d b=%d rl=%d beat_shift=%d bl=%d", p, b, rl, beat_shift, bl);
      wf.enq(rl >> beat_shift);
   endmethod

   method ActionValue#(Bool) finish;
      ff.deq;
      return ff.first;
   endmethod

   interface ObjectReadClient dmaClient;
      interface Get readReq;
	 method ActionValue#(ObjectRequest) get() if (off < reqLen);
	    //$display("mkMemreadEngine.dmaClient.readReq: ptr=%d off=%d reqLen=%d burstLen=%d", pointer, off, reqLen, burstLen);
	    off <= off + extend(burstLen);
	    let bl = burstLen;
	    if (off + extend(burstLen) > reqLen)
	       bl = truncate(reqLen - off);
	    return ObjectRequest { pointer: pointer, offset: extend(off)+base, burstLen: bl, tag: 0 };
	 endmethod
      endinterface
      interface Put readData;
	 method Action put(ObjectData#(dataWidth) d);
	    let new_respCnt = respCnt+1;
	    //$display("mkMemreadEngine.dmaClient.readData new_respCnt=%d wf.first=%d", new_respCnt, wf.first);
	    if (new_respCnt == wf.first) begin
	       ff.enq(True);
	       respCnt <= 0;
	       wf.deq;
	       //$display("mkMemreadEngine.dmaClient.readData: %h", new_respCnt);
	    end
	    else begin
	       respCnt <= new_respCnt;
	    end
	    f.enq(d.data);
	 endmethod
      endinterface
   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 Vector::*;
import FIFOF::*;
import FIFO::*;
import GetPut::*;
import Assert::*;

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

interface MemreadEngine#(numeric type dataWidth);
   method Action start(ObjectPointer pointer, Bit#(ObjectOffsetSize) base, Bit#(32) readLen, Bit#(32) burstLen);
   method ActionValue#(Bool) finish();
   interface ObjectReadClient#(dataWidth) dmaClient;
endinterface

module mkMemreadEngine#(Integer cmdQDepth, FIFOF#(Bit#(dataWidth)) f) (MemreadEngine#(dataWidth))
   provisos (Div#(dataWidth,8,dataWidthBytes),
	     Mul#(dataWidthBytes,8,dataWidth),
	     Log#(dataWidthBytes,beatShift));

   Reg#(Bit#(32))             reqLen <- mkReg(0);
   Reg#(Bit#(32))            respCnt <- mkReg(0);

   Reg#(Bit#(32))                off <- mkReg(0);
   Reg#(Bit#(ObjectOffsetSize)) base <- mkReg(0);

   Reg#(ObjectPointer)       pointer <- mkReg(0);
   Reg#(Bit#(8))            burstLen <- mkReg(0);

   FIFOF#(Bool)                   ff <- mkSizedFIFOF(1);
   FIFO#(Bit#(32))                wf <- mkSizedFIFO(cmdQDepth);

   let beat_shift = fromInteger(valueOf(beatShift));

   method Action start(ObjectPointer p, Bit#(ObjectOffsetSize) b, Bit#(32) rl, Bit#(32) bl) if (off >= reqLen);
      dynamicAssert(bl[31:8]==0, "mkMemreadEngine::start");
      reqLen   <= rl;
      off      <= 0;
      pointer  <= p;
      burstLen <= truncate(bl);
      base     <= b;
      //$display("mkMemreadEngine.start p=%d b=%d rl=%d beat_shift=%d", p, b, rl, beat_shift);
      wf.enq(rl >> beat_shift);
   endmethod

   method ActionValue#(Bool) finish;
      ff.deq;
      return ff.first;
   endmethod

   interface ObjectReadClient dmaClient;
      interface Get readReq;
	 method ActionValue#(ObjectRequest) get() if (off < reqLen);
	    //$display("mkMemreadEngine.dmaClient.readReq: %d %h %h", pointer, extend(off)+base, burstLen);
	    off <= off + extend(burstLen);
	    let bl = burstLen;
	    if (off + extend(burstLen) > reqLen)
	       bl = truncate(reqLen - off);
	    return ObjectRequest { pointer: pointer, offset: extend(off)+base, burstLen: bl, tag: 0 };
	 endmethod
      endinterface
      interface Put readData;
	 method Action put(ObjectData#(dataWidth) d);
	    let new_respCnt = respCnt+1;
	    //$display("mkMemreadEngine.dmaClient.readData new_respCnt=%d wf.first=%d", new_respCnt, wf.first);
	    if (new_respCnt == wf.first) begin
	       ff.enq(True);
	       respCnt <= 0;
	       wf.deq;
	       //$display("mkMemreadEngine.dmaClient.readData: %h", new_respCnt);
	    end
	    else begin
	       respCnt <= new_respCnt;
	    end
	    f.enq(d.data);
	 endmethod
      endinterface
   endinterface
endmodule


added mkDualClockBramFIFOF, raw wrapper for Xilinx BRAM

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

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

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

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

import Clocks::*;
import Vector::*;
import FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import CBus::*; // extendNP and truncateNP

import Arith::*;

(* always_ready, always_enabled *)
interface X7FifoSyncMacro#(numeric type data_width);
   method Bit#(1) empty();
   method Bit#(1) full();
   method Action din(Bit#(data_width) v);
   method Action wren(Bit#(1) wren);
   method Bit#(data_width) dout();
   method Action rden(Bit#(1) rden);
   method Bit#(9) wrcount();
   method Bit#(9) rdcount();
endinterface

import "BVI" FIFO_DUALCLOCK_MACRO =
module  vmkBramFifo#(String fifo_size, Clock wrClock, Reset wrReset, Clock rdClock, Reset rdReset)(X7FifoSyncMacro#(data_width));
   let invertReset <- mkResetInverter(wrReset);
   parameter DEVICE = "7SERIES";
   parameter DATA_WIDTH = valueOf(data_width);
   parameter FIFO_SIZE = fifo_size;
   parameter FIRST_WORD_FALL_THROUGH = 1;
   default_clock wrClock(WRCLK) = wrClock;
   default_reset wrReset(RST) = invertReset;
   input_clock rdClock(RDCLK) = rdClock;
   method EMPTY empty() clocked_by (rdClock) reset_by (wrReset);
   method FULL full() clocked_by (wrClock) reset_by (wrReset);
   method din(DI) enable ((*inhigh*)EN_di) clocked_by (wrClock) reset_by (wrReset);
   method wren(WREN) enable ((*inhigh*)EN_wren) clocked_by (wrClock) reset_by (wrReset);
   method DO dout() clocked_by (rdClock) reset_by (wrReset);
   method rden(RDEN) enable ((*inhigh*)EN_rden) clocked_by (rdClock) reset_by (wrReset);
   // wrcount and rdcount ports are needed for xsim
   method WRCOUNT wrcount() clocked_by (wrClock) reset_by (wrReset);
   method RDCOUNT rdcount() clocked_by (rdClock) reset_by (wrReset);
   schedule (empty, full, dout, din, wren, rden, wrcount, rdcount) CF (empty, full, dout, din, wren, rden, wrcount, rdcount);
endmodule

module mkDualClockBramFIFOF#(Clock srcClock, Reset srcReset, Clock dstClock, Reset dstReset)(FIFOF#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   String fifo_size = "36Kb";
   Vector#(TDiv#(sizet,72),X7FifoSyncMacro#(72)) fifos <- replicateM(vmkBramFifo(fifo_size, srcClock, srcReset, dstClock, dstReset));
   Wire#(Bit#(1)) rdenWire <- mkDWire(0);
   Wire#(Bit#(1)) wrenWire <- mkDWire(0);
   Vector#(TDiv#(sizet,72),Wire#(Bit#(72))) dinWires <- replicateM(mkDWire(0));

   for (Integer i = 0; i < valueOf(TDiv#(sizet,72)); i = i+1) begin
      Reg#(Bit#(9)) rdcount <- mkReg(0);
      Reg#(Bit#(9)) wrcount <- mkReg(0);
      rule enables;
	 fifos[i].rden(rdenWire);
	 fifos[i].wren(wrenWire);
      endrule
      rule inputs;
	 fifos[i].din(dinWires[i]);
      endrule
      rule counts;
	 rdcount <= fifos[i].rdcount();
	 wrcount <= fifos[i].wrcount();
      endrule
   end

   function Bool fifoNotEmpty(Integer i); return fifos[i].empty == 0; endfunction
   function Bool fifoNotFull(Integer i); return fifos[i].full == 0; endfunction
   Vector#(TDiv#(sizet,72), Bool) vNotEmpty = genWith(fifoNotEmpty);
   Vector#(TDiv#(sizet,72), Bool) vNotFull = genWith(fifoNotFull);

   method t first() if (fifos[0].empty == 0);
      function Bit#(72) fifoFirst(Integer i); return fifos[i].dout(); endfunction
      Vector#(TDiv#(sizet,72), Bit#(72)) v = genWith(fifoFirst);
      return unpack(truncateNP(pack(v)));
   endmethod
   method Action deq() if (fifos[0].empty == 0);
      rdenWire <= 1;
   endmethod
   method notEmpty = (fifos[0].empty == 0);
   method Action enq(t v) if (fifos[0].full == 0);
      Vector#(TDiv#(sizet,72), Bit#(72)) vs = unpack(extendNP(pack(v)));
      Vector#(TDiv#(sizet,72), Integer) indices = genVector();
      function Action fifoEnq(Integer i); action dinWires[i] <= vs[i]; endaction endfunction
      mapM_(fifoEnq, indices);
      wrenWire <= 1;
   endmethod
   method notFull = (fifos[0].full == 0);
endmodule

module mkSizedBRAMFIFOF#(Integer m)(FIFOF#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   let clock <- exposeCurrentClock();
   let reset <- exposeCurrentReset();
   let fifo <- mkDualClockBramFIFOF(clock, reset, clock, reset);
   return fifo;
endmodule
module mkSizedBRAMFIFO#(Integer m)(FIFO#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   let clock <- exposeCurrentClock();
   let reset <- exposeCurrentReset();
   let fifo <- mkDualClockBramFIFOF(clock, reset, clock, reset);
   method first = fifo.first;
   method deq = fifo.deq;
   method enq = fifo.enq;
endmodule

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

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

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

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

import Clocks::*;
import Vector::*;
import FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import CBus::*; // extendNP and truncateNP

import Arith::*;

(* always_ready, always_enabled *)
interface X7FifoSyncMacro#(numeric type data_width);
   method Bit#(1) empty();
   method Bit#(1) full();
   method Action din(Bit#(data_width) v);
   method Action wren(Bit#(1) wren);
   method Bit#(data_width) dout();
   method Action rden(Bit#(1) rden);
   method Bit#(9) wrcount();
   method Bit#(9) rdcount();
endinterface

import "BVI" FIFO_DUALCLOCK_MACRO =
module  vmkBramFifo#(Clock wrclk, String fifo_size)(X7FifoSyncMacro#(data_width));
   parameter DEVICE = "7SERIES";
   parameter DATA_WIDTH = valueOf(data_width);
   parameter FIFO_SIZE = fifo_size;
   parameter FIRST_WORD_FALL_THROUGH = 1;
   default_clock clk(RDCLK);
   default_reset rst(RST);
   input_clock wrclk(WRCLK) = wrclk;
   method EMPTY empty();
   method FULL full();
   method din(DI) enable ((*inhigh*)EN_di);
   method wren(WREN) enable ((*inhigh*)EN_wren);
   method DO dout();
   method rden(RDEN) enable ((*inhigh*)EN_rden);
   // wrcount and rdcount ports are needed for xsim
   method WRCOUNT wrcount();
   method RDCOUNT rdcount();
   schedule (empty, full, dout, din, wren, rden, wrcount, rdcount) CF (empty, full, dout, din, wren, rden, wrcount, rdcount);
endmodule

module mkSizedBRAMFIFOF#(Integer m)(FIFOF#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   String fifo_size = "36Kb";
   let defaultClock <- exposeCurrentClock;
   let defaultReset <- exposeCurrentReset;
   let invertReset <- mkResetInverter(defaultReset);
   Vector#(TDiv#(sizet,72),X7FifoSyncMacro#(72)) fifos <- replicateM(vmkBramFifo(defaultClock, fifo_size, reset_by invertReset));
   Wire#(Bit#(1)) rdenWire <- mkDWire(0);
   Wire#(Bit#(1)) wrenWire <- mkDWire(0);
   Vector#(TDiv#(sizet,72),Wire#(Bit#(72))) dinWires <- replicateM(mkDWire(0));

   for (Integer i = 0; i < valueOf(TDiv#(sizet,72)); i = i+1) begin
      Reg#(Bit#(9)) rdcount <- mkReg(0);
      Reg#(Bit#(9)) wrcount <- mkReg(0);
      rule enables;
	 fifos[i].rden(rdenWire);
	 fifos[i].wren(wrenWire);
      endrule
      rule inputs;
	 fifos[i].din(dinWires[i]);
      endrule
      rule counts;
	 rdcount <= fifos[i].rdcount();
	 wrcount <= fifos[i].wrcount();
      endrule
   end

   function Bool fifoNotEmpty(Integer i); return fifos[i].empty == 0; endfunction
   function Bool fifoNotFull(Integer i); return fifos[i].full == 0; endfunction
   Vector#(TDiv#(sizet,72), Bool) vNotEmpty = genWith(fifoNotEmpty);
   Vector#(TDiv#(sizet,72), Bool) vNotFull = genWith(fifoNotFull);

   method t first() if (fifos[0].empty == 0);
      function Bit#(72) fifoFirst(Integer i); return fifos[i].dout(); endfunction
      Vector#(TDiv#(sizet,72), Bit#(72)) v = genWith(fifoFirst);
      return unpack(truncateNP(pack(v)));
   endmethod
   method Action deq() if (fifos[0].empty == 0);
      rdenWire <= 1;
   endmethod
   method notEmpty = (fifos[0].empty == 0);
   method Action enq(t v) if (fifos[0].full == 0);
      Vector#(TDiv#(sizet,72), Bit#(72)) vs = unpack(extendNP(pack(v)));
      Vector#(TDiv#(sizet,72), Integer) indices = genVector();
      function Action fifoEnq(Integer i); action dinWires[i] <= vs[i]; endaction endfunction
      mapM_(fifoEnq, indices);
      wrenWire <= 1;
   endmethod
   method notFull = (fifos[0].full == 0);
endmodule

module mkSizedBRAMFIFO#(Integer m)(FIFO#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   let fifo <- mkSizedBRAMFIFOF(m);
   method first = fifo.first;
   method deq = fifo.deq;
   method enq = fifo.enq;
endmodule


clean up

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 Clocks::*;
import Connectable::*;
import DbgDefs::*;
import DbgTypes::*;
import Ethernet::*;
import EthMac::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;
import MemMgmt::*;
import MemTypes::*;
import Pipe::*;
import PacketBuffer::*;
import PktGen::*;
import StoreAndForward::*;
import SharedBuff::*;
import SpecialFIFOs ::*;
import Deparser::*;
import PaxosTypes::*;

interface PktCapChannel;
   method Action start(Bit#(32) iter);
   method Action stop();
   method PktCapRec read_perf_info();
   interface Put#(PacketDataT#(64)) macRx;
endinterface

module mkPktCapChannel#(Clock rxClock, Reset rxReset)(PktCapChannel);
   let verbose = True;
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   Reg#(Bit#(32)) pktCnt <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(32)) totalCnt <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bool) logging <- mkReg(False, clocked_by rxClock, reset_by rxReset);
   Reg#(Bool) log_started <- mkReg(False, clocked_by rxClock, reset_by rxReset);
   Reg#(Bool) log_stopped <- mkReg(False, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) cycle_start <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) data_bytes_start <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) data_bytes_end <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) idle_cycle_start <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) idle_cycle_end <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) total_cycle_start <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) total_cycle_end <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Wire#(Bool) pkt_sop <- mkDWire(False, clocked_by rxClock, reset_by rxReset);

   Reg#(Bit#(64)) data_bytes <- mkSyncReg(0, rxClock, rxReset, defaultClock);
   Reg#(Bit#(64)) idle_cycles <- mkSyncReg(0, rxClock, rxReset, defaultClock);
   Reg#(Bit#(64)) total_cycles <- mkSyncReg(0, rxClock, rxReset, defaultClock);

   StoreAndFwdFromMacToRing macToRing <- mkStoreAndFwdFromMacToRing(rxClock, rxReset, clocked_by rxClock, reset_by rxReset);

   SyncFIFOIfc#(Bit#(32)) pktCapStartSyncFifo <- mkSyncFIFO(4, defaultClock, defaultReset, rxClock);
   SyncFIFOIfc#(void) pktCapStopSyncFifo <- mkSyncFIFO(4, defaultClock, defaultReset, rxClock);

   rule pkt_sink;
      let v <- macToRing.writeClient.writeData.get;
      pkt_sop <= v.sop;
      if (v.sop) begin
         pktCnt <= pktCnt + 1;
         if (verbose) $display("(%0d) packet count %h/%h", $time, pktCnt, totalCnt);
      end
   endrule

   rule snapshot_start_cycle if (logging && !log_started && pkt_sop);
      total_cycle_start <= macToRing.sdbg.total_cycles;
      data_bytes_start <= macToRing.sdbg.data_bytes;
      idle_cycle_start <= macToRing.sdbg.idle_cycles;
      if (verbose) $display("(%0d) snapshot start %h %h %h", $time, macToRing.sdbg.total_cycles, macToRing.sdbg.data_bytes, macToRing.sdbg.idle_cycles);
      log_started <= True;
   endrule

   rule snapshot_end_cycle if (logging && log_started && pktCnt == totalCnt-1);
      total_cycle_end <= macToRing.sdbg.total_cycles;
      data_bytes_end <= macToRing.sdbg.data_bytes;
      idle_cycle_end <= macToRing.sdbg.idle_cycles;
      if (verbose) $display("(%0d) snapshot end %h %h %h", $time, macToRing.sdbg.total_cycles, macToRing.sdbg.data_bytes, macToRing.sdbg.idle_cycles);
      log_started <= False;
      logging <= False;
   endrule

   rule r_start;
      let v <- toGet(pktCapStartSyncFifo).get;
      totalCnt <= v;
      logging <= True;
   endrule

   rule r_stop;
      let v <- toGet(pktCapStopSyncFifo).get;
      log_started <= False;
      logging <= False;
   endrule

   rule r_perf_info;
      data_bytes <= data_bytes_end - data_bytes_start;
      idle_cycles <= idle_cycle_end - idle_cycle_start;
      total_cycles <= total_cycle_end - total_cycle_start;
   endrule

   method Action start(Bit#(32) iter);
      pktCapStartSyncFifo.enq(iter);
   endmethod
   method Action stop();
      pktCapStopSyncFifo.enq(?);
   endmethod
   method PktCapRec read_perf_info();
      return PktCapRec {data_bytes: data_bytes,
                        idle_cycles: idle_cycles,
                        total_cycles: total_cycles};
   endmethod
   interface macRx = macToRing.macRx;
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 Clocks::*;
import Connectable::*;
import DbgDefs::*;
import DbgTypes::*;
import Ethernet::*;
import EthMac::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;
import MemMgmt::*;
import MemTypes::*;
import Pipe::*;
import PacketBuffer::*;
import PktGen::*;
import StoreAndForward::*;
import SharedBuff::*;
import SpecialFIFOs ::*;
import Deparser::*;
import PaxosTypes::*;

interface PktCapChannel;
   method Action start(Bit#(32) iter);
   method Action stop();
   method PktCapRec read_perf_info();
   interface Put#(PacketDataT#(64)) macRx;
endinterface

module mkPktCapChannel#(Clock rxClock, Reset rxReset)(PktCapChannel);
   let verbose = True;
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   Reg#(Bit#(32)) pktCnt <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(32)) totalCnt <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bool) logging <- mkReg(False, clocked_by rxClock, reset_by rxReset);
   Reg#(Bool) log_started <- mkReg(False, clocked_by rxClock, reset_by rxReset);
   Reg#(Bool) log_stopped <- mkReg(False, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) cycle_start <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) data_bytes_start <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) data_bytes_end <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) idle_cycle_start <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) idle_cycle_end <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) total_cycle_start <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) total_cycle_end <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Wire#(Bool) pkt_sop <- mkDWire(False, clocked_by rxClock, reset_by rxReset);

   Reg#(Bit#(64)) data_bytes <- mkSyncReg(0, rxClock, rxReset, defaultClock);
   Reg#(Bit#(64)) idle_cycles <- mkSyncReg(0, rxClock, rxReset, defaultClock);
   Reg#(Bit#(64)) total_cycles <- mkSyncReg(0, rxClock, rxReset, defaultClock);

   StoreAndFwdFromMacToRing macToRing <- mkStoreAndFwdFromMacToRing(rxClock, rxReset, clocked_by rxClock, reset_by rxReset);

   SyncFIFOIfc#(Bit#(32)) pktCapStartSyncFifo <- mkSyncFIFO(4, defaultClock, defaultReset, rxClock);
   SyncFIFOIfc#(void) pktCapStopSyncFifo <- mkSyncFIFO(4, defaultClock, defaultReset, rxClock);

   rule pkt_sink;
      let v <- macToRing.writeClient.writeData.get;
      pkt_sop <= v.sop;
      if (v.sop) begin
         pktCnt <= pktCnt + 1;
         if (verbose) $display("$(%0d) packet count %h/%h", $time, pktCnt, totalCnt);
      end
   endrule

   rule snapshot_start_cycle if (logging && !log_started && pkt_sop);
      total_cycle_start <= macToRing.sdbg.total_cycles;
      data_bytes_start <= macToRing.sdbg.data_bytes;
      idle_cycle_start <= macToRing.sdbg.idle_cycles;
      if (verbose) $display("(%0d) snapshot start %h %h %h", $time, macToRing.sdbg.total_cycles, macToRing.sdbg.data_bytes, macToRing.sdbg.idle_cycles);
      log_started <= True;
   endrule

   rule snapshot_end_cycle if (logging && log_started && pktCnt == totalCnt-1);
      total_cycle_end <= macToRing.sdbg.total_cycles;
      data_bytes_end <= macToRing.sdbg.data_bytes;
      idle_cycle_end <= macToRing.sdbg.idle_cycles;
      if (verbose) $display("(%0d) snapshot end %h %h %h", $time, macToRing.sdbg.total_cycles, macToRing.sdbg.data_bytes, macToRing.sdbg.idle_cycles);
      log_started <= False;
      logging <= False;
   endrule

   rule r_start;
      let v <- toGet(pktCapStartSyncFifo).get;
      totalCnt <= v;
      logging <= True;
   endrule

   rule r_stop;
      let v <- toGet(pktCapStopSyncFifo).get;
      log_started <= False;
      logging <= False;
   endrule

   rule r_perf_info;
      data_bytes <= data_bytes_end - data_bytes_start;
      idle_cycles <= idle_cycle_end - idle_cycle_start;
      total_cycles <= total_cycle_end - total_cycle_start;
   endrule

   method Action start(Bit#(32) iter);
      pktCapStartSyncFifo.enq(iter);
   endmethod
   method Action stop();
      pktCapStopSyncFifo.enq(?);
   endmethod
   method PktCapRec read_perf_info();
      return PktCapRec {data_bytes: data_bytes,
                        idle_cycles: idle_cycles,
                        total_cycles: total_cycles};
   endmethod
   interface macRx = macToRing.macRx;
endmodule