split rx and tx

split rx and tx

// 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 ELink::*;
import AxiMasterSlave::*;
import AxiBits::*;
import AxiGather::*;

interface ParallellaPins;
   interface Par_txi txi;
   interface Par_txo txo;
   interface Par_rxi rxi;
   interface Par_rxo rxo;
endinterface

interface ParallellaLib;
   interface ParallellaPins pins;
   interface AxiSlaveCommon#(32,32,12,Empty) maxi;  // this will connect to a master
   interface AxiMasterCommon#(32,64,6) saxi;  // this will connect to a slave
   interface Par_misc misc;
endinterface

// 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 ELink::*;
import AxiMasterSlave::*;
import AxiBits::*;
import AxiGather::*;

interface ParallellaPins;
   interface Par_tx tx;
   interface Par_rx rx;
endinterface

interface ParallellaLib;
   interface ParallellaPins pins;
   interface AxiSlaveCommon#(32,32,12,Empty) maxi;  // this will connect to a master
   interface AxiMasterCommon#(32,64,6) saxi;  // this will connect to a slave
   interface Par_misc misc;
endinterface


added declaration of typeclass ConnectableWithClocks

Change-Id: I4beb64cff6e27d41ef95a0579b6e7d407c808e56

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

////////////////////////////////////////////////////////////////////////////////
/// Typeclass Definition
////////////////////////////////////////////////////////////////////////////////
typeclass ConnectableWithClocks#(type a, type b);
   module mkConnectionWithClocks#(a x1, b x2, Clock fastClock, Reset fastReset, Clock slowClock, Reset slowReset)(Empty);
endtypeclass

instance ConnectableWithClocks#(Get#(a), Put#(a)) provisos (Bits#(a, awidth));
   module mkConnectionWithClocks#(Get#(a) in, Put#(a) out,
                                  Clock inClock, Reset inReset,
                                  Clock outClock, Reset outReset)(Empty) provisos (Bits#(a, awidth));
       SyncFIFOIfc#(a) synchronizer <- mkSyncFIFO(1, inClock, inReset, outClock);
       rule doGet;
           let v <- in.get();
	   synchronizer.enq(v);
       endrule
       rule doPut;
           let v = synchronizer.first;
	   synchronizer.deq;
	   out.put(v);
       endrule
   endmodule: mkConnectionWithClocks
endinstance: ConnectableWithClocks

module mkClockBinder#(a ifc) (a);
   return ifc;
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 GetPut :: *;
import PCIE :: *; // ConnectableWithClocks
import Clocks :: *;

instance ConnectableWithClocks#(Get#(a), Put#(a)) provisos (Bits#(a, awidth));
   module mkConnectionWithClocks#(Get#(a) in, Put#(a) out,
                                  Clock inClock, Reset inReset,
                                  Clock outClock, Reset outReset)(Empty) provisos (Bits#(a, awidth));
       SyncFIFOIfc#(a) synchronizer <- mkSyncFIFO(1, inClock, inReset, outClock);
       rule doGet;
           let v <- in.get();
	   synchronizer.enq(v);
       endrule
       rule doPut;
           let v = synchronizer.first;
	   synchronizer.deq;
	   out.put(v);
       endrule
   endmodule: mkConnectionWithClocks
endinstance: ConnectableWithClocks

module mkClockBinder#(a ifc) (a);
   return ifc;
endmodule


added fsync to xsvidata

added fsync to xsvidata

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

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

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

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

import FIFO::*;
import GetPut::*;

interface ImageonSpi;
    method Bit#(1) reset();
    method Bit#(16) timing();
    method Action status_busy(Bit#(1) busy);
    method Action status_error(Bit#(1) error);
    method Bit#(1) txfifo_wen();
    method Bit#(32) txfifo_din();
    method Action txfifo_full(Bit#(1) full);
    method Bit#(1) rxfifo_ren();
    method Action rxfifo_dout(Bit#(32) dout);
    method Action rxfifo_empty(Bit#(1) empty);
endinterface

interface ImageonSerdes;
    method Bit#(1) reset();
    method Bit#(1) auto_align();
    method Bit#(1) align_start();
    method Bit#(1) fifo_enable();
    method Bit#(10) manual_tap();
    method Bit#(10) training();
    method Action iserdes_clk_ready(Bit#(1) ready);
    method Action iserdes_clk_status(Bit#(16) status);
    method Action iserdes_align_busy(Bit#(1) busy);
    method Action iserdes_aligned(Bit#(1) aligned);
endinterface

interface ImageonDecoder;
    method Bit#(1) reset();
    method Bit#(1) enable();
    method Bit#(10) code_ls();
    method Bit#(10) code_le();
    method Bit#(10) code_fs();
    method Bit#(10) code_fe();
    method Bit#(10) code_bl();
    method Bit#(10) code_img();
    method Action frame_start(Bit#(1) start);
endinterface

interface ImageonTrigger;
    method Bit#(3) enable();
    method Bit#(32) default_freq();
    method Bit#(32) cnt_trigger0high();
    method Bit#(32) cnt_trigger0low();
endinterface

interface ImageonSyncGen;
    method Bit#(16) delay();
    method Bit#(16) hactive();
    method Bit#(16) hfporch();
    method Bit#(16) hsync();
    method Bit#(16) hbporch();
    method Bit#(16) vactive();
    method Bit#(16) vfporch();
    method Bit#(16) vsync();
    method Bit#(16) vbporch();
endinterface

typedef struct {
    Bit#(1) fsync;
    Bit#(1) vsync;
    Bit#(1) hsync;
    Bit#(1) active_video;
    Bit#(10) video_data;
} XsviData deriving (Bits);

interface ImageonXsvi;
    method Action vsync(Bit#(1) v);
    method Action hsync(Bit#(1) v);
    method Action active_video(Bit#(1) v);
    method Action video_data(Bit#(10) v);
endinterface

(* always_enabled *)
interface ImageonVita;
    method Bit#(1) host_vita_reset();
    method Bit#(1) host_oe();
    method Action fsync(Bit#(1) fsync);
    interface ImageonSpi spi;
    interface ImageonSerdes serdes;
    interface ImageonDecoder decoder;
    interface ImageonTrigger trigger;
    interface ImageonSyncGen syncgen;
    interface ImageonXsvi xsvi;
    method Bit#(32) get_debugreq();
    method Action set_debugind(Bit#(32) v);
endinterface

interface ImageonControl;
    method Action set_spi_control(Bit#(32) v);
    method Bit#(32) get_spi_control();
    method Action set_iserdes_control(Bit#(32) v);
    method Bit#(32) get_iserdes_control();
    method Action set_decoder_control(Bit#(32) v);
    method Bit#(32) get_decoder_control();
    method Action set_triggen_control(Bit#(32) v);
    method Bit#(32) get_triggen_control();

    method Action set_host_vita_reset(Bit#(1) v);
    method Action set_host_oe(Bit#(1) v);

    method Action set_spi_reset(Bit#(1) v);
    method Action set_spi_timing(Bit#(16) v);

    interface Put#(Bit#(32)) txfifo;
    interface Put#(Bit#(32)) rxfifo_request;
    interface Get#(Bit#(32)) rxfifo_response;

    method Action set_serdes_reset(Bit#(1) v);
    method Action set_serdes_auto_align(Bit#(1) v);
    method Action set_serdes_align_start(Bit#(1) v);
    method Action set_serdes_fifo_enable(Bit#(1) v);
    method Action set_serdes_manual_tap(Bit#(10) v);
    method Action set_serdes_training(Bit#(10) v);
    method Action set_decoder_reset(Bit#(1) v);
    method Action set_decoder_enable(Bit#(1) v);
    method Action set_decoder_code_ls(Bit#(10) v);
    method Action set_decoder_code_le(Bit#(10) v);
    method Action set_decoder_code_fs(Bit#(10) v);
    method Action set_decoder_code_fe(Bit#(10) v);
    method Action set_decoder_code_bl(Bit#(10) v);
    method Action set_decoder_code_img(Bit#(10) v);
    method Action set_trigger_enable(Bit#(3) v);
    method Action set_trigger_default_freq(Bit#(32) v);
    method Action set_trigger_cnt_trigger0high(Bit#(32) v);
    method Action set_trigger_cnt_trigger0low(Bit#(32) v);
    method Action set_syncgen_delay(Bit#(16) v);
    method Action set_syncgen_hactive(Bit#(16) v);
    method Action set_syncgen_hfporch(Bit#(16) v);
    method Action set_syncgen_hsync(Bit#(16) v);
    method Action set_syncgen_hbporch(Bit#(16) v);
    method Action set_syncgen_vactive(Bit#(16) v);
    method Action set_syncgen_vfporch(Bit#(16) v);
    method Action set_syncgen_vsync(Bit#(16) v);
    method Action set_syncgen_vbporch(Bit#(16) v);
    method Action set_debugreq(Bit#(32) v);
    method Bit#(32) get_debugind();
    method XsviData xsviData();
endinterface

interface ImageonVitaController;
    interface ImageonVita host;
    interface ImageonControl control;
endinterface

module mkImageonVitaController(ImageonVitaController);

    Reg#(Bit#(1)) host_vita_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) host_oe_reg <- mkReg(0);
    Wire#(Bit#(1)) host_clock_gen_locked_wire <- mkDWire(0);
    Reg#(Bit#(1)) spi_reset_reg <- mkReg(0);
    Reg#(Bit#(16)) spi_timing_reg <- mkReg(0);

    Wire#(Bit#(1)) spi_status_busy_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_status_error_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_txfifo_full_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_txfifo_wen_wire <- mkDWire(0);
    Wire#(Bit#(32)) spi_txfifo_din_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_rxfifo_ren_wire <- mkDWire(0);
    Wire#(Bit#(32)) spi_rxfifo_dout_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_rxfifo_empty_wire <- mkDWire(0);
    Reg#(Bool) spi_rxfifo_requested_reg <- mkReg(False);

    Reg#(Bit#(1)) serdes_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_auto_align_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_align_start_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_fifo_enable_reg <- mkReg(0);
    Reg#(Bit#(10)) serdes_manual_tap_reg <- mkReg(0);
    Reg#(Bit#(10)) serdes_training_reg <- mkReg(0);
    Wire#(Bit#(1)) serdes_clk_ready_wire <- mkDWire(0);
    Wire#(Bit#(16)) serdes_clk_status_wire <- mkDWire(0);
    Wire#(Bit#(1)) serdes_align_busy_wire <- mkDWire(0);
    Wire#(Bit#(1)) serdes_aligned_wire <- mkDWire(0);

    Reg#(Bit#(1)) decoder_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) decoder_enable_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_ls_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_le_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_fs_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_fe_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_bl_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_img_reg <- mkReg(0);
    Wire#(Bit#(1)) decoder_frame_start_wire <- mkDWire(0);
    Wire#(Bit#(10)) decoder_video_data_wire <- mkDWire(0);

    Reg#(Bit#(3)) trigger_enable_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_default_freq_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger0high_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger0low_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_delay_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hactive_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hfporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hsync_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hbporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vactive_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vfporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vsync_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vbporch_reg <- mkReg(0);
    Wire#(Bit#(10)) xsvi_video_data_wire <- mkDWire(0);
    Wire#(Bit#(1))  xsvi_vsync_wire <- mkDWire(0);
    Wire#(Bit#(1))  xsvi_hsync_wire <- mkDWire(0);
    Wire#(Bit#(1))  xsvi_active_video_wire <- mkDWire(0);
    Wire#(Bit#(1))  xsvi_fsync_wire <- mkDWire(0);
    Reg#(Bit#(32)) debugreq_value <- mkReg(0);
    Reg#(Bit#(32)) debugind_value <- mkReg(0);

    interface ImageonVita host;
	method Bit#(1) host_vita_reset();
	    return host_vita_reset_reg;
	endmethod
	method Bit#(1) host_oe();
	    return host_oe_reg;
	endmethod
	method Action fsync(Bit#(1) sync);
	    xsvi_fsync_wire <= sync;
	endmethod
	interface ImageonSpi spi;
	    method Bit#(1) reset();
		return spi_reset_reg;
	    endmethod
	    method Bit#(16) timing();
		return spi_timing_reg;
	    endmethod
	    method Action status_busy(Bit#(1) busy);
	        spi_status_busy_wire <= busy;
	    endmethod
	    method Action status_error(Bit#(1) error);
	        spi_status_error_wire <= error;
	    endmethod
	    method Bit#(1) txfifo_wen();
		return spi_txfifo_wen_wire;
	    endmethod
	    method Bit#(32) txfifo_din();
		return spi_txfifo_din_wire;
	    endmethod
	    method Action txfifo_full(Bit#(1) full);
	        spi_txfifo_full_wire <= full;
	    endmethod
	    method Bit#(1) rxfifo_ren();
		return spi_rxfifo_ren_wire;
	    endmethod
	    method Action rxfifo_dout(Bit#(32) dout);
	        spi_rxfifo_dout_wire <= dout;
	    endmethod
	    method Action rxfifo_empty(Bit#(1) empty);
	        spi_rxfifo_empty_wire <= empty;
	    endmethod
	endinterface
	interface ImageonSerdes serdes;
	    method Bit#(1) reset();
		return serdes_reset_reg;
	    endmethod
	    method Bit#(1) auto_align();
		return serdes_auto_align_reg;
	    endmethod
	    method Bit#(1) align_start();
		return serdes_align_start_reg;
	    endmethod
	    method Bit#(1) fifo_enable();
		return serdes_fifo_enable_reg;
	    endmethod
	    method Bit#(10) manual_tap();
		return serdes_manual_tap_reg;
	    endmethod
	    method Bit#(10) training();
		return serdes_training_reg;
	    endmethod
	    method Action iserdes_clk_ready(Bit#(1) ready);
	        serdes_clk_ready_wire <= ready;
	    endmethod
	    method Action iserdes_clk_status(Bit#(16) status);
	        serdes_clk_status_wire <= status;
	    endmethod
	    method Action iserdes_align_busy(Bit#(1) busy);
	        serdes_align_busy_wire <= busy;
	    endmethod
	    method Action iserdes_aligned(Bit#(1) aligned);
	        serdes_aligned_wire <= aligned;
	    endmethod
	endinterface
	interface ImageonDecoder decoder;
	    method Bit#(1) reset();
		return decoder_reset_reg;
	    endmethod
	    method Bit#(1) enable();
		return decoder_enable_reg;
	    endmethod
	    method Bit#(10) code_ls();
		return decoder_code_ls_reg;
	    endmethod
	    method Bit#(10) code_le();
		return decoder_code_le_reg;
	    endmethod
	    method Bit#(10) code_fs();
		return decoder_code_fs_reg;
	    endmethod
	    method Bit#(10) code_fe();
		return decoder_code_fe_reg;
	    endmethod
	    method Bit#(10) code_bl();
		return decoder_code_bl_reg;
	    endmethod
	    method Bit#(10) code_img();
		return decoder_code_img_reg;
	    endmethod
	    method Action frame_start(Bit#(1) start);
	        decoder_frame_start_wire <= start;
	    endmethod
	endinterface
	interface ImageonTrigger trigger;
	    method Bit#(3) enable();
		return trigger_enable_reg;
	    endmethod
	    method Bit#(32) default_freq();
		return trigger_default_freq_reg;
	    endmethod
	    method Bit#(32) cnt_trigger0high();
		return trigger_cnt_trigger0high_reg;
	    endmethod
	    method Bit#(32) cnt_trigger0low();
		return trigger_cnt_trigger0low_reg;
	    endmethod
	endinterface
	interface ImageonSyncGen syncgen;
	    method Bit#(16) delay();
		return syncgen_delay_reg;
	    endmethod
	    method Bit#(16) hactive();
		return syncgen_hactive_reg;
	    endmethod
	    method Bit#(16) hfporch();
		return syncgen_hfporch_reg;
	    endmethod
	    method Bit#(16) hsync();
		return syncgen_hsync_reg;
	    endmethod
	    method Bit#(16) hbporch();
		return syncgen_hbporch_reg;
	    endmethod
	    method Bit#(16) vactive();
		return syncgen_vactive_reg;
	    endmethod
	    method Bit#(16) vfporch();
		return syncgen_vfporch_reg;
	    endmethod
	    method Bit#(16) vsync();
		return syncgen_vsync_reg;
	    endmethod
	    method Bit#(16) vbporch();
		return syncgen_vbporch_reg;
	    endmethod
	endinterface
	interface ImageonXsvi xsvi;
	    method Action vsync(Bit#(1) v);
	        xsvi_vsync_wire <= v;
	    endmethod
	    method Action hsync(Bit#(1) v);
	        xsvi_hsync_wire <= v;
	    endmethod
	    method Action active_video(Bit#(1) v);
	        xsvi_active_video_wire <= v;
	    endmethod
	    method Action video_data(Bit#(10) v);
	        xsvi_video_data_wire <= v;
	    endmethod
	endinterface
        method Bit#(32) get_debugreq();
            return debugreq_value;
	endmethod
        method Action set_debugind(Bit#(32) v);
            debugind_value <= v;
	endmethod
    endinterface
    interface ImageonControl control;
// SPI_CONTROL
//    [ 0] VITA_RESET
//    [ 1] SPI_RESET
//    [ 8] SPI_STATUS_BUSY
//    [ 9] SPI_STATUS_ERROR
//    [16] SPI_TXFIFO_FULL
//    [24] SPI_RXFIFO_EMPTY
	method Action set_spi_control(Bit#(32) v);
            host_vita_reset_reg <= v[0];
            spi_reset_reg <= v[1];
	endmethod
	method Bit#(32) get_spi_control();
	    let v = 0;
            v[0] = host_vita_reset_reg;
	    v[1] = spi_reset_reg;
	    v[8] = spi_status_busy_wire;
	    v[9] = spi_status_error_wire;
	    v[16] = spi_txfifo_full_wire;
	    v[24] = spi_rxfifo_empty_wire;
	    return v;
	endmethod

// ISERDES_CONTROL
//    [ 0] ISERDES_RESET
//    [ 1] ISERDES_AUTO_ALIGN
//    [ 2] ISERDES_ALIGN_START
//    [ 3] ISERDES_FIFO_ENABLE
//    [ 8] ISERDES_CLK_READY
//    [ 9] ISERDES_ALIGN_BUSY
//    [10] ISERDES_ALIGNED
// [23:16] ISERDES_TXCLK_STATUS
// [31:24] ISERDES_RXCLK_STATUS
	method Action set_iserdes_control(Bit#(32) v);
	    serdes_reset_reg <= v[0];
	    serdes_auto_align_reg <= v[1];
	    serdes_align_start_reg <= v[2];
	    serdes_fifo_enable_reg <= v[3];
	endmethod
	method Bit#(32) get_iserdes_control();
	    let v = 0;
	    v[0] = serdes_reset_reg;
	    v[1] = serdes_auto_align_reg;
	    v[2] = serdes_align_start_reg;
	    v[3] = serdes_fifo_enable_reg;
	    v[8] = serdes_clk_ready_wire;
	    v[9] = serdes_align_busy_wire;
	    v[10] = serdes_aligned_wire;
	    v[31:16] = serdes_clk_status_wire;
	    return v;
	endmethod
// DECODER_CONTROL[7:0]
//    [0] DECODER_RESET
//    [1] DECODER_ENABLE
	method Action set_decoder_control(Bit#(32) v);
	    decoder_reset_reg <= v[0];
	    decoder_enable_reg <= v[1];
	endmethod
	method Bit#(32) get_decoder_control();
	    let v = 0;
	    v[0] = decoder_reset_reg;
	    v[1] = decoder_enable_reg;
	    return v;
	endmethod
// TRIGGEN_CONTROL
// [ 2: 0] TRIGGEN_ENABLE
// [ 6: 4] TRIGGEN_SYNC2READOUT
// [    8] TRIGGEN_READOUTTRIGGER
// [   16] TRIGGEN_EXT_POLARITY
// [   24] TRIGGEN_CNT_UPDATE
// [30:28] TRIGGEN_GEN_POLARITY
	method Action set_triggen_control(Bit#(32) v);
	    trigger_enable_reg <= v[2:0];
	endmethod
	method Bit#(32) get_triggen_control();
	    let v = 0;
	    v[2:0] = trigger_enable_reg;
	    return v;
	endmethod

	method Action set_host_vita_reset(Bit#(1) v);
	    host_vita_reset_reg <= v;
	endmethod
	method Action set_host_oe(Bit#(1) v);
	    host_oe_reg <= v;
	endmethod

	method Action set_spi_reset(Bit#(1) v);
	    spi_reset_reg <= v;
	endmethod
	method Action set_spi_timing(Bit#(16) v);
	    spi_timing_reg <= v;
	endmethod
	interface Put txfifo;
	    method Action put(Bit#(32) v) if (spi_txfifo_full_wire == 0);
	        spi_txfifo_wen_wire <= 1;
		spi_txfifo_din_wire <= v;
	    endmethod
	endinterface
        interface Put rxfifo_request;
	    method Action put(Bit#(32) v) if (!spi_rxfifo_requested_reg && (spi_rxfifo_empty_wire == 0));
	        spi_rxfifo_requested_reg <= True;
		spi_rxfifo_ren_wire <= 1;
	    endmethod
	endinterface
	interface Get rxfifo_response;
	    method ActionValue#(Bit#(32)) get() if (spi_rxfifo_requested_reg);
	        spi_rxfifo_requested_reg <= False;
		return spi_rxfifo_dout_wire;
	    endmethod
	endinterface
	method Action set_serdes_reset(Bit#(1) v);
	    serdes_reset_reg <= v;
	endmethod
	method Action set_serdes_auto_align(Bit#(1) v);
	    serdes_auto_align_reg <= v;
	endmethod
	method Action set_serdes_align_start(Bit#(1) v);
	    serdes_align_start_reg <= v;
	endmethod
	method Action set_serdes_fifo_enable(Bit#(1) v);
	    serdes_fifo_enable_reg <= v;
	endmethod
	method Action set_serdes_manual_tap(Bit#(10) v);
	    serdes_manual_tap_reg <= v;
	endmethod
	method Action set_serdes_training(Bit#(10) v);
	    serdes_training_reg <= v;
	endmethod
	method Action set_decoder_reset(Bit#(1) v);
	    decoder_reset_reg <= v;
	endmethod
	method Action set_decoder_enable(Bit#(1) v);
	    decoder_enable_reg <= v;
	endmethod
	method Action set_decoder_code_ls(Bit#(10) v);
	    decoder_code_ls_reg <= v;
	endmethod
	method Action set_decoder_code_le(Bit#(10) v);
	    decoder_code_le_reg <= v;
	endmethod
	method Action set_decoder_code_fs(Bit#(10) v);
	    decoder_code_fs_reg <= v;
	endmethod
	method Action set_decoder_code_fe(Bit#(10) v);
	    decoder_code_fe_reg <= v;
	endmethod
	method Action set_decoder_code_bl(Bit#(10) v);
	    decoder_code_bl_reg <= v;
	endmethod
	method Action set_decoder_code_img(Bit#(10) v);
	    decoder_code_img_reg <= v;
	endmethod
	method Action set_trigger_enable(Bit#(3) v);
	    trigger_enable_reg <= v;
	endmethod
	method Action set_trigger_default_freq(Bit#(32) v);
	    trigger_default_freq_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger0high(Bit#(32) v);
	    trigger_cnt_trigger0high_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger0low(Bit#(32) v);
	    trigger_cnt_trigger0low_reg <= v;
	endmethod
	method Action set_syncgen_delay(Bit#(16) v);
	    syncgen_delay_reg <= v;
	endmethod
	method Action set_syncgen_hactive(Bit#(16) v);
	    syncgen_hactive_reg <= v;
	endmethod
	method Action set_syncgen_hfporch(Bit#(16) v);
	    syncgen_hfporch_reg <= v;
	endmethod
	method Action set_syncgen_hsync(Bit#(16) v);
	    syncgen_hsync_reg <= v;
	endmethod
	method Action set_syncgen_hbporch(Bit#(16) v);
	    syncgen_hbporch_reg <= v;
	endmethod
	method Action set_syncgen_vactive(Bit#(16) v);
	    syncgen_vactive_reg <= v;
	endmethod
	method Action set_syncgen_vfporch(Bit#(16) v);
	    syncgen_vfporch_reg <= v;
	endmethod
	method Action set_syncgen_vsync(Bit#(16) v);
	    syncgen_vsync_reg <= v;
	endmethod
	method Action set_syncgen_vbporch(Bit#(16) v);
	    syncgen_vbporch_reg <= v;
	endmethod
        method Action set_debugreq(Bit#(32) v);
            debugreq_value <= v;
	endmethod
        method Bit#(32) get_debugind();
            return debugind_value;
	endmethod
	method XsviData xsviData();
	    return XsviData {
	        fsync: xsvi_fsync_wire,
	        vsync: xsvi_vsync_wire,
		hsync: xsvi_hsync_wire,
		active_video: xsvi_active_video_wire,
		video_data: xsvi_video_data_wire
	    };
	endmethod
    endinterface
endmodule

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

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

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

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

import FIFO::*;
import GetPut::*;

interface ImageonSpi;
    method Bit#(1) reset();
    method Bit#(16) timing();
    method Action status_busy(Bit#(1) busy);
    method Action status_error(Bit#(1) error);
    method Bit#(1) txfifo_wen();
    method Bit#(32) txfifo_din();
    method Action txfifo_full(Bit#(1) full);
    method Bit#(1) rxfifo_ren();
    method Action rxfifo_dout(Bit#(32) dout);
    method Action rxfifo_empty(Bit#(1) empty);
endinterface

interface ImageonSerdes;
    method Bit#(1) reset();
    method Bit#(1) auto_align();
    method Bit#(1) align_start();
    method Bit#(1) fifo_enable();
    method Bit#(10) manual_tap();
    method Bit#(10) training();
    method Action iserdes_clk_ready(Bit#(1) ready);
    method Action iserdes_clk_status(Bit#(16) status);
    method Action iserdes_align_busy(Bit#(1) busy);
    method Action iserdes_aligned(Bit#(1) aligned);
endinterface

interface ImageonDecoder;
    method Bit#(1) reset();
    method Bit#(1) enable();
    method Bit#(10) code_ls();
    method Bit#(10) code_le();
    method Bit#(10) code_fs();
    method Bit#(10) code_fe();
    method Bit#(10) code_bl();
    method Bit#(10) code_img();
    method Action frame_start(Bit#(1) start);
endinterface

interface ImageonTrigger;
    method Bit#(3) enable();
    method Bit#(32) default_freq();
    method Bit#(32) cnt_trigger0high();
    method Bit#(32) cnt_trigger0low();
endinterface

interface ImageonSyncGen;
    method Bit#(16) delay();
    method Bit#(16) hactive();
    method Bit#(16) hfporch();
    method Bit#(16) hsync();
    method Bit#(16) hbporch();
    method Bit#(16) vactive();
    method Bit#(16) vfporch();
    method Bit#(16) vsync();
    method Bit#(16) vbporch();
endinterface

typedef struct {
    Bit#(1) vsync;
    Bit#(1) hsync;
    Bit#(1) active_video;
    Bit#(10) video_data;
} XsviData deriving (Bits);

interface ImageonXsvi;
    method Action vsync(Bit#(1) v);
    method Action hsync(Bit#(1) v);
    method Action active_video(Bit#(1) v);
    method Action video_data(Bit#(10) v);
endinterface

(* always_enabled *)
interface ImageonVita;
    method Bit#(1) host_vita_reset();
    method Bit#(1) host_oe();
    method Action fsync(Bit#(1) fsync);
    interface ImageonSpi spi;
    interface ImageonSerdes serdes;
    interface ImageonDecoder decoder;
    interface ImageonTrigger trigger;
    interface ImageonSyncGen syncgen;
    interface ImageonXsvi xsvi;
    method Bit#(32) get_debugreq();
    method Action set_debugind(Bit#(32) v);
endinterface

interface ImageonControl;
    method Action set_spi_control(Bit#(32) v);
    method Bit#(32) get_spi_control();
    method Action set_iserdes_control(Bit#(32) v);
    method Bit#(32) get_iserdes_control();
    method Action set_decoder_control(Bit#(32) v);
    method Bit#(32) get_decoder_control();
    method Action set_triggen_control(Bit#(32) v);
    method Bit#(32) get_triggen_control();

    method Action set_host_vita_reset(Bit#(1) v);
    method Action set_host_oe(Bit#(1) v);

    method Action set_spi_reset(Bit#(1) v);
    method Action set_spi_timing(Bit#(16) v);

    interface Put#(Bit#(32)) txfifo;
    interface Put#(Bit#(32)) rxfifo_request;
    interface Get#(Bit#(32)) rxfifo_response;

    method Action set_serdes_reset(Bit#(1) v);
    method Action set_serdes_auto_align(Bit#(1) v);
    method Action set_serdes_align_start(Bit#(1) v);
    method Action set_serdes_fifo_enable(Bit#(1) v);
    method Action set_serdes_manual_tap(Bit#(10) v);
    method Action set_serdes_training(Bit#(10) v);
    method Action set_decoder_reset(Bit#(1) v);
    method Action set_decoder_enable(Bit#(1) v);
    method Action set_decoder_code_ls(Bit#(10) v);
    method Action set_decoder_code_le(Bit#(10) v);
    method Action set_decoder_code_fs(Bit#(10) v);
    method Action set_decoder_code_fe(Bit#(10) v);
    method Action set_decoder_code_bl(Bit#(10) v);
    method Action set_decoder_code_img(Bit#(10) v);
    method Action set_trigger_enable(Bit#(3) v);
    method Action set_trigger_default_freq(Bit#(32) v);
    method Action set_trigger_cnt_trigger0high(Bit#(32) v);
    method Action set_trigger_cnt_trigger0low(Bit#(32) v);
    method Action set_syncgen_delay(Bit#(16) v);
    method Action set_syncgen_hactive(Bit#(16) v);
    method Action set_syncgen_hfporch(Bit#(16) v);
    method Action set_syncgen_hsync(Bit#(16) v);
    method Action set_syncgen_hbporch(Bit#(16) v);
    method Action set_syncgen_vactive(Bit#(16) v);
    method Action set_syncgen_vfporch(Bit#(16) v);
    method Action set_syncgen_vsync(Bit#(16) v);
    method Action set_syncgen_vbporch(Bit#(16) v);
    method Action set_debugreq(Bit#(32) v);
    method Bit#(32) get_debugind();
    method XsviData xsviData();
endinterface

interface ImageonVitaController;
    interface ImageonVita host;
    interface ImageonControl control;
endinterface

module mkImageonVitaController(ImageonVitaController);

    Reg#(Bit#(1)) host_vita_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) host_oe_reg <- mkReg(0);
    Wire#(Bit#(1)) host_clock_gen_locked_wire <- mkDWire(0);
    Reg#(Bit#(1)) spi_reset_reg <- mkReg(0);
    Reg#(Bit#(16)) spi_timing_reg <- mkReg(0);

    Wire#(Bit#(1)) spi_status_busy_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_status_error_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_txfifo_full_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_txfifo_wen_wire <- mkDWire(0);
    Wire#(Bit#(32)) spi_txfifo_din_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_rxfifo_ren_wire <- mkDWire(0);
    Wire#(Bit#(32)) spi_rxfifo_dout_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_rxfifo_empty_wire <- mkDWire(0);
    Reg#(Bool) spi_rxfifo_requested_reg <- mkReg(False);

    Reg#(Bit#(1)) serdes_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_auto_align_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_align_start_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_fifo_enable_reg <- mkReg(0);
    Reg#(Bit#(10)) serdes_manual_tap_reg <- mkReg(0);
    Reg#(Bit#(10)) serdes_training_reg <- mkReg(0);
    Wire#(Bit#(1)) serdes_clk_ready_wire <- mkDWire(0);
    Wire#(Bit#(16)) serdes_clk_status_wire <- mkDWire(0);
    Wire#(Bit#(1)) serdes_align_busy_wire <- mkDWire(0);
    Wire#(Bit#(1)) serdes_aligned_wire <- mkDWire(0);

    Reg#(Bit#(1)) decoder_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) decoder_enable_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_ls_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_le_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_fs_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_fe_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_bl_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_img_reg <- mkReg(0);
    Wire#(Bit#(1)) decoder_frame_start_wire <- mkDWire(0);
    Wire#(Bit#(10)) decoder_video_data_wire <- mkDWire(0);

    Reg#(Bit#(3)) remapper_write_cfg_reg <- mkReg(0);
    Reg#(Bit#(3)) remapper_mode_reg <- mkReg(0);
    Reg#(Bit#(3)) trigger_enable_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_default_freq_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger0high_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger0low_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_delay_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hactive_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hfporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hsync_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hbporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vactive_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vfporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vsync_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vbporch_reg <- mkReg(0);
    Reg#(Bit#(32)) vsync_reg <- mkReg(0);
    Reg#(Bit#(32)) hsync_reg <- mkReg(0);
    Reg#(Bit#(32)) active_reg <- mkReg(0);
    Wire#(Bit#(10)) xsvi_video_data_wire <- mkDWire(0);
    Wire#(Bit#(1))  xsvi_vsync_wire <- mkDWire(0);
    Wire#(Bit#(1))  xsvi_hsync_wire <- mkDWire(0);
    Wire#(Bit#(1))  xsvi_active_video_wire <- mkDWire(0);
    Reg#(Bit#(32)) debugreq_value <- mkReg(0);
    Reg#(Bit#(32)) debugind_value <- mkReg(0);

    interface ImageonVita host;
	method Bit#(1) host_vita_reset();
	    return host_vita_reset_reg;
	endmethod
	method Bit#(1) host_oe();
	    return host_oe_reg;
	endmethod
	method Action fsync(Bit#(1) sync);
	endmethod
	interface ImageonSpi spi;
	    method Bit#(1) reset();
		return spi_reset_reg;
	    endmethod
	    method Bit#(16) timing();
		return spi_timing_reg;
	    endmethod
	    method Action status_busy(Bit#(1) busy);
	        spi_status_busy_wire <= busy;
	    endmethod
	    method Action status_error(Bit#(1) error);
	        spi_status_error_wire <= error;
	    endmethod
	    method Bit#(1) txfifo_wen();
		return spi_txfifo_wen_wire;
	    endmethod
	    method Bit#(32) txfifo_din();
		return spi_txfifo_din_wire;
	    endmethod
	    method Action txfifo_full(Bit#(1) full);
	        spi_txfifo_full_wire <= full;
	    endmethod
	    method Bit#(1) rxfifo_ren();
		return spi_rxfifo_ren_wire;
	    endmethod
	    method Action rxfifo_dout(Bit#(32) dout);
	        spi_rxfifo_dout_wire <= dout;
	    endmethod
	    method Action rxfifo_empty(Bit#(1) empty);
	        spi_rxfifo_empty_wire <= empty;
	    endmethod
	endinterface
	interface ImageonSerdes serdes;
	    method Bit#(1) reset();
		return serdes_reset_reg;
	    endmethod
	    method Bit#(1) auto_align();
		return serdes_auto_align_reg;
	    endmethod
	    method Bit#(1) align_start();
		return serdes_align_start_reg;
	    endmethod
	    method Bit#(1) fifo_enable();
		return serdes_fifo_enable_reg;
	    endmethod
	    method Bit#(10) manual_tap();
		return serdes_manual_tap_reg;
	    endmethod
	    method Bit#(10) training();
		return serdes_training_reg;
	    endmethod
	    method Action iserdes_clk_ready(Bit#(1) ready);
	        serdes_clk_ready_wire <= ready;
	    endmethod
	    method Action iserdes_clk_status(Bit#(16) status);
	        serdes_clk_status_wire <= status;
	    endmethod
	    method Action iserdes_align_busy(Bit#(1) busy);
	        serdes_align_busy_wire <= busy;
	    endmethod
	    method Action iserdes_aligned(Bit#(1) aligned);
	        serdes_aligned_wire <= aligned;
	    endmethod
	endinterface
	interface ImageonDecoder decoder;
	    method Bit#(1) reset();
		return decoder_reset_reg;
	    endmethod
	    method Bit#(1) enable();
		return decoder_enable_reg;
	    endmethod
	    method Bit#(10) code_ls();
		return decoder_code_ls_reg;
	    endmethod
	    method Bit#(10) code_le();
		return decoder_code_le_reg;
	    endmethod
	    method Bit#(10) code_fs();
		return decoder_code_fs_reg;
	    endmethod
	    method Bit#(10) code_fe();
		return decoder_code_fe_reg;
	    endmethod
	    method Bit#(10) code_bl();
		return decoder_code_bl_reg;
	    endmethod
	    method Bit#(10) code_img();
		return decoder_code_img_reg;
	    endmethod
	    method Action frame_start(Bit#(1) start);
	        decoder_frame_start_wire <= start;
	    endmethod
	endinterface
	interface ImageonTrigger trigger;
	    method Bit#(3) enable();
		return trigger_enable_reg;
	    endmethod
	    method Bit#(32) default_freq();
		return trigger_default_freq_reg;
	    endmethod
	    method Bit#(32) cnt_trigger0high();
		return trigger_cnt_trigger0high_reg;
	    endmethod
	    method Bit#(32) cnt_trigger0low();
		return trigger_cnt_trigger0low_reg;
	    endmethod
	endinterface
	interface ImageonSyncGen syncgen;
	    method Bit#(16) delay();
		return syncgen_delay_reg;
	    endmethod
	    method Bit#(16) hactive();
		return syncgen_hactive_reg;
	    endmethod
	    method Bit#(16) hfporch();
		return syncgen_hfporch_reg;
	    endmethod
	    method Bit#(16) hsync();
		return syncgen_hsync_reg;
	    endmethod
	    method Bit#(16) hbporch();
		return syncgen_hbporch_reg;
	    endmethod
	    method Bit#(16) vactive();
		return syncgen_vactive_reg;
	    endmethod
	    method Bit#(16) vfporch();
		return syncgen_vfporch_reg;
	    endmethod
	    method Bit#(16) vsync();
		return syncgen_vsync_reg;
	    endmethod
	    method Bit#(16) vbporch();
		return syncgen_vbporch_reg;
	    endmethod
	endinterface
	interface ImageonXsvi xsvi;
	    method Action vsync(Bit#(1) v);
	        xsvi_vsync_wire <= v;
	        if (v == 1)
	            vsync_reg <= vsync_reg + 1;
	    endmethod
	    method Action hsync(Bit#(1) v);
	        xsvi_hsync_wire <= v;
	        if (v == 1)
	            hsync_reg <= hsync_reg + 1;
	    endmethod
	    method Action active_video(Bit#(1) v);
	        xsvi_active_video_wire <= v;
	        if (v == 1)
	            active_reg <= active_reg + 1;
	    endmethod
	    method Action video_data(Bit#(10) v);
	        xsvi_video_data_wire <= v;
	    endmethod
	endinterface
        method Bit#(32) get_debugreq();
            return debugreq_value;
	endmethod
        method Action set_debugind(Bit#(32) v);
            debugind_value <= v;
	endmethod
    endinterface
    interface ImageonControl control;
// SPI_CONTROL
//    [ 0] VITA_RESET
//    [ 1] SPI_RESET
//    [ 8] SPI_STATUS_BUSY
//    [ 9] SPI_STATUS_ERROR
//    [16] SPI_TXFIFO_FULL
//    [24] SPI_RXFIFO_EMPTY
	method Action set_spi_control(Bit#(32) v);
            host_vita_reset_reg <= v[0];
            spi_reset_reg <= v[1];
	endmethod
	method Bit#(32) get_spi_control();
	    let v = 0;
            v[0] = host_vita_reset_reg;
	    v[1] = spi_reset_reg;
	    v[8] = spi_status_busy_wire;
	    v[9] = spi_status_error_wire;
	    v[16] = spi_txfifo_full_wire;
	    v[24] = spi_rxfifo_empty_wire;
	    return v;
	endmethod

// ISERDES_CONTROL
//    [ 0] ISERDES_RESET
//    [ 1] ISERDES_AUTO_ALIGN
//    [ 2] ISERDES_ALIGN_START
//    [ 3] ISERDES_FIFO_ENABLE
//    [ 8] ISERDES_CLK_READY
//    [ 9] ISERDES_ALIGN_BUSY
//    [10] ISERDES_ALIGNED
// [23:16] ISERDES_TXCLK_STATUS
// [31:24] ISERDES_RXCLK_STATUS
	method Action set_iserdes_control(Bit#(32) v);
	    serdes_reset_reg <= v[0];
	    serdes_auto_align_reg <= v[1];
	    serdes_align_start_reg <= v[2];
	    serdes_fifo_enable_reg <= v[3];
	endmethod
	method Bit#(32) get_iserdes_control();
	    let v = 0;
	    v[0] = serdes_reset_reg;
	    v[1] = serdes_auto_align_reg;
	    v[2] = serdes_align_start_reg;
	    v[3] = serdes_fifo_enable_reg;
	    v[8] = serdes_clk_ready_wire;
	    v[9] = serdes_align_busy_wire;
	    v[10] = serdes_aligned_wire;
	    v[31:16] = serdes_clk_status_wire;
	    return v;
	endmethod
// DECODER_CONTROL[7:0]
//    [0] DECODER_RESET
//    [1] DECODER_ENABLE
	method Action set_decoder_control(Bit#(32) v);
	    decoder_reset_reg <= v[0];
	    decoder_enable_reg <= v[1];
	endmethod
	method Bit#(32) get_decoder_control();
	    let v = 0;
	    v[0] = decoder_reset_reg;
	    v[1] = decoder_enable_reg;
	    return v;
	endmethod
// TRIGGEN_CONTROL
// [ 2: 0] TRIGGEN_ENABLE
// [ 6: 4] TRIGGEN_SYNC2READOUT
// [    8] TRIGGEN_READOUTTRIGGER
// [   16] TRIGGEN_EXT_POLARITY
// [   24] TRIGGEN_CNT_UPDATE
// [30:28] TRIGGEN_GEN_POLARITY
	method Action set_triggen_control(Bit#(32) v);
	    trigger_enable_reg <= v[2:0];
	endmethod
	method Bit#(32) get_triggen_control();
	    let v = 0;
	    v[2:0] = trigger_enable_reg;
	    return v;
	endmethod

	method Action set_host_vita_reset(Bit#(1) v);
	    host_vita_reset_reg <= v;
	endmethod
	method Action set_host_oe(Bit#(1) v);
	    host_oe_reg <= v;
	endmethod

	method Action set_spi_reset(Bit#(1) v);
	    spi_reset_reg <= v;
	endmethod
	method Action set_spi_timing(Bit#(16) v);
	    spi_timing_reg <= v;
	endmethod
	interface Put txfifo;
	    method Action put(Bit#(32) v) if (spi_txfifo_full_wire == 0);
	        spi_txfifo_wen_wire <= 1;
		spi_txfifo_din_wire <= v;
	    endmethod
	endinterface
        interface Put rxfifo_request;
	    method Action put(Bit#(32) v) if (!spi_rxfifo_requested_reg && (spi_rxfifo_empty_wire == 0));
	        spi_rxfifo_requested_reg <= True;
		spi_rxfifo_ren_wire <= 1;
	    endmethod
	endinterface
	interface Get rxfifo_response;
	    method ActionValue#(Bit#(32)) get() if (spi_rxfifo_requested_reg);
	        spi_rxfifo_requested_reg <= False;
		return spi_rxfifo_dout_wire;
	    endmethod
	endinterface
	method Action set_serdes_reset(Bit#(1) v);
	    serdes_reset_reg <= v;
	endmethod
	method Action set_serdes_auto_align(Bit#(1) v);
	    serdes_auto_align_reg <= v;
	endmethod
	method Action set_serdes_align_start(Bit#(1) v);
	    serdes_align_start_reg <= v;
	endmethod
	method Action set_serdes_fifo_enable(Bit#(1) v);
	    serdes_fifo_enable_reg <= v;
	endmethod
	method Action set_serdes_manual_tap(Bit#(10) v);
	    serdes_manual_tap_reg <= v;
	endmethod
	method Action set_serdes_training(Bit#(10) v);
	    serdes_training_reg <= v;
	endmethod
	method Action set_decoder_reset(Bit#(1) v);
	    decoder_reset_reg <= v;
	endmethod
	method Action set_decoder_enable(Bit#(1) v);
	    decoder_enable_reg <= v;
	endmethod
	method Action set_decoder_code_ls(Bit#(10) v);
	    decoder_code_ls_reg <= v;
	endmethod
	method Action set_decoder_code_le(Bit#(10) v);
	    decoder_code_le_reg <= v;
	endmethod
	method Action set_decoder_code_fs(Bit#(10) v);
	    decoder_code_fs_reg <= v;
	endmethod
	method Action set_decoder_code_fe(Bit#(10) v);
	    decoder_code_fe_reg <= v;
	endmethod
	method Action set_decoder_code_bl(Bit#(10) v);
	    decoder_code_bl_reg <= v;
	endmethod
	method Action set_decoder_code_img(Bit#(10) v);
	    decoder_code_img_reg <= v;
	endmethod
	method Action set_trigger_enable(Bit#(3) v);
	    trigger_enable_reg <= v;
	endmethod
	method Action set_trigger_default_freq(Bit#(32) v);
	    trigger_default_freq_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger0high(Bit#(32) v);
	    trigger_cnt_trigger0high_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger0low(Bit#(32) v);
	    trigger_cnt_trigger0low_reg <= v;
	endmethod
	method Action set_syncgen_delay(Bit#(16) v);
	    syncgen_delay_reg <= v;
	endmethod
	method Action set_syncgen_hactive(Bit#(16) v);
	    syncgen_hactive_reg <= v;
	endmethod
	method Action set_syncgen_hfporch(Bit#(16) v);
	    syncgen_hfporch_reg <= v;
	endmethod
	method Action set_syncgen_hsync(Bit#(16) v);
	    syncgen_hsync_reg <= v;
	endmethod
	method Action set_syncgen_hbporch(Bit#(16) v);
	    syncgen_hbporch_reg <= v;
	endmethod
	method Action set_syncgen_vactive(Bit#(16) v);
	    syncgen_vactive_reg <= v;
	endmethod
	method Action set_syncgen_vfporch(Bit#(16) v);
	    syncgen_vfporch_reg <= v;
	endmethod
	method Action set_syncgen_vsync(Bit#(16) v);
	    syncgen_vsync_reg <= v;
	endmethod
	method Action set_syncgen_vbporch(Bit#(16) v);
	    syncgen_vbporch_reg <= v;
	endmethod
        method Action set_debugreq(Bit#(32) v);
            debugreq_value <= v;
	endmethod
        method Bit#(32) get_debugind();
            return debugind_value;
	endmethod
	method XsviData xsviData();
	    return XsviData {
	        vsync: xsvi_vsync_wire,
		hsync: xsvi_hsync_wire,
		active_video: xsvi_active_video_wire,
		video_data: xsvi_video_data_wire
	    };
	endmethod
    endinterface
endmodule


for loop -> genWith

for loop -> genWith

// Copyright (C) 2012 Muralidaran Vijayaraghavan <vmurali@csail.mit.edu>

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

/*
Comments: This EHR design generates the following scheduling constraints (forall i):
forall j >= i, r[i] < w[j]
forall j < i, r[i] > w[j]
forall j > i, w[i] < w[j]
w[i] conflicts with w[i]
forall j, r[i] is conflict free with r[j]
*/

import Vector::*;
import RWire::*;

typedef  Vector#(n, Reg#(t)) Ehr#(numeric type n, type t);

module mkEhr#(t init)(Ehr#(n, t)) provisos(Bits#(t, tSz));
  Vector#(n, RWire#(t)) lat <- replicateM(mkUnsafeRWire);

  Vector#(n, Vector#(n, RWire#(Maybe#(t)))) dummy <- replicateM(replicateM(mkUnsafeRWire));
  Vector#(n, Reg#(Bool)) dummy2 <- replicateM(mkReg(True));

  Reg#(t) rl <- mkReg(init);

  rule canon;
    t upd = rl;
    for(Integer i = 0; i < valueOf(n); i = i + 1)
      if(lat[i].wget matches tagged Valid .x)
        upd = x;
    rl <= upd;
  endrule

   function Reg#(t) genEhr(Integer i);
      return (interface Reg;
	 method Action _write(t x);
	    lat[i].wset(x);
	    dummy2[i] <= True;
	    for(Integer j = 0; j < i; j = j + 1)
	       dummy[i][j].wset(lat[j].wget);
         endmethod

	 method t _read;
	    t upd = rl;
	    Bool yes = True;
	    for(Integer j = i; j < valueOf(n); j = j + 1)
	       yes = yes && dummy2[j];
	    for(Integer j = 0; j < i; j = j + 1)
	       begin
                  if(lat[j].wget matches tagged Valid .x)
                     upd = x;
	       end
	    return yes? upd : ?;
         endmethod
	 endinterface);
   endfunction

   Ehr#(n, t) r = genWith(genEhr);

   return r;
endmodule

// Copyright (C) 2012 Muralidaran Vijayaraghavan <vmurali@csail.mit.edu>

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

/*
Comments: This EHR design generates the following scheduling constraints (forall i):
forall j >= i, r[i] < w[j]
forall j < i, r[i] > w[j]
forall j > i, w[i] < w[j]
w[i] conflicts with w[i]
forall j, r[i] is conflict free with r[j]
*/

import Vector::*;
import RWire::*;

typedef  Vector#(n, Reg#(t)) Ehr#(numeric type n, type t);

module mkEhr#(t init)(Ehr#(n, t)) provisos(Bits#(t, tSz));
  Vector#(n, RWire#(t)) lat <- replicateM(mkUnsafeRWire);

  Vector#(n, Vector#(n, RWire#(Maybe#(t)))) dummy <- replicateM(replicateM(mkUnsafeRWire));
  Vector#(n, Reg#(Bool)) dummy2 <- replicateM(mkReg(True));

  Reg#(t) rl <- mkReg(init);

  Ehr#(n, t) r = newVector;

  rule canon;
    t upd = rl;
    for(Integer i = 0; i < valueOf(n); i = i + 1)
      if(lat[i].wget matches tagged Valid .x)
        upd = x;
    rl <= upd;
  endrule

  for(Integer i = 0; i < valueOf(n); i = i + 1)
    r[i] = (interface Reg;
              method Action _write(t x);
                lat[i].wset(x);
                dummy2[i] <= True;
                for(Integer j = 0; j < i; j = j + 1)
                  dummy[i][j].wset(lat[j].wget);
              endmethod

              method t _read;
                t upd = rl;
                Bool yes = True;
                for(Integer j = i; j < valueOf(n); j = j + 1)
                  yes = yes && dummy2[j];
                for(Integer j = 0; j < i; j = j + 1)
                begin
                  if(lat[j].wget matches tagged Valid .x)
                    upd = x;
                end
                return yes? upd : ?;
              endmethod
            endinterface);

   return r;
endmodule


removed unused dmaErrorFifo

removed unused dmaErrorFifo

Change-Id: I795ef76189de2c6fd740c825afafa781dddde657

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

// BSV Libraries
import FIFO::*;
import Vector::*;
import List::*;
import GetPut::*;
import ClientServer::*;
import Assert::*;
import StmtFSM::*;

// CONNECTAL Libraries
import MemTypes::*;
import ConnectalMemory::*;
import MMU::*;
import MemServerInternal::*;

function Put#(t) null_put();
   return (interface Put;
              method Action put(t x) if (False);
                 noAction;
              endmethod
           endinterface);
endfunction

function Get#(t) null_get();
   return (interface Get;
              method ActionValue#(t) get() if (False);
                 return ?;
              endmethod
           endinterface);
endfunction

function  PhysMemWriteClient#(addrWidth, busWidth) null_mem_write_client();
   return (interface PhysMemWriteClient;
              interface Get writeReq = null_get;
              interface Get writeData = null_get;
              interface Put writeDone = null_put;
           endinterface);
endfunction

function  PhysMemReadClient#(addrWidth, busWidth) null_mem_read_client();
   return (interface PhysMemReadClient;
              interface Get readReq = null_get;
              interface Put readData = null_put;
           endinterface);
endfunction

interface MemServer#(numeric type addrWidth, numeric type dataWidth, numeric type nMasters);
   interface DmaDebugRequest request;
   interface Vector#(nMasters,PhysMemMaster#(addrWidth, dataWidth)) masters;
endinterface

typedef struct {
   DmaErrorType errorType;
   Bit#(32) pref;
   } DmaError deriving (Bits);

module mkMemServerRW#(DmaDebugIndication dmaIndication,
		      Vector#(numReadClients, MemReadClient#(dataWidth)) readClients,
		      Vector#(numWriteClients, MemWriteClient#(dataWidth)) writeClients,
		      Vector#(numMMUs,MMU#(PhysAddrWidth)) mmus)
   (MemServer#(PhysAddrWidth, dataWidth, nMasters))

   provisos (Add#(1,a__,dataWidth),
	     Mul#(TDiv#(dataWidth, 8), 8, dataWidth),
	     Mul#(nwc, nMasters, numWriteClients),
	     Mul#(nrc, nMasters, numReadClients),
	     Add#(b__, TLog#(nrc), 6),
	     Add#(c__, TLog#(nwc), 6),
	     Add#(TLog#(TDiv#(dataWidth, 8)), d__, BurstLenSize)
	     );

   MemServer#(PhysAddrWidth,dataWidth,nMasters) reader <- mkMemServerR(dmaIndication,  readClients, mmus);
   MemServer#(PhysAddrWidth,dataWidth,nMasters) writer <- mkMemServerW(dmaIndication, writeClients, mmus);

   function PhysMemMaster#(PhysAddrWidth,dataWidth) mkm(Integer i) = (interface PhysMemMaster#(PhysAddrWidth,dataWidth);
								 interface PhysMemReadClient read_client = reader.masters[i].read_client;
								 interface PhysMemWriteClient write_client = writer.masters[i].write_client;
							      endinterface);

   interface DmaDebugRequest request;
      method Action getStateDbg(ChannelType rc);
	 if (rc == Read)
	    reader.request.getStateDbg(rc);
	 else
	    writer.request.getStateDbg(rc);
      endmethod
      method Action getMemoryTraffic(ChannelType rc);
	 if (rc == Read)
	    reader.request.getMemoryTraffic(rc);
	 else
	    writer.request.getMemoryTraffic(rc);
      endmethod
      method Action addrRequest(Bit#(32) pointer, Bit#(32) offset);
	 writer.request.addrRequest(pointer,offset);
      endmethod
   endinterface
   interface masters = map(mkm,genVector);
endmodule

module mkMemServerR#(DmaDebugIndication dmaIndication,
		     Vector#(numReadClients, MemReadClient#(dataWidth)) readClients,
		     Vector#(numMMUs,MMU#(PhysAddrWidth)) mmus)
   (MemServer#(PhysAddrWidth, dataWidth, nMasters))

   provisos (Add#(1,a__,dataWidth),
	     Mul#(TDiv#(dataWidth, 8), 8, dataWidth),
	     Mul#(nrc, nMasters, numReadClients),
	     Add#(b__, TLog#(nrc), 6),
	     Add#(TLog#(TDiv#(dataWidth, 8)), c__, BurstLenSize)
	     );

   FIFO#(Bit#(32))   addrReqFifo <- mkFIFO;
   Reg#(Bit#(8)) dbgPtr <- mkReg(0);
   Reg#(Bit#(8)) trafficPtr <- mkReg(0);
   Reg#(Bit#(64)) trafficAccum <- mkReg(0);

   function a selectClient(Vector#(n, a) in, Integer r, Integer i, Integer j); return in[j * r + i]; endfunction
   function Vector#(nrc, a) selectClients(Vector#(numReadClients, a) vec, Integer m);
      return genWith(selectClient(vec, valueOf(nMasters), m));
   endfunction
   Vector#(nMasters,Vector#(nrc, MemReadClient#(dataWidth))) client_bins = genWith(selectClients(readClients));

   module foo#(Integer i) (MMUAddrServer#(PhysAddrWidth,nMasters));
      let rv <- mkMMUAddrServer(mmus[i].addr[0]);
      return rv;
   endmodule
   Vector#(numMMUs,MMUAddrServer#(PhysAddrWidth,nMasters)) mmu_servers <- mapM(foo,genVector);

   Vector#(nMasters,MemReadInternal#(PhysAddrWidth,dataWidth)) readers;
   for(Integer i = 0; i < valueOf(nMasters); i = i+1) begin
      Vector#(numMMUs,Server#(ReqTup,Bit#(PhysAddrWidth))) ss;
      for(Integer j = 0; j < valueOf(numMMUs); j=j+1)
	 ss[j] = mmu_servers[j].servers[i];
      readers[i] <- mkMemReadInternal(client_bins[i], dmaIndication, ss);
   end

   rule mmuEntry;
      addrReqFifo.deq;
      let physAddr <- mmus[addrReqFifo.first[31:16]].addr[0].response.get;
      dmaIndication.addrResponse(zeroExtend(physAddr));
   endrule

   function PhysMemMaster#(PhysAddrWidth,dataWidth) mkm(Integer i) = (interface PhysMemMaster#(PhysAddrWidth,dataWidth);
								 interface PhysMemReadClient read_client = readers[i].read_client;
								 interface PhysMemWriteClient write_client = null_mem_write_client;
							      endinterface);

   Stmt dbgStmt = seq
		     for(dbgPtr <= 0; dbgPtr < fromInteger(valueOf(nMasters)); dbgPtr <= dbgPtr+1)
			(action
			    let rv <- readers[dbgPtr].dbg.dbg;
			    dmaIndication.reportStateDbg(rv);
			 endaction);
		  endseq;
   FSM dbgFSM <- mkFSM(dbgStmt);

   Stmt trafficStmt = seq
			 trafficAccum <= 0;
			 for(trafficPtr <= 0; trafficPtr < fromInteger(valueOf(nMasters)); trafficPtr <= trafficPtr+1)
			    (action
				let rv <- readers[trafficPtr].dbg.getMemoryTraffic();
				trafficAccum <= trafficAccum + rv;
			     endaction);
			 dmaIndication.reportMemoryTraffic(trafficAccum);
		      endseq;
   FSM trafficFSM <- mkFSM(trafficStmt);

   interface DmaDebugRequest request;
      method Action getStateDbg(ChannelType rc);
	 if (rc == Read)
	    dbgFSM.start;
      endmethod
      method Action getMemoryTraffic(ChannelType rc);
	 if (rc == Read)
	    trafficFSM.start;
      endmethod
      method Action addrRequest(Bit#(32) pointer, Bit#(32) offset);
	 addrReqFifo.enq(pointer);
	 mmus[pointer[31:16]].addr[0].request.put(ReqTup{id:truncate(pointer), off:extend(offset)});
      endmethod
   endinterface
   interface masters = map(mkm,genVector);
endmodule

module mkMemServerW#(DmaDebugIndication dmaIndication,
		     Vector#(numWriteClients, MemWriteClient#(dataWidth)) writeClients,
		     Vector#(numMMUs,MMU#(PhysAddrWidth)) mmus)
   (MemServer#(PhysAddrWidth, dataWidth, nMasters))

   provisos (Add#(1,a__,dataWidth),
	     Mul#(TDiv#(dataWidth, 8), 8, dataWidth),
	     Mul#(nwc, nMasters, numWriteClients),
	     Add#(b__, TLog#(nwc), 6)
	     );

   FIFO#(Bit#(32))   addrReqFifo <- mkFIFO;
   Reg#(Bit#(8)) dbgPtr <- mkReg(0);
   Reg#(Bit#(8)) trafficPtr <- mkReg(0);
   Reg#(Bit#(64)) trafficAccum <- mkReg(0);

   function a selectClient(Vector#(n, a) in, Integer r, Integer i, Integer j); return in[j * r + i]; endfunction
   function Vector#(nwc, a) selectClients(Vector#(numWriteClients, a) vec, Integer m);
      return genWith(selectClient(vec, valueOf(nMasters), m));
   endfunction
   Vector#(nMasters,Vector#(nwc, MemWriteClient#(dataWidth))) client_bins = genWith(selectClients(writeClients));

   module foo#(Integer i) (MMUAddrServer#(PhysAddrWidth,nMasters));
      let rv <- mkMMUAddrServer(mmus[i].addr[1]);
      return rv;
   endmodule
   Vector#(numMMUs,MMUAddrServer#(PhysAddrWidth,nMasters)) mmu_servers <- mapM(foo,genVector);

   Vector#(nMasters,MemWriteInternal#(PhysAddrWidth,dataWidth)) writers;
   for(Integer i = 0; i < valueOf(nMasters); i = i+1) begin
      Vector#(numMMUs,Server#(ReqTup,Bit#(PhysAddrWidth))) ss;
      for(Integer j = 0; j < valueOf(numMMUs); j=j+1)
	 ss[j] = mmu_servers[j].servers[i];
      writers[i] <- mkMemWriteInternal(client_bins[i], dmaIndication, ss);
   end

   rule mmuEntry;
      addrReqFifo.deq;
      let physAddr <- mmus[addrReqFifo.first[31:16]].addr[1].response.get;
      dmaIndication.addrResponse(zeroExtend(physAddr));
   endrule

   function PhysMemMaster#(PhysAddrWidth,dataWidth) mkm(Integer i) = (interface PhysMemMaster#(PhysAddrWidth,dataWidth);
								 interface PhysMemReadClient read_client = null_mem_read_client;
								 interface PhysMemWriteClient write_client = writers[i].write_client;
							      endinterface);

   Stmt dbgStmt = seq
		     for(dbgPtr <= 0; dbgPtr < fromInteger(valueOf(nMasters)); dbgPtr <= dbgPtr+1)
			(action
			    let rv <- writers[dbgPtr].dbg.dbg;
			    dmaIndication.reportStateDbg(rv);
			 endaction);
		  endseq;
   FSM dbgFSM <- mkFSM(dbgStmt);

   Stmt trafficStmt = seq
			 trafficAccum <= 0;
			 for(trafficPtr <= 0; trafficPtr < fromInteger(valueOf(nMasters)); trafficPtr <= trafficPtr+1)
			    (action
				let rv <- writers[trafficPtr].dbg.getMemoryTraffic();
				trafficAccum <= trafficAccum + rv;
			     endaction);
			 dmaIndication.reportMemoryTraffic(trafficAccum);
		      endseq;
   FSM trafficFSM <- mkFSM(trafficStmt);

   interface DmaDebugRequest request;
      method Action getStateDbg(ChannelType rc);
	 if (rc == Write)
	    dbgFSM.start;
      endmethod
      method Action getMemoryTraffic(ChannelType rc);
	 if (rc == Write)
	    trafficFSM.start;
      endmethod
      method Action addrRequest(Bit#(32) pointer, Bit#(32) offset);
	 addrReqFifo.enq(pointer);
	 mmus[pointer[31:16]].addr[1].request.put(ReqTup{id:truncate(pointer), off:extend(offset)});
      endmethod
   endinterface
   interface masters = map(mkm,genVector);
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.

// BSV Libraries
import FIFO::*;
import Vector::*;
import List::*;
import GetPut::*;
import ClientServer::*;
import Assert::*;
import StmtFSM::*;

// CONNECTAL Libraries
import MemTypes::*;
import ConnectalMemory::*;
import MMU::*;
import MemServerInternal::*;

function Put#(t) null_put();
   return (interface Put;
              method Action put(t x) if (False);
                 noAction;
              endmethod
           endinterface);
endfunction

function Get#(t) null_get();
   return (interface Get;
              method ActionValue#(t) get() if (False);
                 return ?;
              endmethod
           endinterface);
endfunction

function  PhysMemWriteClient#(addrWidth, busWidth) null_mem_write_client();
   return (interface PhysMemWriteClient;
              interface Get writeReq = null_get;
              interface Get writeData = null_get;
              interface Put writeDone = null_put;
           endinterface);
endfunction

function  PhysMemReadClient#(addrWidth, busWidth) null_mem_read_client();
   return (interface PhysMemReadClient;
              interface Get readReq = null_get;
              interface Put readData = null_put;
           endinterface);
endfunction

interface MemServer#(numeric type addrWidth, numeric type dataWidth, numeric type nMasters);
   interface DmaDebugRequest request;
   interface Vector#(nMasters,PhysMemMaster#(addrWidth, dataWidth)) masters;
endinterface

typedef struct {
   DmaErrorType errorType;
   Bit#(32) pref;
   } DmaError deriving (Bits);

module mkMemServerRW#(DmaDebugIndication dmaIndication,
		      Vector#(numReadClients, MemReadClient#(dataWidth)) readClients,
		      Vector#(numWriteClients, MemWriteClient#(dataWidth)) writeClients,
		      Vector#(numMMUs,MMU#(PhysAddrWidth)) mmus)
   (MemServer#(PhysAddrWidth, dataWidth, nMasters))

   provisos (Add#(1,a__,dataWidth),
	     Mul#(TDiv#(dataWidth, 8), 8, dataWidth),
	     Mul#(nwc, nMasters, numWriteClients),
	     Mul#(nrc, nMasters, numReadClients),
	     Add#(b__, TLog#(nrc), 6),
	     Add#(c__, TLog#(nwc), 6),
	     Add#(TLog#(TDiv#(dataWidth, 8)), d__, BurstLenSize)
	     );

   MemServer#(PhysAddrWidth,dataWidth,nMasters) reader <- mkMemServerR(dmaIndication,  readClients, mmus);
   MemServer#(PhysAddrWidth,dataWidth,nMasters) writer <- mkMemServerW(dmaIndication, writeClients, mmus);

   FIFO#(DmaError) dmaErrorFifo <- mkFIFO();
   rule dmaError;
      let error <- toGet(dmaErrorFifo).get();
      dmaIndication.error(extend(pack(error.errorType)), error.pref, 0, 0);
   endrule

   function PhysMemMaster#(PhysAddrWidth,dataWidth) mkm(Integer i) = (interface PhysMemMaster#(PhysAddrWidth,dataWidth);
								 interface PhysMemReadClient read_client = reader.masters[i].read_client;
								 interface PhysMemWriteClient write_client = writer.masters[i].write_client;
							      endinterface);

   interface DmaDebugRequest request;
      method Action getStateDbg(ChannelType rc);
	 if (rc == Read)
	    reader.request.getStateDbg(rc);
	 else
	    writer.request.getStateDbg(rc);
      endmethod
      method Action getMemoryTraffic(ChannelType rc);
	 if (rc == Read)
	    reader.request.getMemoryTraffic(rc);
	 else
	    writer.request.getMemoryTraffic(rc);
      endmethod
      method Action addrRequest(Bit#(32) pointer, Bit#(32) offset);
	 writer.request.addrRequest(pointer,offset);
      endmethod
   endinterface
   interface masters = map(mkm,genVector);
endmodule

module mkMemServerR#(DmaDebugIndication dmaIndication,
		     Vector#(numReadClients, MemReadClient#(dataWidth)) readClients,
		     Vector#(numMMUs,MMU#(PhysAddrWidth)) mmus)
   (MemServer#(PhysAddrWidth, dataWidth, nMasters))

   provisos (Add#(1,a__,dataWidth),
	     Mul#(TDiv#(dataWidth, 8), 8, dataWidth),
	     Mul#(nrc, nMasters, numReadClients),
	     Add#(b__, TLog#(nrc), 6),
	     Add#(TLog#(TDiv#(dataWidth, 8)), c__, BurstLenSize)
	     );

   FIFO#(Bit#(32))   addrReqFifo <- mkFIFO;
   Reg#(Bit#(8)) dbgPtr <- mkReg(0);
   Reg#(Bit#(8)) trafficPtr <- mkReg(0);
   Reg#(Bit#(64)) trafficAccum <- mkReg(0);

   function a selectClient(Vector#(n, a) in, Integer r, Integer i, Integer j); return in[j * r + i]; endfunction
   function Vector#(nrc, a) selectClients(Vector#(numReadClients, a) vec, Integer m);
      return genWith(selectClient(vec, valueOf(nMasters), m));
   endfunction
   Vector#(nMasters,Vector#(nrc, MemReadClient#(dataWidth))) client_bins = genWith(selectClients(readClients));

   module foo#(Integer i) (MMUAddrServer#(PhysAddrWidth,nMasters));
      let rv <- mkMMUAddrServer(mmus[i].addr[0]);
      return rv;
   endmodule
   Vector#(numMMUs,MMUAddrServer#(PhysAddrWidth,nMasters)) mmu_servers <- mapM(foo,genVector);

   Vector#(nMasters,MemReadInternal#(PhysAddrWidth,dataWidth)) readers;
   for(Integer i = 0; i < valueOf(nMasters); i = i+1) begin
      Vector#(numMMUs,Server#(ReqTup,Bit#(PhysAddrWidth))) ss;
      for(Integer j = 0; j < valueOf(numMMUs); j=j+1)
	 ss[j] = mmu_servers[j].servers[i];
      readers[i] <- mkMemReadInternal(client_bins[i], dmaIndication, ss);
   end

   rule mmuEntry;
      addrReqFifo.deq;
      let physAddr <- mmus[addrReqFifo.first[31:16]].addr[0].response.get;
      dmaIndication.addrResponse(zeroExtend(physAddr));
   endrule

   function PhysMemMaster#(PhysAddrWidth,dataWidth) mkm(Integer i) = (interface PhysMemMaster#(PhysAddrWidth,dataWidth);
								 interface PhysMemReadClient read_client = readers[i].read_client;
								 interface PhysMemWriteClient write_client = null_mem_write_client;
							      endinterface);

   Stmt dbgStmt = seq
		     for(dbgPtr <= 0; dbgPtr < fromInteger(valueOf(nMasters)); dbgPtr <= dbgPtr+1)
			(action
			    let rv <- readers[dbgPtr].dbg.dbg;
			    dmaIndication.reportStateDbg(rv);
			 endaction);
		  endseq;
   FSM dbgFSM <- mkFSM(dbgStmt);

   Stmt trafficStmt = seq
			 trafficAccum <= 0;
			 for(trafficPtr <= 0; trafficPtr < fromInteger(valueOf(nMasters)); trafficPtr <= trafficPtr+1)
			    (action
				let rv <- readers[trafficPtr].dbg.getMemoryTraffic();
				trafficAccum <= trafficAccum + rv;
			     endaction);
			 dmaIndication.reportMemoryTraffic(trafficAccum);
		      endseq;
   FSM trafficFSM <- mkFSM(trafficStmt);

   FIFO#(DmaError) dmaErrorFifo <- mkFIFO();
   rule dmaError;
      let error <- toGet(dmaErrorFifo).get();
      dmaIndication.error(extend(pack(error.errorType)), error.pref, 0, 0);
   endrule

   interface DmaDebugRequest request;
      method Action getStateDbg(ChannelType rc);
	 if (rc == Read)
	    dbgFSM.start;
      endmethod
      method Action getMemoryTraffic(ChannelType rc);
	 if (rc == Read)
	    trafficFSM.start;
      endmethod
      method Action addrRequest(Bit#(32) pointer, Bit#(32) offset);
	 addrReqFifo.enq(pointer);
	 mmus[pointer[31:16]].addr[0].request.put(ReqTup{id:truncate(pointer), off:extend(offset)});
      endmethod
   endinterface
   interface masters = map(mkm,genVector);
endmodule

module mkMemServerW#(DmaDebugIndication dmaIndication,
		     Vector#(numWriteClients, MemWriteClient#(dataWidth)) writeClients,
		     Vector#(numMMUs,MMU#(PhysAddrWidth)) mmus)
   (MemServer#(PhysAddrWidth, dataWidth, nMasters))

   provisos (Add#(1,a__,dataWidth),
	     Mul#(TDiv#(dataWidth, 8), 8, dataWidth),
	     Mul#(nwc, nMasters, numWriteClients),
	     Add#(b__, TLog#(nwc), 6)
	     );

   FIFO#(Bit#(32))   addrReqFifo <- mkFIFO;
   Reg#(Bit#(8)) dbgPtr <- mkReg(0);
   Reg#(Bit#(8)) trafficPtr <- mkReg(0);
   Reg#(Bit#(64)) trafficAccum <- mkReg(0);

   function a selectClient(Vector#(n, a) in, Integer r, Integer i, Integer j); return in[j * r + i]; endfunction
   function Vector#(nwc, a) selectClients(Vector#(numWriteClients, a) vec, Integer m);
      return genWith(selectClient(vec, valueOf(nMasters), m));
   endfunction
   Vector#(nMasters,Vector#(nwc, MemWriteClient#(dataWidth))) client_bins = genWith(selectClients(writeClients));

   module foo#(Integer i) (MMUAddrServer#(PhysAddrWidth,nMasters));
      let rv <- mkMMUAddrServer(mmus[i].addr[1]);
      return rv;
   endmodule
   Vector#(numMMUs,MMUAddrServer#(PhysAddrWidth,nMasters)) mmu_servers <- mapM(foo,genVector);

   Vector#(nMasters,MemWriteInternal#(PhysAddrWidth,dataWidth)) writers;
   for(Integer i = 0; i < valueOf(nMasters); i = i+1) begin
      Vector#(numMMUs,Server#(ReqTup,Bit#(PhysAddrWidth))) ss;
      for(Integer j = 0; j < valueOf(numMMUs); j=j+1)
	 ss[j] = mmu_servers[j].servers[i];
      writers[i] <- mkMemWriteInternal(client_bins[i], dmaIndication, ss);
   end

   rule mmuEntry;
      addrReqFifo.deq;
      let physAddr <- mmus[addrReqFifo.first[31:16]].addr[1].response.get;
      dmaIndication.addrResponse(zeroExtend(physAddr));
   endrule

   function PhysMemMaster#(PhysAddrWidth,dataWidth) mkm(Integer i) = (interface PhysMemMaster#(PhysAddrWidth,dataWidth);
								 interface PhysMemReadClient read_client = null_mem_read_client;
								 interface PhysMemWriteClient write_client = writers[i].write_client;
							      endinterface);

   Stmt dbgStmt = seq
		     for(dbgPtr <= 0; dbgPtr < fromInteger(valueOf(nMasters)); dbgPtr <= dbgPtr+1)
			(action
			    let rv <- writers[dbgPtr].dbg.dbg;
			    dmaIndication.reportStateDbg(rv);
			 endaction);
		  endseq;
   FSM dbgFSM <- mkFSM(dbgStmt);

   Stmt trafficStmt = seq
			 trafficAccum <= 0;
			 for(trafficPtr <= 0; trafficPtr < fromInteger(valueOf(nMasters)); trafficPtr <= trafficPtr+1)
			    (action
				let rv <- writers[trafficPtr].dbg.getMemoryTraffic();
				trafficAccum <= trafficAccum + rv;
			     endaction);
			 dmaIndication.reportMemoryTraffic(trafficAccum);
		      endseq;
   FSM trafficFSM <- mkFSM(trafficStmt);

   FIFO#(DmaError) dmaErrorFifo <- mkFIFO();
   rule dmaError;
      let error <- toGet(dmaErrorFifo).get();
      dmaIndication.error(extend(pack(error.errorType)), error.pref, 0, 0);
   endrule

   interface DmaDebugRequest request;
      method Action getStateDbg(ChannelType rc);
	 if (rc == Write)
	    dbgFSM.start;
      endmethod
      method Action getMemoryTraffic(ChannelType rc);
	 if (rc == Write)
	    trafficFSM.start;
      endmethod
      method Action addrRequest(Bit#(32) pointer, Bit#(32) offset);
	 addrReqFifo.enq(pointer);
	 mmus[pointer[31:16]].addr[1].request.put(ReqTup{id:truncate(pointer), off:extend(offset)});
      endmethod
   endinterface
   interface masters = map(mkm,genVector);
endmodule


fix build error on MemInitIfc

fix build error on MemInitIfc

/*

Copyright (C) 2012

Arvind <arvind@csail.mit.edu>
Muralidaran Vijayaraghavan <vmurali@csail.mit.edu>

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 Types::*;
import FShow::*;
import MemTypes::*;

// cpu to host data type
typedef enum {
    ExitCode = 2'd0,
    PrintChar = 2'd1,
    PrintIntLow = 2'd2,
    PrintIntHigh = 2'd3
} CpuToHostType deriving(Bits, Eq, FShow);

typedef struct {
    CpuToHostType c2hType;
    Bit#(16) data;
} CpuToHostData deriving(Bits, Eq, FShow);

interface Proc;
    method ActionValue#(CpuToHostData) cpuToHost;
    method Action hostToCpu(Addr startpc);
endinterface

// general purpose reg index
typedef Bit#(5) RIndx;

// opcode
typedef Bit#(7) Opcode;
Opcode opLoad    = 7'b0000011;
Opcode opMiscMem = 7'b0001111;
Opcode opOpImm   = 7'b0010011;
Opcode opAuipc   = 7'b0010111;
Opcode opStore   = 7'b0100011;
Opcode opAmo     = 7'b0101111;
Opcode opOp      = 7'b0110011;
Opcode opLui     = 7'b0110111;
Opcode opBranch  = 7'b1100011;
Opcode opJalr    = 7'b1100111;
Opcode opJal     = 7'b1101111;
Opcode opSystem  = 7'b1110011;

// CSR index
typedef Bit#(12) CsrIndx;
CsrIndx csrInstret = 12'hc02;
CsrIndx csrCycle   = 12'hc00;
CsrIndx csrMhartid = 12'hf10;
CsrIndx csrMdcsr   = 12'h7b0;

// LR, SC, FENCE not implemented
// LB(U), LH(U), SB, SH not implemented

// For CSR, only following two are implemented
// CSRR rd csr (i.e. CSRRS rd csr x0)
// CSRW csr rs1 (i.e. CSRRW x0 csr rs1)

// SCALL, SBREAK not implemented

typedef enum {
    Unsupported,
    Alu,
    Ld,
    St,
    J,
    Jr,
    Br,
    Csrr,
    Csrw,
    Auipc
} IType deriving(Bits, Eq, FShow);

typedef enum {
    Eq,
    Neq,
    Lt,
    Ltu,
    Ge,
    Geu,
    AT,
    NT
} BrFunc deriving(Bits, Eq, FShow);

typedef enum {
    Add,
    Sub,
    And,
    Or,
    Xor,
    Slt,
    Sltu,
    Sll,
    Sra,
    Srl
} AluFunc deriving(Bits, Eq, FShow);

typedef void Exception;

typedef struct {
    Addr pc;
    Addr nextPc;
    IType brType;
    Bool taken;
    Bool mispredict;
} Redirect deriving (Bits, Eq, FShow);

typedef struct {
    IType            iType;
    AluFunc          aluFunc;
    BrFunc           brFunc;
    Maybe#(RIndx)    dst;
    Maybe#(RIndx)    src1;
    Maybe#(RIndx)    src2;
    Maybe#(CsrIndx)  csr;
    Maybe#(Data)     imm;
} DecodedInst deriving(Bits, Eq, FShow);

typedef struct {
    IType            iType;
    Maybe#(RIndx)    dst;
    Maybe#(CsrIndx)  csr;
    Data             data;
    Addr             addr;
    Bool             mispredict;
    Bool             brTaken;
} ExecInst deriving(Bits, Eq, FShow);

// function code
// ALU
Bit#(3) fnADD   = 3'b000;
Bit#(3) fnSLL   = 3'b001;
Bit#(3) fnSLT   = 3'b010;
Bit#(3) fnSLTU  = 3'b011;
Bit#(3) fnXOR   = 3'b100;
Bit#(3) fnSR    = 3'b101;
Bit#(3) fnOR    = 3'b110;
Bit#(3) fnAND   = 3'b111;
// Branch
Bit#(3) fnBEQ   = 3'b000;
Bit#(3) fnBNE   = 3'b001;
Bit#(3) fnBLT   = 3'b100;
Bit#(3) fnBGE   = 3'b101;
Bit#(3) fnBLTU  = 3'b110;
Bit#(3) fnBGEU  = 3'b111;
// Load
Bit#(3) fnLW    = 3'b010;
//Bit#(3) fnLB    = 3'b000;
//Bit#(3) fnLH    = 3'b001;
//Bit#(3) fnLBU   = 3'b100;
//Bit#(3) fnLHU   = 3'b101;
// Store
Bit#(3) fnSW    = 3'b010;
//Bit#(3) fnSB    = 3'b000;
//Bit#(3) fnSH    = 3'b001;
// Amo
Bit#(5) fnLR    = 5'b00010;
Bit#(5) fnSC    = 5'b00011;
//MiscMem
Bit#(3) fnFENCE  = 3'b000;
//Bit#(3) fnFENCEI = 3'b001;
// System
Bit#(3) fnCSRRW  = 3'b001;
Bit#(3) fnCSRRS  = 3'b010;
//Bit#(3) fnCSRRC  = 3'b011;
//Bit#(3) fnCSRRWI = 3'b101;
//Bit#(3) fnCSRRSI = 3'b110;
//Bit#(3) fnCSRRCI = 3'b111;
Bit#(3) fnPRIV   = 3'b000;
Bit#(12) privSCALL    = 12'h000;

function Bool dataHazard(Maybe#(RIndx) src1, Maybe#(RIndx) src2, Maybe#(RIndx) dst);
    return (isValid(dst) && ((isValid(src1) && fromMaybe(?, dst)==fromMaybe(?, src1)) ||
                             (isValid(src2) && fromMaybe(?, dst)==fromMaybe(?, src2))));
endfunction

// pretty print instuction
function Fmt showInst(Instruction inst);
    Fmt ret = $format("");

    Opcode opcode = inst[  6 :  0 ];
    let rd     = inst[ 11 :  7 ];
    let funct3 = inst[ 14 : 12 ];
    let rs1    = inst[ 19 : 15 ];
    let rs2    = inst[ 24 : 20 ];
//    let funct7 = inst[ 31 : 25 ];
    let aluSel = inst[30]; // select between Add/Sub, Srl/Sra

    Bit#(32) immI   = signExtend(inst[31:20]);
    Bit#(32) immS   = signExtend({ inst[31:25], inst[11:7] });
    Bit#(32) immB   = signExtend({ inst[31], inst[7], inst[30:25], inst[11:8], 1'b0});
    Bit#(32) immU   = { inst[31:12], 12'b0 };
    Bit#(32) immJ   = signExtend({ inst[31], inst[19:12], inst[20], inst[30:25], inst[24:21], 1'b0});

    case (opcode)
        opOpImm: begin
            ret = case (funct3)
                fnADD: $format("addi");
                fnSLT: $format("slti");
                fnSLTU: $format("sltiu");
                fnAND: $format("andi");
                fnOR: $format("ori");
                fnXOR: $format("xori");
                fnSLL: $format("slli");
                fnSR: (aluSel == 0 ? $format("srli") : $format("srai"));
                default: $format("unsupport OpImm 0x%0x", inst);
            endcase;
            ret = ret + $format(" r%d = r%d ", rd, rs1);
            ret = ret + (case (funct3)
                fnSLL, fnSR: $format("0x%0x", immI[4:0]); // only low 5 bits for shift
                default: $format("0x%0x", immI);
            endcase);
        end

        opOp: begin
            ret = case (funct3)
                fnADD: (aluSel == 0 ? $format("add") : $format("sub"));
                fnSLT: $format("slt");
                fnSLTU: $format("sltu");
                fnAND: $format("and");
                fnOR: $format("or");
                fnXOR: $format("xor");
                fnSLL: $format("sll");
                fnSR: (aluSel == 0 ? $format("srl") : $format("sra"));
                default: $format("unsupport Op 0x%0x", inst);
            endcase;
            ret = ret + $format(" r%d = r%d r%d", rd, rs1, rs2);
        end

        opLui: begin
            ret = $format("lui r%d 0x%0x", rd, immU);
        end

        opAuipc: begin
            ret = $format("auipc r%d 0x%0x", rd, immU);
        end

        opJal: begin
            ret = $format("jal r%d 0x%0x", rd, immJ);
        end

        opJalr: begin
            ret = $format("jalr r%d [r%d 0x%0x]", rd, rs1, immI);
        end

        opBranch: begin
            ret = case(funct3)
                fnBEQ: $format("beq");
                fnBNE: $format("bne");
                fnBLT: $format("blt");
                fnBLTU: $format("bltu");
                fnBGE: $format("bge");
                fnBGEU: $format("bgeu");
                default: $format("unsupport Branch 0x%0x", inst);
            endcase;
            ret = ret + $format(" r%d r%d 0x%0x", rs1, rs2, immB);
        end

        opLoad: begin
            ret = case(funct3)
                fnLW: $format("lw");
                default: $format("unsupport Load 0x%0x", inst);
            endcase;
            ret = ret + $format(" r%d = [r%d 0x%0x]", rd, rs1, immI);
        end

        opStore: begin
            ret = case(funct3)
                fnSW: $format("sw");
                default: $format("unsupport Store 0x%0x", inst);
            endcase;
            ret = ret + $format(" [r%d 0x%0x] = r%d", rs1, immS, rs2);
        end

        opMiscMem: begin
            ret = case (funct3)
                //fnFENCE: $format("fence");
                //fnFENCEI: $format("fence.i");
                default: $format("unsupport MiscMem 0x%0x", inst);
            endcase;
        end

        opAmo: begin
            ret = $format("unsupport Amo 0x%0x", inst);
        end

        opSystem: begin
            case (funct3)
                fnCSRRW, fnCSRRS: begin //fnCSRRC, fnCSRRWI, fnCSRRSI, fnCSRRCI: begin
                    ret = case(funct3)
                        fnCSRRW: $format("csrrw");
                        fnCSRRS: $format("csrrs");
                    endcase;
                    ret = ret + $format(" r%d csr0x%0x r%d", rd, immI[11:0], rs1);
                end

                fnPRIV: begin
                    ret = case (truncate(immI))
                        //privSCALL: $format("scall");
                        default: $format("unsupport System PRIV 0x%0x", inst);
                    endcase;
                end

                default: begin
                    ret = $format("unsupport System 0x%0x", inst);
                end
            endcase
        end

        default: begin
            ret = $format("unsupport 0x%0x", inst);
        end
    endcase

  return ret;

endfunction

/*

Copyright (C) 2012

Arvind <arvind@csail.mit.edu>
Muralidaran Vijayaraghavan <vmurali@csail.mit.edu>

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 Types::*;
import FShow::*;
import MemTypes::*;

// cpu to host data type
typedef enum {
    ExitCode = 2'd0,
    PrintChar = 2'd1,
    PrintIntLow = 2'd2,
    PrintIntHigh = 2'd3
} CpuToHostType deriving(Bits, Eq, FShow);

typedef struct {
    CpuToHostType c2hType;
    Bit#(16) data;
} CpuToHostData deriving(Bits, Eq, FShow);

interface Proc;
    method ActionValue#(CpuToHostData) cpuToHost;
    method Action hostToCpu(Addr startpc);
    interface MemInitIfc iMemInit;
    interface MemInitIfc dMemInit;
endinterface

// general purpose reg index
typedef Bit#(5) RIndx;

// opcode
typedef Bit#(7) Opcode;
Opcode opLoad    = 7'b0000011;
Opcode opMiscMem = 7'b0001111;
Opcode opOpImm   = 7'b0010011;
Opcode opAuipc   = 7'b0010111;
Opcode opStore   = 7'b0100011;
Opcode opAmo     = 7'b0101111;
Opcode opOp      = 7'b0110011;
Opcode opLui     = 7'b0110111;
Opcode opBranch  = 7'b1100011;
Opcode opJalr    = 7'b1100111;
Opcode opJal     = 7'b1101111;
Opcode opSystem  = 7'b1110011;

// CSR index
typedef Bit#(12) CsrIndx;
CsrIndx csrInstret = 12'hc02;
CsrIndx csrCycle   = 12'hc00;
CsrIndx csrMhartid = 12'hf10;
CsrIndx csrMdcsr   = 12'h7b0;

// LR, SC, FENCE not implemented
// LB(U), LH(U), SB, SH not implemented

// For CSR, only following two are implemented
// CSRR rd csr (i.e. CSRRS rd csr x0)
// CSRW csr rs1 (i.e. CSRRW x0 csr rs1)

// SCALL, SBREAK not implemented

typedef enum {
    Unsupported,
    Alu,
    Ld,
    St,
    J,
    Jr,
    Br,
    Csrr,
    Csrw,
    Auipc
} IType deriving(Bits, Eq, FShow);

typedef enum {
    Eq,
    Neq,
    Lt,
    Ltu,
    Ge,
    Geu,
    AT,
    NT
} BrFunc deriving(Bits, Eq, FShow);

typedef enum {
    Add,
    Sub,
    And,
    Or,
    Xor,
    Slt,
    Sltu,
    Sll,
    Sra,
    Srl
} AluFunc deriving(Bits, Eq, FShow);

typedef void Exception;

typedef struct {
    Addr pc;
    Addr nextPc;
    IType brType;
    Bool taken;
    Bool mispredict;
} Redirect deriving (Bits, Eq, FShow);

typedef struct {
    IType            iType;
    AluFunc          aluFunc;
    BrFunc           brFunc;
    Maybe#(RIndx)    dst;
    Maybe#(RIndx)    src1;
    Maybe#(RIndx)    src2;
    Maybe#(CsrIndx)  csr;
    Maybe#(Data)     imm;
} DecodedInst deriving(Bits, Eq, FShow);

typedef struct {
    IType            iType;
    Maybe#(RIndx)    dst;
    Maybe#(CsrIndx)  csr;
    Data             data;
    Addr             addr;
    Bool             mispredict;
    Bool             brTaken;
} ExecInst deriving(Bits, Eq, FShow);

// function code
// ALU
Bit#(3) fnADD   = 3'b000;
Bit#(3) fnSLL   = 3'b001;
Bit#(3) fnSLT   = 3'b010;
Bit#(3) fnSLTU  = 3'b011;
Bit#(3) fnXOR   = 3'b100;
Bit#(3) fnSR    = 3'b101;
Bit#(3) fnOR    = 3'b110;
Bit#(3) fnAND   = 3'b111;
// Branch
Bit#(3) fnBEQ   = 3'b000;
Bit#(3) fnBNE   = 3'b001;
Bit#(3) fnBLT   = 3'b100;
Bit#(3) fnBGE   = 3'b101;
Bit#(3) fnBLTU  = 3'b110;
Bit#(3) fnBGEU  = 3'b111;
// Load
Bit#(3) fnLW    = 3'b010;
//Bit#(3) fnLB    = 3'b000;
//Bit#(3) fnLH    = 3'b001;
//Bit#(3) fnLBU   = 3'b100;
//Bit#(3) fnLHU   = 3'b101;
// Store
Bit#(3) fnSW    = 3'b010;
//Bit#(3) fnSB    = 3'b000;
//Bit#(3) fnSH    = 3'b001;
// Amo
Bit#(5) fnLR    = 5'b00010;
Bit#(5) fnSC    = 5'b00011;
//MiscMem
Bit#(3) fnFENCE  = 3'b000;
//Bit#(3) fnFENCEI = 3'b001;
// System
Bit#(3) fnCSRRW  = 3'b001;
Bit#(3) fnCSRRS  = 3'b010;
//Bit#(3) fnCSRRC  = 3'b011;
//Bit#(3) fnCSRRWI = 3'b101;
//Bit#(3) fnCSRRSI = 3'b110;
//Bit#(3) fnCSRRCI = 3'b111;
Bit#(3) fnPRIV   = 3'b000;
Bit#(12) privSCALL    = 12'h000;

function Bool dataHazard(Maybe#(RIndx) src1, Maybe#(RIndx) src2, Maybe#(RIndx) dst);
    return (isValid(dst) && ((isValid(src1) && fromMaybe(?, dst)==fromMaybe(?, src1)) ||
                             (isValid(src2) && fromMaybe(?, dst)==fromMaybe(?, src2))));
endfunction

// pretty print instuction
function Fmt showInst(Instruction inst);
    Fmt ret = $format("");

    Opcode opcode = inst[  6 :  0 ];
    let rd     = inst[ 11 :  7 ];
    let funct3 = inst[ 14 : 12 ];
    let rs1    = inst[ 19 : 15 ];
    let rs2    = inst[ 24 : 20 ];
//    let funct7 = inst[ 31 : 25 ];
    let aluSel = inst[30]; // select between Add/Sub, Srl/Sra

    Bit#(32) immI   = signExtend(inst[31:20]);
    Bit#(32) immS   = signExtend({ inst[31:25], inst[11:7] });
    Bit#(32) immB   = signExtend({ inst[31], inst[7], inst[30:25], inst[11:8], 1'b0});
    Bit#(32) immU   = { inst[31:12], 12'b0 };
    Bit#(32) immJ   = signExtend({ inst[31], inst[19:12], inst[20], inst[30:25], inst[24:21], 1'b0});

    case (opcode)
        opOpImm: begin
            ret = case (funct3)
                fnADD: $format("addi");
                fnSLT: $format("slti");
                fnSLTU: $format("sltiu");
                fnAND: $format("andi");
                fnOR: $format("ori");
                fnXOR: $format("xori");
                fnSLL: $format("slli");
                fnSR: (aluSel == 0 ? $format("srli") : $format("srai"));
                default: $format("unsupport OpImm 0x%0x", inst);
            endcase;
            ret = ret + $format(" r%d = r%d ", rd, rs1);
            ret = ret + (case (funct3)
                fnSLL, fnSR: $format("0x%0x", immI[4:0]); // only low 5 bits for shift
                default: $format("0x%0x", immI);
            endcase);
        end

        opOp: begin
            ret = case (funct3)
                fnADD: (aluSel == 0 ? $format("add") : $format("sub"));
                fnSLT: $format("slt");
                fnSLTU: $format("sltu");
                fnAND: $format("and");
                fnOR: $format("or");
                fnXOR: $format("xor");
                fnSLL: $format("sll");
                fnSR: (aluSel == 0 ? $format("srl") : $format("sra"));
                default: $format("unsupport Op 0x%0x", inst);
            endcase;
            ret = ret + $format(" r%d = r%d r%d", rd, rs1, rs2);
        end

        opLui: begin
            ret = $format("lui r%d 0x%0x", rd, immU);
        end

        opAuipc: begin
            ret = $format("auipc r%d 0x%0x", rd, immU);
        end

        opJal: begin
            ret = $format("jal r%d 0x%0x", rd, immJ);
        end

        opJalr: begin
            ret = $format("jalr r%d [r%d 0x%0x]", rd, rs1, immI);
        end

        opBranch: begin
            ret = case(funct3)
                fnBEQ: $format("beq");
                fnBNE: $format("bne");
                fnBLT: $format("blt");
                fnBLTU: $format("bltu");
                fnBGE: $format("bge");
                fnBGEU: $format("bgeu");
                default: $format("unsupport Branch 0x%0x", inst);
            endcase;
            ret = ret + $format(" r%d r%d 0x%0x", rs1, rs2, immB);
        end

        opLoad: begin
            ret = case(funct3)
                fnLW: $format("lw");
                default: $format("unsupport Load 0x%0x", inst);
            endcase;
            ret = ret + $format(" r%d = [r%d 0x%0x]", rd, rs1, immI);
        end

        opStore: begin
            ret = case(funct3)
                fnSW: $format("sw");
                default: $format("unsupport Store 0x%0x", inst);
            endcase;
            ret = ret + $format(" [r%d 0x%0x] = r%d", rs1, immS, rs2);
        end

        opMiscMem: begin
            ret = case (funct3)
                //fnFENCE: $format("fence");
                //fnFENCEI: $format("fence.i");
                default: $format("unsupport MiscMem 0x%0x", inst);
            endcase;
        end

        opAmo: begin
            ret = $format("unsupport Amo 0x%0x", inst);
        end

        opSystem: begin
            case (funct3)
                fnCSRRW, fnCSRRS: begin //fnCSRRC, fnCSRRWI, fnCSRRSI, fnCSRRCI: begin
                    ret = case(funct3)
                        fnCSRRW: $format("csrrw");
                        fnCSRRS: $format("csrrs");
                    endcase;
                    ret = ret + $format(" r%d csr0x%0x r%d", rd, immI[11:0], rs1);
                end

                fnPRIV: begin
                    ret = case (truncate(immI))
                        //privSCALL: $format("scall");
                        default: $format("unsupport System PRIV 0x%0x", inst);
                    endcase;
                end

                default: begin
                    ret = $format("unsupport System 0x%0x", inst);
                end
            endcase
        end

        default: begin
            ret = $format("unsupport 0x%0x", inst);
        end
    endcase

  return ret;

endfunction