everywhere

everywhere

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

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

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

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

import FIFOF::*;
import GetPutF::*;
import RingTypes::*;

module mkEchoEngine ( ServerF#(Bit#(64), Bit#(64)));
   FIFOF#(Bit#(64)) f_echo <- mkSizedFIFOF(16);   // buffer incoming requests

   interface PutF request = toPutF(f_echo);
   interface GetF response = toGetF(f_echo);

endmodule: mkEchoEngine

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

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

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

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

import FIFOF::*;
import GetPutF::*;
import RingTypes::*;

module mkEchoEngine ( ServerF#(Bit#(64), Bit#(64)));
   FIFOF#(Bit#(64)) f_echo <- mkSizedFIFOF(16);   // buffer incoming requests

   interface PutF request = toPutF(f_echo);
   interface GetF response = toGetF(f_echo);

endmodule: mkEchoServer


changes for blue scope event test. Still wrong.

/* Copyright (c) 2014 Quanta Research Cambridge, Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
import SpecialFIFOs::*;
import Vector::*;
import StmtFSM::*;
import FIFO::*;
import CtrlMux::*;
import Portal::*;
import HostInterface::*;
import Leds::*;
import BlueScopeEvent::*;
import ConnectalMemory::*;
import MemTypes::*;
import MemServer::*;
import MMU::*;

// generated by tool
import BlueScopeEventRequest::*;
import MemServerRequest::*;
import MMURequest::*;
import MemcpyIndication::*;
import BlueScopeEventIndication::*;
import MemServerIndication::*;
import MMUIndication::*;
import SerialConfigRequest::*;
import SerialConfigIndication::*;

`define BluescopeSampleLength 512

typedef enum {HostMemServerIndication, HostMemServerRequest, HostMMURequest, HostMMUIndication, BlueScopeEventIndication, BlueScopeEventRequest, SerialConfigIndication, SerialConfigRequest} IfcNames deriving (Eq,Bits);

module mkConnectalTop(ConnectalTop#(PhysAddrWidth,DataBusWidth,Empty,1));

   BlueScopeEventIndicationProxy blueScopeIndicationProxy <- mkBlueScopeEventIndicationProxy(BluescopeIndication);
   BlueScopeEvent#(64) bs <- mkBlueScopeEvent(`BluescopeSampleLength, blueScopeIndicationProxy.ifc);
   BlueScopeEventRequestWrapper blueScopeRequestWrapper <- mkBlueScopeEventRequestWrapper(BluescopeRequest,bs.requestIfc);

   MemcpyIndicationProxy memcpyIndicationProxy <- mkMemcpyIndicationProxy(MemcpyIndication);
   Memcpy memcpy <- mkMemcpyRequest(memcpyIndicationProxy.ifc, bs);
   MemcpyRequestWrapper memcpyRequestWrapper <- mkMemcpyRequestWrapper(MemcpyRequest,memcpy.request);

   Vector#(1, MemWriteClient#(DataBusWidth)) writeClients = newVector();
   writeClients[0] = bs.writeClient;

   MMUIndicationProxy hostMMUIndicationProxy <- mkMMUIndicationProxy(HostMMUIndication);
   MMU#(PhysAddrWidth) hostMMU <- mkMMU(0, True, hostMMUIndicationProxy.ifc);
   MMURequestWrapper hostMMURequestWrapper <- mkMMURequestWrapper(HostMMURequest, hostMMU.request);

   MemServerIndicationProxy hostMemServerIndicationProxy <- mkMemServerIndicationProxy(HostMemServerIndication);
   MemServer#(PhysAddrWidth,64,1) dma <- mkMemServerRW(hostMemServerIndicationProxy.ifc, readClients, writeClients, cons(hostMMU,nil));
   MemServerRequestWrapper hostMemServerRequestWrapper <- mkMemServerRequestWrapper(HostMemServerRequest, dma.request);

   Vector#(8,StdPortal) portals;
   portals[0] = serialConfigRequestWrapper.portalIfc;
   portals[1] = serialConfigIndicationProxy.portalIfc;
   portals[2] = blueScopeEventRequestWrapper.portalIfc;
   portals[3] = blueScopeEventIndicationProxy.portalIfc;
   portals[4] = hostMemServerRequestWrapper.portalIfc;
   portals[5] = hostMemServerIndicationProxy.portalIfc;
   portals[6] = hostMMURequestWrapper.portalIfc;
   portals[7] = hostMMUIndicationProxy.portalIfc;
   let ctrl_mux <- mkSlaveMux(portals);

   interface interrupt = getInterruptVector(portals);
   interface slave = ctrl_mux;
   interface masters = dma.masters;
   interface leds = default_leds;
endmodule

/* Copyright (c) 2014 Quanta Research Cambridge, Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
import SpecialFIFOs::*;
import Vector::*;
import StmtFSM::*;
import FIFO::*;
import CtrlMux::*;
import Portal::*;
import HostInterface::*;
import Leds::*;
import BlueScope::*;
import ConnectalMemory::*;
import MemTypes::*;
import MemServer::*;
import MMU::*;

// generated by tool
import MemcpyRequest::*;
import BlueScopeRequest::*;
import MemServerRequest::*;
import MMURequest::*;
import MemcpyIndication::*;
import BlueScopeIndication::*;
import MemServerIndication::*;
import MMUIndication::*;

// defined by user
import Memcpy::*;

`define BluescopeSampleLength 8

typedef enum {MemcpyIndication, MemcpyRequest, HostMemServerIndication, HostMemServerRequest, HostMMURequest, HostMMUIndication, BluescopeIndication, BluescopeRequest} IfcNames deriving (Eq,Bits);

module mkConnectalTop(StdConnectalDmaTop#(PhysAddrWidth));

   BlueScopeIndicationProxy blueScopeIndicationProxy <- mkBlueScopeIndicationProxy(BluescopeIndication);
   BlueScope#(64) bs <- mkBlueScope(`BluescopeSampleLength, blueScopeIndicationProxy.ifc);
   BlueScopeRequestWrapper blueScopeRequestWrapper <- mkBlueScopeRequestWrapper(BluescopeRequest,bs.requestIfc);

   MemcpyIndicationProxy memcpyIndicationProxy <- mkMemcpyIndicationProxy(MemcpyIndication);
   Memcpy memcpy <- mkMemcpyRequest(memcpyIndicationProxy.ifc, bs);
   MemcpyRequestWrapper memcpyRequestWrapper <- mkMemcpyRequestWrapper(MemcpyRequest,memcpy.request);

   Vector#(1,  MemReadClient#(64))   readClients = newVector();
   readClients[0] = memcpy.readClient;
   Vector#(2, MemWriteClient#(64)) writeClients = newVector();
   writeClients[0] = bs.writeClient;
   writeClients[1] = memcpy.writeClient;
   MMUIndicationProxy hostMMUIndicationProxy <- mkMMUIndicationProxy(HostMMUIndication);
   MMU#(PhysAddrWidth) hostMMU <- mkMMU(0, True, hostMMUIndicationProxy.ifc);
   MMURequestWrapper hostMMURequestWrapper <- mkMMURequestWrapper(HostMMURequest, hostMMU.request);

   MemServerIndicationProxy hostMemServerIndicationProxy <- mkMemServerIndicationProxy(HostMemServerIndication);
   MemServer#(PhysAddrWidth,64,1) dma <- mkMemServerRW(hostMemServerIndicationProxy.ifc, readClients, writeClients, cons(hostMMU,nil));
   MemServerRequestWrapper hostMemServerRequestWrapper <- mkMemServerRequestWrapper(HostMemServerRequest, dma.request);

   Vector#(8,StdPortal) portals;
   portals[0] = memcpyRequestWrapper.portalIfc;
   portals[1] = memcpyIndicationProxy.portalIfc;
   portals[2] = blueScopeRequestWrapper.portalIfc;
   portals[3] = blueScopeIndicationProxy.portalIfc;
   portals[4] = hostMemServerRequestWrapper.portalIfc;
   portals[5] = hostMemServerIndicationProxy.portalIfc;
   portals[6] = hostMMURequestWrapper.portalIfc;
   portals[7] = hostMMUIndicationProxy.portalIfc;
   let ctrl_mux <- mkSlaveMux(portals);

   interface interrupt = getInterruptVector(portals);
   interface slave = ctrl_mux;
   interface masters = dma.masters;
   interface leds = default_leds;
endmodule


Decoder now correctly obeys m, a, f, and d macros

// Copyright (c) 2016 Massachusetts Institute of Technology

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

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

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

`include "ProcConfig.bsv"
`include "Opcodes.defines"

import BuildVector::*;
import Opcodes::*;
import RVTypes::*;
import Vector::*;
import DefaultValue::*;

function Maybe#(ExecFunc) toExecFuncRV32I(Instruction inst);
    return (case (inst) matches
            // BRANCH
            `BEQ:   tagged Valid (tagged Br Eq);
            `BNE:   tagged Valid (tagged Br Neq);
            `BLT:   tagged Valid (tagged Br Lt);
            `BGE:   tagged Valid (tagged Br Ge);
            `BLTU:  tagged Valid (tagged Br Ltu);
            `BGEU:  tagged Valid (tagged Br Geu);
            // JALR
            `JALR:  tagged Valid (tagged Br Jalr);
            // JAL
            `JAL:   tagged Valid (tagged Br Jal);
            // LUI
            `LUI:   tagged Valid (tagged Alu AluInst{op: Lui,   w: False});
            // AUIPC
            `AUIPC: tagged Valid (tagged Alu AluInst{op: Auipc, w: False});
            // OP-IMM
            `ADDI:  tagged Valid (tagged Alu AluInst{op: Add,   w: False});
            `SLLI:  tagged Valid (tagged Alu AluInst{op: Sll,   w: False});
            `SLTI:  tagged Valid (tagged Alu AluInst{op: Slt,   w: False});
            `SLTIU: tagged Valid (tagged Alu AluInst{op: Sltu,  w: False});
            `XORI:  tagged Valid (tagged Alu AluInst{op: Xor,   w: False});
            `SRLI:  tagged Valid (tagged Alu AluInst{op: Srl,   w: False});
            `SRAI:  tagged Valid (tagged Alu AluInst{op: Sra,   w: False});
            `ORI:   tagged Valid (tagged Alu AluInst{op: Or,    w: False});
            `ANDI:  tagged Valid (tagged Alu AluInst{op: And,   w: False});
            // OP
            `ADD:   tagged Valid (tagged Alu AluInst{op: Add,   w: False});
            `SUB:   tagged Valid (tagged Alu AluInst{op: Sub,   w: False});
            `SLL:   tagged Valid (tagged Alu AluInst{op: Sll,   w: False});
            `SLT:   tagged Valid (tagged Alu AluInst{op: Slt,   w: False});
            `SLTU:  tagged Valid (tagged Alu AluInst{op: Sltu,  w: False});
            `XOR:   tagged Valid (tagged Alu AluInst{op: Xor,   w: False});
            `SRL:   tagged Valid (tagged Alu AluInst{op: Srl,   w: False});
            `SRA:   tagged Valid (tagged Alu AluInst{op: Sra,   w: False});
            `OR:    tagged Valid (tagged Alu AluInst{op: Or,    w: False});
            `AND:   tagged Valid (tagged Alu AluInst{op: And,   w: False});
            // LOAD
            `LB:    tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: B, isUnsigned: False});
            `LH:    tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: H, isUnsigned: False});
            `LW:    tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: W, isUnsigned: False});
            `LBU:   tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: B, isUnsigned: True});
            `LHU:   tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: H, isUnsigned: True});
            // STORE
            `SB:    tagged Valid (tagged Mem RVMemInst{op: tagged Mem St, size: B, isUnsigned: False});
            `SH:    tagged Valid (tagged Mem RVMemInst{op: tagged Mem St, size: H, isUnsigned: False});
            `SW:    tagged Valid (tagged Mem RVMemInst{op: tagged Mem St, size: W, isUnsigned: False});
            // MISC-MEM
            `FENCE:     tagged Valid (tagged Fence (tagged InterCore unpack(truncate(inst[27:20]))));
            `FENCE_I:   tagged Valid (tagged Fence (tagged IntraCore FenceI));

            default: tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV64I(Instruction inst);
    return (case (inst) matches
            // OP-IMM-32
            `ADDIW: tagged Valid (tagged Alu AluInst{op: Add,   w: True});
            `SLLIW: tagged Valid (tagged Alu AluInst{op: Sll,   w: True});
            `SRLIW: tagged Valid (tagged Alu AluInst{op: Srl,   w: True});
            `SRAIW: tagged Valid (tagged Alu AluInst{op: Sra,   w: True});
            // OP-32
            `ADDW:  tagged Valid (tagged Alu AluInst{op: Add,   w: True});
            `SUBW:  tagged Valid (tagged Alu AluInst{op: Sub,   w: True});
            `SLLW:  tagged Valid (tagged Alu AluInst{op: Sll,   w: True});
            `SRLW:  tagged Valid (tagged Alu AluInst{op: Srl,   w: True});
            `SRAW:  tagged Valid (tagged Alu AluInst{op: Sra,   w: True});
            // LOAD
            `LD:    tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: D, isUnsigned: False});
            `LWU:   tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: W, isUnsigned: True});
            // STORE
            `SD:    tagged Valid (tagged Mem RVMemInst{op: tagged Mem St, size: D, isUnsigned: False});
            // MISC-MEM
            `FENCE:     tagged Valid (tagged Fence (tagged InterCore unpack(truncate(inst[27:20]))));
            `FENCE_I:   tagged Valid (tagged Fence (tagged IntraCore FenceI));

            default: tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncPriv(Instruction inst);
    InstructionFields instFields = unpack(inst);
    return (case (inst) matches
            `ECALL:     tagged Valid (tagged System ECall);
            `EBREAK:    tagged Valid (tagged System EBreak);
            // `URET:      tagged Valid (tagged System URet);
            `SRET:      tagged Valid (tagged System SRet);
            // `HRET:      tagged Valid (tagged System HRet);
            `MRET:      tagged Valid (tagged System MRet);
            `SFENCE_VM: tagged Valid (tagged Fence (tagged IntraCore SFenceVM));
            `WFI:       tagged Valid (tagged System WFI);
            `CSRRW:     tagged Valid (tagged System ((instFields.rd == 0) ? CSRW : CSRRW));
            `CSRRS:     tagged Valid (tagged System ((instFields.rs1 == 0) ? CSRR : CSRRS));
            `CSRRC:     tagged Valid (tagged System ((instFields.rs1 == 0) ? CSRR : CSRRC));
            `CSRRWI:    tagged Valid (tagged System ((instFields.rd == 0) ? CSRW : CSRRW));
            `CSRRSI:    tagged Valid (tagged System ((instFields.rs1 == 0) ? CSRR : CSRRS));
            `CSRRCI:    tagged Valid (tagged System ((instFields.rs1 == 0) ? CSRR : CSRRC));

            default:    tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV32M(Instruction inst);
    return (case(inst) matches
            `MUL:       tagged Valid (tagged MulDiv MulDivInst{func: Mul,  w: False, sign: Signed});
            `MULH:      tagged Valid (tagged MulDiv MulDivInst{func: Mulh, w: False, sign: Signed});
            `MULHSU:    tagged Valid (tagged MulDiv MulDivInst{func: Mulh, w: False, sign: SignedUnsigned});
            `MULHU:     tagged Valid (tagged MulDiv MulDivInst{func: Mulh, w: False, sign: Unsigned});
            `DIV:       tagged Valid (tagged MulDiv MulDivInst{func: Div,  w: False, sign: Signed});
            `DIVU:      tagged Valid (tagged MulDiv MulDivInst{func: Div,  w: False, sign: Unsigned});
            `REM:       tagged Valid (tagged MulDiv MulDivInst{func: Rem,  w: False, sign: Signed});
            `REMU:      tagged Valid (tagged MulDiv MulDivInst{func: Rem,  w: False, sign: Unsigned});

            default:    tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV64M(Instruction inst);
    return (case(inst) matches
            `MULW:      tagged Valid (tagged MulDiv MulDivInst{func: Mul,  w: True,  sign: Signed});
            `DIVW:      tagged Valid (tagged MulDiv MulDivInst{func: Div,  w: True,  sign: Signed});
            `DIVUW:     tagged Valid (tagged MulDiv MulDivInst{func: Div,  w: True,  sign: Unsigned});
            `REMW:      tagged Valid (tagged MulDiv MulDivInst{func: Rem,  w: True,  sign: Signed});
            `REMUW:     tagged Valid (tagged MulDiv MulDivInst{func: Rem,  w: True,  sign: Unsigned});

            default:    tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV32A(Instruction inst);
    return (case (inst) matches
            `AMOADD_W:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo Add,  size: W, isUnsigned: False});
            `AMOXOR_W:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo Xor,  size: W, isUnsigned: False});
            `AMOOR_W:   tagged Valid (tagged Mem RVMemInst{op: tagged Amo Or,   size: W, isUnsigned: False});
            `AMOAND_W:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo And,  size: W, isUnsigned: False});
            `AMOMIN_W:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo Min,  size: W, isUnsigned: False});
            `AMOMAX_W:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo Max,  size: W, isUnsigned: False});
            `AMOMINU_W: tagged Valid (tagged Mem RVMemInst{op: tagged Amo Minu, size: W, isUnsigned: False});
            `AMOMAXU_W: tagged Valid (tagged Mem RVMemInst{op: tagged Amo Maxu, size: W, isUnsigned: False});
            `AMOSWAP_W: tagged Valid (tagged Mem RVMemInst{op: tagged Amo Swap, size: W, isUnsigned: False});
            `LR_W:      tagged Valid (tagged Mem RVMemInst{op: tagged Mem Lr,   size: W, isUnsigned: False});
            `SC_W:      tagged Valid (tagged Mem RVMemInst{op: tagged Mem Sc,   size: W, isUnsigned: False});

            default:    tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV64A(Instruction inst);
    return (case (inst) matches
            `AMOADD_D:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo Add,  size: D, isUnsigned: False});
            `AMOXOR_D:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo Xor,  size: D, isUnsigned: False});
            `AMOOR_D:   tagged Valid (tagged Mem RVMemInst{op: tagged Amo Or,   size: D, isUnsigned: False});
            `AMOAND_D:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo And,  size: D, isUnsigned: False});
            `AMOMIN_D:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo Min,  size: D, isUnsigned: False});
            `AMOMAX_D:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo Max,  size: D, isUnsigned: False});
            `AMOMINU_D: tagged Valid (tagged Mem RVMemInst{op: tagged Amo Minu, size: D, isUnsigned: False});
            `AMOMAXU_D: tagged Valid (tagged Mem RVMemInst{op: tagged Amo Maxu, size: D, isUnsigned: False});
            `AMOSWAP_D: tagged Valid (tagged Mem RVMemInst{op: tagged Amo Swap, size: D, isUnsigned: False});
            `LR_D:      tagged Valid (tagged Mem RVMemInst{op: tagged Mem Lr,   size: D, isUnsigned: False});
            `SC_D:      tagged Valid (tagged Mem RVMemInst{op: tagged Mem Sc,   size: D, isUnsigned: False});

            default:    tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV32F(Instruction inst);
    return (case (inst) matches
            `FADD_S:    tagged Valid (tagged Fpu FpuInst{func: FAdd,     precision: Single});
            `FSUB_S:    tagged Valid (tagged Fpu FpuInst{func: FSub,     precision: Single});
            `FMUL_S:    tagged Valid (tagged Fpu FpuInst{func: FMul,     precision: Single});
`ifndef NO_FDIV
            `FDIV_S:    tagged Valid (tagged Fpu FpuInst{func: FDiv,     precision: Single});
`endif
            `FSGNJ_S:   tagged Valid (tagged Fpu FpuInst{func: FSgnj,    precision: Single});
            `FSGNJN_S:  tagged Valid (tagged Fpu FpuInst{func: FSgnjn,   precision: Single});
            `FSGNJX_S:  tagged Valid (tagged Fpu FpuInst{func: FSgnjx,   precision: Single});
            `FMIN_S:    tagged Valid (tagged Fpu FpuInst{func: FMin,     precision: Single});
            `FMAX_S:    tagged Valid (tagged Fpu FpuInst{func: FMax,     precision: Single});
`ifndef NO_FSQRT
            `FSQRT_S:   tagged Valid (tagged Fpu FpuInst{func: FSqrt,    precision: Single});
`endif

            `FLE_S:     tagged Valid (tagged Fpu FpuInst{func: FLe,      precision: Single});
            `FLT_S:     tagged Valid (tagged Fpu FpuInst{func: FLt,      precision: Single});
            `FEQ_S:     tagged Valid (tagged Fpu FpuInst{func: FEq,      precision: Single});

            `FCVT_W_S:  tagged Valid (tagged Fpu FpuInst{func: FCvt_WF,  precision: Single});
            `FCVT_WU_S: tagged Valid (tagged Fpu FpuInst{func: FCvt_WUF, precision: Single});

            `FMV_X_S:   tagged Valid (tagged Fpu FpuInst{func: FMv_XF,   precision: Single});

            `FCLASS_S:  tagged Valid (tagged Fpu FpuInst{func: FClass,   precision: Single});

            `FCVT_S_W:  tagged Valid (tagged Fpu FpuInst{func: FCvt_FW,  precision: Single});
            `FCVT_S_WU: tagged Valid (tagged Fpu FpuInst{func: FCvt_FWU, precision: Single});
            `FMV_S_X:   tagged Valid (tagged Fpu FpuInst{func: FMv_FX,   precision: Single});

            // Floating-Point Memory instructions
            `FLW:       tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: W, isUnsigned: True});
            `FSW:       tagged Valid (tagged Mem RVMemInst{op: tagged Mem St, size: W, isUnsigned: True});

            // FMA instructions
            `FMADD_S:   tagged Valid (tagged Fpu FpuInst{func: FMAdd,  precision: Single});
            `FMSUB_S:   tagged Valid (tagged Fpu FpuInst{func: FMSub,  precision: Single});
            `FNMSUB_S:  tagged Valid (tagged Fpu FpuInst{func: FNMSub, precision: Single});
            `FNMADD_S:  tagged Valid (tagged Fpu FpuInst{func: FNMAdd, precision: Single});

            default:    tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV64F(Instruction inst);
    return (case (inst) matches
            `FCVT_L_S:  tagged Valid (tagged Fpu FpuInst{func: FCvt_LF,  precision: Single});
            `FCVT_LU_S: tagged Valid (tagged Fpu FpuInst{func: FCvt_LUF, precision: Single});
            `FCVT_S_L:  tagged Valid (tagged Fpu FpuInst{func: FCvt_FL,  precision: Single});
            `FCVT_S_LU: tagged Valid (tagged Fpu FpuInst{func: FCvt_FLU, precision: Single});

            default:    tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV32D(Instruction inst);
    return (case (inst) matches
            `FADD_D:    tagged Valid (tagged Fpu FpuInst{func: FAdd,     precision: Double});
            `FSUB_D:    tagged Valid (tagged Fpu FpuInst{func: FSub,     precision: Double});
            `FMUL_D:    tagged Valid (tagged Fpu FpuInst{func: FMul,     precision: Double});
`ifndef NO_FDIV
            `FDIV_D:    tagged Valid (tagged Fpu FpuInst{func: FDiv,     precision: Double});
`endif
            `FSGNJ_D:   tagged Valid (tagged Fpu FpuInst{func: FSgnj,    precision: Double});
            `FSGNJN_D:  tagged Valid (tagged Fpu FpuInst{func: FSgnjn,   precision: Double});
            `FSGNJX_D:  tagged Valid (tagged Fpu FpuInst{func: FSgnjx,   precision: Double});
            `FMIN_D:    tagged Valid (tagged Fpu FpuInst{func: FMin,     precision: Double});
            `FMAX_D:    tagged Valid (tagged Fpu FpuInst{func: FMax,     precision: Double});
            `FCVT_S_D:  tagged Valid (tagged Fpu FpuInst{func: FCvt_FF,  precision: Single});
            `FCVT_D_S:  tagged Valid (tagged Fpu FpuInst{func: FCvt_FF,  precision: Double});
`ifndef NO_FSQRT
            `FSQRT_D:   tagged Valid (tagged Fpu FpuInst{func: FSqrt,    precision: Double});
`endif

            `FLE_D:     tagged Valid (tagged Fpu FpuInst{func: FLe,      precision: Double});
            `FLT_D:     tagged Valid (tagged Fpu FpuInst{func: FLt,      precision: Double});
            `FEQ_D:     tagged Valid (tagged Fpu FpuInst{func: FEq,      precision: Double});

            `FCVT_W_D:  tagged Valid (tagged Fpu FpuInst{func: FCvt_WF,  precision: Double});
            `FCVT_WU_D: tagged Valid (tagged Fpu FpuInst{func: FCvt_WUF, precision: Double});

            `FCLASS_D:  tagged Valid (tagged Fpu FpuInst{func: FClass,   precision: Double});

            `FCVT_D_W:  tagged Valid (tagged Fpu FpuInst{func: FCvt_FW,  precision: Double});
            `FCVT_D_WU: tagged Valid (tagged Fpu FpuInst{func: FCvt_FWU, precision: Double});

            // Floating-Point Memory instructions
            `FLD:       tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: D, isUnsigned: False});
            `FSD:       tagged Valid (tagged Mem RVMemInst{op: tagged Mem St, size: D, isUnsigned: False});

            // FMA instructions
            `FMADD_D:   tagged Valid (tagged Fpu FpuInst{func: FMAdd,  precision: Double});
            `FMSUB_D:   tagged Valid (tagged Fpu FpuInst{func: FMSub,  precision: Double});
            `FNMSUB_D:  tagged Valid (tagged Fpu FpuInst{func: FNMSub, precision: Double});
            `FNMADD_D:  tagged Valid (tagged Fpu FpuInst{func: FNMAdd, precision: Double});

            default:    tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV64D(Instruction inst);
    return (case (inst) matches
            `FCVT_L_D:  tagged Valid (tagged Fpu FpuInst{func: FCvt_LF,  precision: Double});
            `FCVT_LU_D: tagged Valid (tagged Fpu FpuInst{func: FCvt_LUF, precision: Double});
            `FMV_X_D:   tagged Valid (tagged Fpu FpuInst{func: FMv_XF,   precision: Double});
            `FCVT_D_L:  tagged Valid (tagged Fpu FpuInst{func: FCvt_FL,  precision: Double});
            `FCVT_D_LU: tagged Valid (tagged Fpu FpuInst{func: FCvt_FLU, precision: Double});
            `FMV_D_X:   tagged Valid (tagged Fpu FpuInst{func: FMv_FX,   precision: Double});

            default:    tagged Invalid;
        endcase);
endfunction

// This returns a valid result if the instruction is legal, otherwise it
// returns a tagged invalid.
(* noinline *)
function Maybe#(RVDecodedInst) decodeInst(Instruction inst);
    // Construct a vector of all the results
    // We will apply a fold function on this vector to find the valid result
    let decoderResults = vec(
            toExecFuncRV32I(inst),
            toExecFuncRV64I(inst),
`ifdef m
            `m ? toExecFuncRV32M(inst) : tagged Invalid,
            `m ? toExecFuncRV64M(inst) : tagged Invalid,
`endif
`ifdef a
            `a ? toExecFuncRV32A(inst) : tagged Invalid,
            `a ? toExecFuncRV64A(inst) : tagged Invalid,
`endif
`ifdef f
            `f ? toExecFuncRV32F(inst) : tagged Invalid,
            `f ? toExecFuncRV64F(inst) : tagged Invalid,
`endif
`ifdef d
            `d ? toExecFuncRV32D(inst) : tagged Invalid,
            `d ? toExecFuncRV64D(inst) : tagged Invalid,
`endif
            toExecFuncPriv(inst)
        );

    // This fold is equivalent to going down the list of decoder results and
    // returning the first valid result
    function Maybe#(t) fold_op(Maybe#(t) x, Maybe#(t) y) provisos (Bits#(t, tSz));
        return isValid(x) ? x : y;
    endfunction
    let execFunc = fold(fold_op, decoderResults);

    if (execFunc matches tagged Valid .validExecFunc) begin
        InstType instType = toInstType(inst);
        return tagged Valid (RVDecodedInst {
                execFunc: validExecFunc,
                imm: instType.imm,
                rs1: instType.rs1,
                rs2: instType.rs2,
                rs3: instType.rs3,
                dst: instType.dst,
                inst: inst });
    end else begin
        return tagged Invalid;
    end
endfunction

// This function is used to get the immediate value from a decoded instruction
function Maybe#(Data) getImmediate(ImmType imm, Instruction inst);
    Data immI  = signExtend(inst[31:20]);
    Data immS  = signExtend({inst[31:25], inst[11:7]});
    Data immSB = signExtend({inst[31], inst[7], inst[30:25], inst[11:8], 1'b0});
    Data immU  = signExtend({inst[31:12], 12'b0});
    Data immUJ = signExtend({inst[31], inst[19:12], inst[20], inst[30:21], 1'b0});
    Data immZ  = zeroExtend(inst[19:15]);
    return (case (imm)
            S:  tagged Valid immS;
            SB: tagged Valid immSB;
            U:  tagged Valid immU;
            UJ: tagged Valid immUJ;
            I:  tagged Valid immI;
            Z:  tagged Valid immZ;
            default: tagged Invalid;
        endcase);
endfunction

function Bit#(2) getMinPriv(Instruction inst);
    return (getInstFields(inst).opcode == System) ? inst[29:28] : prvU;
endfunction

// Copyright (c) 2016 Massachusetts Institute of Technology

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

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

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

`include "ProcConfig.bsv"
`include "Opcodes.defines"

import BuildVector::*;
import Opcodes::*;
import RVTypes::*;
import Vector::*;
import DefaultValue::*;

function Maybe#(ExecFunc) toExecFuncRV32I(Instruction inst);
    return (case (inst) matches
            // BRANCH
            `BEQ:   tagged Valid (tagged Br Eq);
            `BNE:   tagged Valid (tagged Br Neq);
            `BLT:   tagged Valid (tagged Br Lt);
            `BGE:   tagged Valid (tagged Br Ge);
            `BLTU:  tagged Valid (tagged Br Ltu);
            `BGEU:  tagged Valid (tagged Br Geu);
            // JALR
            `JALR:  tagged Valid (tagged Br Jalr);
            // JAL
            `JAL:   tagged Valid (tagged Br Jal);
            // LUI
            `LUI:   tagged Valid (tagged Alu AluInst{op: Lui,   w: False});
            // AUIPC
            `AUIPC: tagged Valid (tagged Alu AluInst{op: Auipc, w: False});
            // OP-IMM
            `ADDI:  tagged Valid (tagged Alu AluInst{op: Add,   w: False});
            `SLLI:  tagged Valid (tagged Alu AluInst{op: Sll,   w: False});
            `SLTI:  tagged Valid (tagged Alu AluInst{op: Slt,   w: False});
            `SLTIU: tagged Valid (tagged Alu AluInst{op: Sltu,  w: False});
            `XORI:  tagged Valid (tagged Alu AluInst{op: Xor,   w: False});
            `SRLI:  tagged Valid (tagged Alu AluInst{op: Srl,   w: False});
            `SRAI:  tagged Valid (tagged Alu AluInst{op: Sra,   w: False});
            `ORI:   tagged Valid (tagged Alu AluInst{op: Or,    w: False});
            `ANDI:  tagged Valid (tagged Alu AluInst{op: And,   w: False});
            // OP
            `ADD:   tagged Valid (tagged Alu AluInst{op: Add,   w: False});
            `SUB:   tagged Valid (tagged Alu AluInst{op: Sub,   w: False});
            `SLL:   tagged Valid (tagged Alu AluInst{op: Sll,   w: False});
            `SLT:   tagged Valid (tagged Alu AluInst{op: Slt,   w: False});
            `SLTU:  tagged Valid (tagged Alu AluInst{op: Sltu,  w: False});
            `XOR:   tagged Valid (tagged Alu AluInst{op: Xor,   w: False});
            `SRL:   tagged Valid (tagged Alu AluInst{op: Srl,   w: False});
            `SRA:   tagged Valid (tagged Alu AluInst{op: Sra,   w: False});
            `OR:    tagged Valid (tagged Alu AluInst{op: Or,    w: False});
            `AND:   tagged Valid (tagged Alu AluInst{op: And,   w: False});
            // LOAD
            `LB:    tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: B, isUnsigned: False});
            `LH:    tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: H, isUnsigned: False});
            `LW:    tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: W, isUnsigned: False});
            `LBU:   tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: B, isUnsigned: True});
            `LHU:   tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: H, isUnsigned: True});
            // STORE
            `SB:    tagged Valid (tagged Mem RVMemInst{op: tagged Mem St, size: B, isUnsigned: False});
            `SH:    tagged Valid (tagged Mem RVMemInst{op: tagged Mem St, size: H, isUnsigned: False});
            `SW:    tagged Valid (tagged Mem RVMemInst{op: tagged Mem St, size: W, isUnsigned: False});
            // MISC-MEM
            `FENCE:     tagged Valid (tagged Fence (tagged InterCore unpack(truncate(inst[27:20]))));
            `FENCE_I:   tagged Valid (tagged Fence (tagged IntraCore FenceI));

            default: tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV64I(Instruction inst);
    return (case (inst) matches
            // OP-IMM-32
            `ADDIW: tagged Valid (tagged Alu AluInst{op: Add,   w: True});
            `SLLIW: tagged Valid (tagged Alu AluInst{op: Sll,   w: True});
            `SRLIW: tagged Valid (tagged Alu AluInst{op: Srl,   w: True});
            `SRAIW: tagged Valid (tagged Alu AluInst{op: Sra,   w: True});
            // OP-32
            `ADDW:  tagged Valid (tagged Alu AluInst{op: Add,   w: True});
            `SUBW:  tagged Valid (tagged Alu AluInst{op: Sub,   w: True});
            `SLLW:  tagged Valid (tagged Alu AluInst{op: Sll,   w: True});
            `SRLW:  tagged Valid (tagged Alu AluInst{op: Srl,   w: True});
            `SRAW:  tagged Valid (tagged Alu AluInst{op: Sra,   w: True});
            // LOAD
            `LD:    tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: D, isUnsigned: False});
            `LWU:   tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: W, isUnsigned: True});
            // STORE
            `SD:    tagged Valid (tagged Mem RVMemInst{op: tagged Mem St, size: D, isUnsigned: False});
            // MISC-MEM
            `FENCE:     tagged Valid (tagged Fence (tagged InterCore unpack(truncate(inst[27:20]))));
            `FENCE_I:   tagged Valid (tagged Fence (tagged IntraCore FenceI));

            default: tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncPriv(Instruction inst);
    InstructionFields instFields = unpack(inst);
    return (case (inst) matches
            `ECALL:     tagged Valid (tagged System ECall);
            `EBREAK:    tagged Valid (tagged System EBreak);
            // `URET:      tagged Valid (tagged System URet);
            `SRET:      tagged Valid (tagged System SRet);
            // `HRET:      tagged Valid (tagged System HRet);
            `MRET:      tagged Valid (tagged System MRet);
            `SFENCE_VM: tagged Valid (tagged Fence (tagged IntraCore SFenceVM));
            `WFI:       tagged Valid (tagged System WFI);
            `CSRRW:     tagged Valid (tagged System ((instFields.rd == 0) ? CSRW : CSRRW));
            `CSRRS:     tagged Valid (tagged System ((instFields.rs1 == 0) ? CSRR : CSRRS));
            `CSRRC:     tagged Valid (tagged System ((instFields.rs1 == 0) ? CSRR : CSRRC));
            `CSRRWI:    tagged Valid (tagged System ((instFields.rd == 0) ? CSRW : CSRRW));
            `CSRRSI:    tagged Valid (tagged System ((instFields.rs1 == 0) ? CSRR : CSRRS));
            `CSRRCI:    tagged Valid (tagged System ((instFields.rs1 == 0) ? CSRR : CSRRC));

            default:    tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV32M(Instruction inst);
    return (case(inst) matches
            `MUL:       tagged Valid (tagged MulDiv MulDivInst{func: Mul,  w: False, sign: Signed});
            `MULH:      tagged Valid (tagged MulDiv MulDivInst{func: Mulh, w: False, sign: Signed});
            `MULHSU:    tagged Valid (tagged MulDiv MulDivInst{func: Mulh, w: False, sign: SignedUnsigned});
            `MULHU:     tagged Valid (tagged MulDiv MulDivInst{func: Mulh, w: False, sign: Unsigned});
            `DIV:       tagged Valid (tagged MulDiv MulDivInst{func: Div,  w: False, sign: Signed});
            `DIVU:      tagged Valid (tagged MulDiv MulDivInst{func: Div,  w: False, sign: Unsigned});
            `REM:       tagged Valid (tagged MulDiv MulDivInst{func: Rem,  w: False, sign: Signed});
            `REMU:      tagged Valid (tagged MulDiv MulDivInst{func: Rem,  w: False, sign: Unsigned});

            default:    tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV64M(Instruction inst);
    return (case(inst) matches
            `MULW:      tagged Valid (tagged MulDiv MulDivInst{func: Mul,  w: True,  sign: Signed});
            `DIVW:      tagged Valid (tagged MulDiv MulDivInst{func: Div,  w: True,  sign: Signed});
            `DIVUW:     tagged Valid (tagged MulDiv MulDivInst{func: Div,  w: True,  sign: Unsigned});
            `REMW:      tagged Valid (tagged MulDiv MulDivInst{func: Rem,  w: True,  sign: Signed});
            `REMUW:     tagged Valid (tagged MulDiv MulDivInst{func: Rem,  w: True,  sign: Unsigned});

            default:    tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV32A(Instruction inst);
    return (case (inst) matches
            `AMOADD_W:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo Add,  size: W, isUnsigned: False});
            `AMOXOR_W:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo Xor,  size: W, isUnsigned: False});
            `AMOOR_W:   tagged Valid (tagged Mem RVMemInst{op: tagged Amo Or,   size: W, isUnsigned: False});
            `AMOAND_W:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo And,  size: W, isUnsigned: False});
            `AMOMIN_W:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo Min,  size: W, isUnsigned: False});
            `AMOMAX_W:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo Max,  size: W, isUnsigned: False});
            `AMOMINU_W: tagged Valid (tagged Mem RVMemInst{op: tagged Amo Minu, size: W, isUnsigned: False});
            `AMOMAXU_W: tagged Valid (tagged Mem RVMemInst{op: tagged Amo Maxu, size: W, isUnsigned: False});
            `AMOSWAP_W: tagged Valid (tagged Mem RVMemInst{op: tagged Amo Swap, size: W, isUnsigned: False});
            `LR_W:      tagged Valid (tagged Mem RVMemInst{op: tagged Mem Lr,   size: W, isUnsigned: False});
            `SC_W:      tagged Valid (tagged Mem RVMemInst{op: tagged Mem Sc,   size: W, isUnsigned: False});

            default:    tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV64A(Instruction inst);
    return (case (inst) matches
            `AMOADD_D:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo Add,  size: D, isUnsigned: False});
            `AMOXOR_D:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo Xor,  size: D, isUnsigned: False});
            `AMOOR_D:   tagged Valid (tagged Mem RVMemInst{op: tagged Amo Or,   size: D, isUnsigned: False});
            `AMOAND_D:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo And,  size: D, isUnsigned: False});
            `AMOMIN_D:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo Min,  size: D, isUnsigned: False});
            `AMOMAX_D:  tagged Valid (tagged Mem RVMemInst{op: tagged Amo Max,  size: D, isUnsigned: False});
            `AMOMINU_D: tagged Valid (tagged Mem RVMemInst{op: tagged Amo Minu, size: D, isUnsigned: False});
            `AMOMAXU_D: tagged Valid (tagged Mem RVMemInst{op: tagged Amo Maxu, size: D, isUnsigned: False});
            `AMOSWAP_D: tagged Valid (tagged Mem RVMemInst{op: tagged Amo Swap, size: D, isUnsigned: False});
            `LR_D:      tagged Valid (tagged Mem RVMemInst{op: tagged Mem Lr,   size: D, isUnsigned: False});
            `SC_D:      tagged Valid (tagged Mem RVMemInst{op: tagged Mem Sc,   size: D, isUnsigned: False});

            default:    tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV32F(Instruction inst);
    return (case (inst) matches
            `FADD_S:    tagged Valid (tagged Fpu FpuInst{func: FAdd,     precision: Single});
            `FSUB_S:    tagged Valid (tagged Fpu FpuInst{func: FSub,     precision: Single});
            `FMUL_S:    tagged Valid (tagged Fpu FpuInst{func: FMul,     precision: Single});
`ifndef NO_FDIV
            `FDIV_S:    tagged Valid (tagged Fpu FpuInst{func: FDiv,     precision: Single});
`endif
            `FSGNJ_S:   tagged Valid (tagged Fpu FpuInst{func: FSgnj,    precision: Single});
            `FSGNJN_S:  tagged Valid (tagged Fpu FpuInst{func: FSgnjn,   precision: Single});
            `FSGNJX_S:  tagged Valid (tagged Fpu FpuInst{func: FSgnjx,   precision: Single});
            `FMIN_S:    tagged Valid (tagged Fpu FpuInst{func: FMin,     precision: Single});
            `FMAX_S:    tagged Valid (tagged Fpu FpuInst{func: FMax,     precision: Single});
`ifndef NO_FSQRT
            `FSQRT_S:   tagged Valid (tagged Fpu FpuInst{func: FSqrt,    precision: Single});
`endif

            `FLE_S:     tagged Valid (tagged Fpu FpuInst{func: FLe,      precision: Single});
            `FLT_S:     tagged Valid (tagged Fpu FpuInst{func: FLt,      precision: Single});
            `FEQ_S:     tagged Valid (tagged Fpu FpuInst{func: FEq,      precision: Single});

            `FCVT_W_S:  tagged Valid (tagged Fpu FpuInst{func: FCvt_WF,  precision: Single});
            `FCVT_WU_S: tagged Valid (tagged Fpu FpuInst{func: FCvt_WUF, precision: Single});

            `FMV_X_S:   tagged Valid (tagged Fpu FpuInst{func: FMv_XF,   precision: Single});

            `FCLASS_S:  tagged Valid (tagged Fpu FpuInst{func: FClass,   precision: Single});

            `FCVT_S_W:  tagged Valid (tagged Fpu FpuInst{func: FCvt_FW,  precision: Single});
            `FCVT_S_WU: tagged Valid (tagged Fpu FpuInst{func: FCvt_FWU, precision: Single});
            `FMV_S_X:   tagged Valid (tagged Fpu FpuInst{func: FMv_FX,   precision: Single});

            // Floating-Point Memory instructions
            `FLW:       tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: W, isUnsigned: True});
            `FSW:       tagged Valid (tagged Mem RVMemInst{op: tagged Mem St, size: W, isUnsigned: True});

            // FMA instructions
            `FMADD_S:   tagged Valid (tagged Fpu FpuInst{func: FMAdd,  precision: Single});
            `FMSUB_S:   tagged Valid (tagged Fpu FpuInst{func: FMSub,  precision: Single});
            `FNMSUB_S:  tagged Valid (tagged Fpu FpuInst{func: FNMSub, precision: Single});
            `FNMADD_S:  tagged Valid (tagged Fpu FpuInst{func: FNMAdd, precision: Single});

            default:    tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV64F(Instruction inst);
    return (case (inst) matches
            `FCVT_L_S:  tagged Valid (tagged Fpu FpuInst{func: FCvt_LF,  precision: Single});
            `FCVT_LU_S: tagged Valid (tagged Fpu FpuInst{func: FCvt_LUF, precision: Single});
            `FCVT_S_L:  tagged Valid (tagged Fpu FpuInst{func: FCvt_FL,  precision: Single});
            `FCVT_S_LU: tagged Valid (tagged Fpu FpuInst{func: FCvt_FLU, precision: Single});

            default:    tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV32D(Instruction inst);
    return (case (inst) matches
            `FADD_D:    tagged Valid (tagged Fpu FpuInst{func: FAdd,     precision: Double});
            `FSUB_D:    tagged Valid (tagged Fpu FpuInst{func: FSub,     precision: Double});
            `FMUL_D:    tagged Valid (tagged Fpu FpuInst{func: FMul,     precision: Double});
`ifndef NO_FDIV
            `FDIV_D:    tagged Valid (tagged Fpu FpuInst{func: FDiv,     precision: Double});
`endif
            `FSGNJ_D:   tagged Valid (tagged Fpu FpuInst{func: FSgnj,    precision: Double});
            `FSGNJN_D:  tagged Valid (tagged Fpu FpuInst{func: FSgnjn,   precision: Double});
            `FSGNJX_D:  tagged Valid (tagged Fpu FpuInst{func: FSgnjx,   precision: Double});
            `FMIN_D:    tagged Valid (tagged Fpu FpuInst{func: FMin,     precision: Double});
            `FMAX_D:    tagged Valid (tagged Fpu FpuInst{func: FMax,     precision: Double});
            `FCVT_S_D:  tagged Valid (tagged Fpu FpuInst{func: FCvt_FF,  precision: Single});
            `FCVT_D_S:  tagged Valid (tagged Fpu FpuInst{func: FCvt_FF,  precision: Double});
`ifndef NO_FSQRT
            `FSQRT_D:   tagged Valid (tagged Fpu FpuInst{func: FSqrt,    precision: Double});
`endif

            `FLE_D:     tagged Valid (tagged Fpu FpuInst{func: FLe,      precision: Double});
            `FLT_D:     tagged Valid (tagged Fpu FpuInst{func: FLt,      precision: Double});
            `FEQ_D:     tagged Valid (tagged Fpu FpuInst{func: FEq,      precision: Double});

            `FCVT_W_D:  tagged Valid (tagged Fpu FpuInst{func: FCvt_WF,  precision: Double});
            `FCVT_WU_D: tagged Valid (tagged Fpu FpuInst{func: FCvt_WUF, precision: Double});

            `FCLASS_D:  tagged Valid (tagged Fpu FpuInst{func: FClass,   precision: Double});

            `FCVT_D_W:  tagged Valid (tagged Fpu FpuInst{func: FCvt_FW,  precision: Double});
            `FCVT_D_WU: tagged Valid (tagged Fpu FpuInst{func: FCvt_FWU, precision: Double});

            // Floating-Point Memory instructions
            `FLD:       tagged Valid (tagged Mem RVMemInst{op: tagged Mem Ld, size: D, isUnsigned: False});
            `FSD:       tagged Valid (tagged Mem RVMemInst{op: tagged Mem St, size: D, isUnsigned: False});

            // FMA instructions
            `FMADD_D:   tagged Valid (tagged Fpu FpuInst{func: FMAdd,  precision: Double});
            `FMSUB_D:   tagged Valid (tagged Fpu FpuInst{func: FMSub,  precision: Double});
            `FNMSUB_D:  tagged Valid (tagged Fpu FpuInst{func: FNMSub, precision: Double});
            `FNMADD_D:  tagged Valid (tagged Fpu FpuInst{func: FNMAdd, precision: Double});

            default:    tagged Invalid;
        endcase);
endfunction

function Maybe#(ExecFunc) toExecFuncRV64D(Instruction inst);
    return (case (inst) matches
            `FCVT_L_D:  tagged Valid (tagged Fpu FpuInst{func: FCvt_LF,  precision: Double});
            `FCVT_LU_D: tagged Valid (tagged Fpu FpuInst{func: FCvt_LUF, precision: Double});
            `FMV_X_D:   tagged Valid (tagged Fpu FpuInst{func: FMv_XF,   precision: Double});
            `FCVT_D_L:  tagged Valid (tagged Fpu FpuInst{func: FCvt_FL,  precision: Double});
            `FCVT_D_LU: tagged Valid (tagged Fpu FpuInst{func: FCvt_FLU, precision: Double});
            `FMV_D_X:   tagged Valid (tagged Fpu FpuInst{func: FMv_FX,   precision: Double});

            default:    tagged Invalid;
        endcase);
endfunction

// This returns a valid result if the instruction is legal, otherwise it
// returns a tagged invalid.
(* noinline *)
function Maybe#(RVDecodedInst) decodeInst(Instruction inst);
    // Construct a vector of all the results
    // We will apply a fold function on this vector to find the valid result
    let decoderResults = vec(
            toExecFuncRV32I(inst),
            toExecFuncRV64I(inst),
`ifdef m
            toExecFuncRV32M(inst),
            toExecFuncRV64M(inst),
`endif
`ifdef a
            toExecFuncRV32A(inst),
            toExecFuncRV64A(inst),
`endif
`ifdef f
            toExecFuncRV32F(inst),
            toExecFuncRV64F(inst),
`endif
`ifdef d
            toExecFuncRV32D(inst),
            toExecFuncRV64D(inst),
`endif
            toExecFuncPriv(inst)
        );

    // This fold is equivalent to going down the list of decoder results and
    // returning the first valid result
    function Maybe#(t) fold_op(Maybe#(t) x, Maybe#(t) y) provisos (Bits#(t, tSz));
        return isValid(x) ? x : y;
    endfunction
    let execFunc = fold(fold_op, decoderResults);

    if (execFunc matches tagged Valid .validExecFunc) begin
        InstType instType = toInstType(inst);
        return tagged Valid (RVDecodedInst {
                execFunc: validExecFunc,
                imm: instType.imm,
                rs1: instType.rs1,
                rs2: instType.rs2,
                rs3: instType.rs3,
                dst: instType.dst,
                inst: inst });
    end else begin
        return tagged Invalid;
    end
endfunction

// This function is used to get the immediate value from a decoded instruction
function Maybe#(Data) getImmediate(ImmType imm, Instruction inst);
    Data immI  = signExtend(inst[31:20]);
    Data immS  = signExtend({inst[31:25], inst[11:7]});
    Data immSB = signExtend({inst[31], inst[7], inst[30:25], inst[11:8], 1'b0});
    Data immU  = signExtend({inst[31:12], 12'b0});
    Data immUJ = signExtend({inst[31], inst[19:12], inst[20], inst[30:21], 1'b0});
    Data immZ  = zeroExtend(inst[19:15]);
    return (case (imm)
            S:  tagged Valid immS;
            SB: tagged Valid immSB;
            U:  tagged Valid immU;
            UJ: tagged Valid immUJ;
            I:  tagged Valid immI;
            Z:  tagged Valid immZ;
            default: tagged Invalid;
        endcase);
endfunction

function Bit#(2) getMinPriv(Instruction inst);
    return (getInstFields(inst).opcode == System) ? inst[29:28] : prvU;
endfunction


updated examples/imageon for xbsv changes

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

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

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

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

// bsv libraries
import Vector::*;
import GetPut::*;
import Connectable :: *;
import Clocks :: *;
import FIFO::*;
import DefaultValue::*;
import MemTypes::*;

// portz libraries
import Portal::*;
import Directory::*;
import CtrlMux::*;
import Portal::*;
import Leds::*;
import XADC::*;

// generated by tool
import ImageonSerdesRequestWrapper::*;
import ImageonSerdesIndicationProxy::*;
import ImageonSensorRequestWrapper::*;
import ImageonSensorIndicationProxy::*;
import HdmiInternalRequestWrapper::*;
import HdmiInternalIndicationProxy::*;

// defined by user
import IserdesDatadeser::*;
import Imageon::*;
import HDMI::*;
import YUV::*;
import XilinxCells::*;
import XbsvXilinxCells::*;

typedef enum { ImageonSerdesRequest, ImageonSensorRequest, HdmiInternalRequest,
    ImageonSerdesIndication, ImageonSensorIndication, HdmiInternalIndication} IfcNames deriving (Eq,Bits);

interface ImageCapturePins;
   interface ImageonSensorPins pins;
   interface ImageonSerdesPins serpins;
   (* prefix="" *)
   interface HDMI#(Bit#(HdmiBits)) hdmi;
   method Action fmc_video_clk1(Bit#(1) v);
endinterface
interface ImageCapture;
   interface Vector#(6,StdPortal) portals;
   interface ImageCapturePins pins;
   interface XADC             xadc;
endinterface

module mkImageCapture#(Clock fmc_imageon_clk1)(ImageCapture);
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();
   ClockGenerator7AdvParams clockParams = defaultValue;
   clockParams.bandwidth          = "OPTIMIZED";
   clockParams.compensation       = "ZHOLD";
   clockParams.clkfbout_mult_f    = 8.000;
   clockParams.clkfbout_phase     = 0.0;
   clockParams.clkin1_period      = 6.734007; // 148.5 MHz
   clockParams.clkin2_period      = 6.734007;
   clockParams.clkout0_divide_f   = 8.000;    // 148.5 MHz
   clockParams.clkout0_duty_cycle = 0.5;
   clockParams.clkout0_phase      = 0.0000;
   clockParams.clkout1_divide     = 32;       // 37.125 MHz
   clockParams.clkout1_duty_cycle = 0.5;
   clockParams.clkout1_phase      = 0.0000;
   clockParams.divclk_divide      = 1;
   clockParams.ref_jitter1        = 0.010;
   clockParams.ref_jitter2        = 0.010;

   XClockGenerator7 clockGen <- mkClockGenerator7Adv(clockParams, clocked_by fmc_imageon_clk1);
   C2B c2b_fb <- mkC2B(clockGen.clkfbout, clocked_by clockGen.clkfbout);
   rule txoutrule5;
      clockGen.clkfbin(c2b_fb.o());
   endrule
   Clock hdmi_clock <- mkClockBUFG(clocked_by clockGen.clkout0);    // 148.5   MHz
   Clock imageon_clock <- mkClockBUFG(clocked_by clockGen.clkout1); //  37.125 MHz
   Reset hdmi_reset <- mkAsyncReset(2, defaultReset, hdmi_clock);
   Reset imageon_reset <- mkAsyncReset(2, defaultReset, imageon_clock);
   SyncPulseIfc vsyncPulse <- mkSyncHandshake(hdmi_clock, hdmi_reset, imageon_clock);

   // instantiate user portals
   // serdes: serial line protocol for wires from sensor (nothing sensor specific)
   ImageonSerdesIndicationProxy serdesIndicationProxy <- mkImageonSerdesIndicationProxy(ImageonSerdesIndication);
   ISerdes serdes <- mkISerdes(defaultClock, defaultReset, serdesIndicationProxy.ifc,
			clocked_by imageon_clock, reset_by imageon_reset);
   ImageonSerdesRequestWrapper serdesRequestWrapper <- mkImageonSerdesRequestWrapper(ImageonSerdesRequest,serdes.control);

   // fromSensor: sensor specific processing of serdes input, resulting in pixels
   ImageonSensorIndicationProxy sensorIndicationProxy <- mkImageonSensorIndicationProxy(ImageonSensorIndication);
   ImageonSensor fromSensor <- mkImageonSensor(defaultClock, defaultReset, serdes.data, vsyncPulse.pulse(),
       hdmi_clock, hdmi_reset, sensorIndicationProxy.ifc, clocked_by imageon_clock, reset_by imageon_reset);
   ImageonSensorRequestWrapper sensorRequestWrapper <- mkImageonSensorRequestWrapper(ImageonSensorRequest,fromSensor.control);

   // hdmi: output to display
   HdmiInternalIndicationProxy hdmiIndicationProxy <- mkHdmiInternalIndicationProxy(HdmiInternalIndication);
   HdmiGenerator#(Rgb888) hdmiGen <- mkHdmiGenerator(defaultClock, defaultReset,
       vsyncPulse, hdmiIndicationProxy.ifc, clocked_by hdmi_clock, reset_by hdmi_reset);
   Rgb888ToYyuv converter <- mkRgb888ToYyuv(clocked_by hdmi_clock, reset_by hdmi_reset);
   mkConnection(hdmiGen.rgb888, converter.rgb888);
   HDMI#(Bit#(HdmiBits)) hdmisignals <- mkHDMI(converter.yyuv, clocked_by hdmi_clock, reset_by hdmi_reset);
   HdmiInternalRequestWrapper hdmiRequestWrapper <- mkHdmiInternalRequestWrapper(HdmiInternalRequest,hdmiGen.control);

   Reg#(Bool) frameStart <- mkReg(False, clocked_by imageon_clock, reset_by imageon_reset);
   Reg#(Bit#(32)) frameCount <- mkReg(0, clocked_by imageon_clock, reset_by imageon_reset);
   SyncFIFOIfc#(Tuple2#(Bit#(2),Bit#(32))) frameStartSynchronizer <- mkSyncFIFO(2, imageon_clock, imageon_reset, defaultClock);

   rule frameStartRule;
       let monitor = fromSensor.monitor();
       Bool fs = unpack(monitor[0]);
       if (fs && !frameStart) begin
	  // start of frame?
	  // need to cross the clock domain
	  frameStartSynchronizer.enq(tuple2(monitor, frameCount));
	  frameCount <= frameCount + 1;
       end
      frameStart <= fs;
   endrule
   rule frameStartIndication;
      let tpl = frameStartSynchronizer.first();
      frameStartSynchronizer.deq();
      let monitor = tpl_1(tpl);
      let count = tpl_2(tpl);
      //captureIndicationProxy.ifc.frameStart(monitor, count);
   endrule

Reg#(Bit#(10)) xsvi <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);
   rule xsviConnection;
       // copy data from sensor to hdmi output
       let xsvit <- fromSensor.get_data();
       xsvi <= xsvit;
   endrule
   rule xsviput;
       Bit#(32) pixel = {8'b0, xsvi[9:2], xsvi[9:2], xsvi[9:2]};
       hdmiGen.request.put(pixel);
   endrule
   Reg#(Bit#(1)) bozobit <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);
    rule bozobit_rule;
        bozobit <= ~bozobit;
    endrule

   Vector#(6,StdPortal) portal_array;
   portal_array[0] = serdesRequestWrapper.portalIfc;
   portal_array[1] = serdesIndicationProxy.portalIfc;
   portal_array[2] = sensorRequestWrapper.portalIfc;
   portal_array[3] = sensorIndicationProxy.portalIfc;
   portal_array[4] = hdmiRequestWrapper.portalIfc;
   portal_array[5] = hdmiIndicationProxy.portalIfc;
   interface Vector portals = portal_array;

   interface ImageCapturePins pins;
       interface ImageonSensorPins pins = fromSensor.pins;
       interface ImageonSerdesPins serpins = serdes.pins;
       interface HDMI hdmi = hdmisignals;
   endinterface
   interface XADC             xadc;
        method Bit#(4) gpio;
            return { bozobit, hdmisignals.hdmi_vsync,
                //hdmisignals.hdmi_data[8], hdmisignals.hdmi_data[0]};
                hdmisignals.hdmi_hsync, hdmisignals.hdmi_de};
        endmethod
   endinterface
endmodule

module mkPortalTop(PortalTop#(PhysAddrWidth,64,ImageCapturePins,0));
   //Clock defaultClock <- exposeCurrentClock();
   //Reset defaultReset <- exposeCurrentReset();
   B2C1 iclock <- mkB2C1();
   Clock iclock_buf <- mkClockBUFG(clocked_by iclock.c);
   ImageCapture ic <- mkImageCapture(iclock_buf);

   // instantiate system directory
   StdDirectory dir <- mkStdDirectory(ic.portals);
   let ctrl_mux <- mkSlaveMux(dir,ic.portals);

   interface interrupt = getInterruptVector(ic.portals);
   interface slave = ctrl_mux;
   interface masters = nil;
   //interface leds = captureRequestInternal.leds;
   //interface xadc = ic.xadc;
   interface ImageCapturePins pins;
       method Action fmc_video_clk1(Bit#(1) v);
           iclock.inputclock(v);
       endmethod
       interface ImageonSensorPins pins = ic.pins.pins;
       interface ImageonSerdesPins serpins = ic.pins.serpins;
       interface HDMI hdmi = ic.pins.hdmi;
   endinterface
endmodule : mkPortalTop

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

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

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

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

// bsv libraries
import Vector::*;
import GetPut::*;
import Connectable :: *;
import Clocks :: *;
import FIFO::*;
import DefaultValue::*;

// portz libraries
import Portal::*;
import Directory::*;
import CtrlMux::*;
import Portal::*;
import Leds::*;
import XADC::*;

// generated by tool
import ImageonSerdesRequestWrapper::*;
import ImageonSerdesIndicationProxy::*;
import ImageonSensorRequestWrapper::*;
import ImageonSensorIndicationProxy::*;
import HdmiInternalRequestWrapper::*;
import HdmiInternalIndicationProxy::*;

// defined by user
import IserdesDatadeser::*;
import Imageon::*;
import HDMI::*;
import YUV::*;
import XilinxCells::*;
import XbsvXilinxCells::*;

typedef enum { ImageonSerdesRequest, ImageonSensorRequest, HdmiInternalRequest,
    ImageonSerdesIndication, ImageonSensorIndication, HdmiInternalIndication} IfcNames deriving (Eq,Bits);

interface ImageCapturePins;
   interface ImageonSensorPins pins;
   interface ImageonSerdesPins serpins;
   (* prefix="" *)
   interface HDMI#(Bit#(HdmiBits)) hdmi;
   method Action fmc_video_clk1(Bit#(1) v);
endinterface
interface ImageCapture;
   interface Vector#(6,StdPortal) portals;
   interface ImageCapturePins pins;
   interface XADC             xadc;
endinterface

module mkImageCapture#(Clock fmc_imageon_clk1)(ImageCapture);
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();
   ClockGenerator7AdvParams clockParams = defaultValue;
   clockParams.bandwidth          = "OPTIMIZED";
   clockParams.compensation       = "ZHOLD";
   clockParams.clkfbout_mult_f    = 8.000;
   clockParams.clkfbout_phase     = 0.0;
   clockParams.clkin1_period      = 6.734007; // 148.5 MHz
   clockParams.clkin2_period      = 6.734007;
   clockParams.clkout0_divide_f   = 8.000;    // 148.5 MHz
   clockParams.clkout0_duty_cycle = 0.5;
   clockParams.clkout0_phase      = 0.0000;
   clockParams.clkout1_divide     = 32;       // 37.125 MHz
   clockParams.clkout1_duty_cycle = 0.5;
   clockParams.clkout1_phase      = 0.0000;
   clockParams.divclk_divide      = 1;
   clockParams.ref_jitter1        = 0.010;
   clockParams.ref_jitter2        = 0.010;

   XClockGenerator7 clockGen <- mkClockGenerator7Adv(clockParams, clocked_by fmc_imageon_clk1);
   C2B c2b_fb <- mkC2B(clockGen.clkfbout, clocked_by clockGen.clkfbout);
   rule txoutrule5;
      clockGen.clkfbin(c2b_fb.o());
   endrule
   Clock hdmi_clock <- mkClockBUFG(clocked_by clockGen.clkout0);    // 148.5   MHz
   Clock imageon_clock <- mkClockBUFG(clocked_by clockGen.clkout1); //  37.125 MHz
   Reset hdmi_reset <- mkAsyncReset(2, defaultReset, hdmi_clock);
   Reset imageon_reset <- mkAsyncReset(2, defaultReset, imageon_clock);
   SyncPulseIfc vsyncPulse <- mkSyncHandshake(hdmi_clock, hdmi_reset, imageon_clock);

   // instantiate user portals
   // serdes: serial line protocol for wires from sensor (nothing sensor specific)
   ImageonSerdesIndicationProxy serdesIndicationProxy <- mkImageonSerdesIndicationProxy(ImageonSerdesIndication);
   ISerdes serdes <- mkISerdes(defaultClock, defaultReset, serdesIndicationProxy.ifc,
			clocked_by imageon_clock, reset_by imageon_reset);
   ImageonSerdesRequestWrapper serdesRequestWrapper <- mkImageonSerdesRequestWrapper(ImageonSerdesRequest,serdes.control);

   // fromSensor: sensor specific processing of serdes input, resulting in pixels
   ImageonSensorIndicationProxy sensorIndicationProxy <- mkImageonSensorIndicationProxy(ImageonSensorIndication);
   ImageonSensor fromSensor <- mkImageonSensor(defaultClock, defaultReset, serdes.data, vsyncPulse.pulse(),
       hdmi_clock, hdmi_reset, sensorIndicationProxy.ifc, clocked_by imageon_clock, reset_by imageon_reset);
   ImageonSensorRequestWrapper sensorRequestWrapper <- mkImageonSensorRequestWrapper(ImageonSensorRequest,fromSensor.control);

   // hdmi: output to display
   HdmiInternalIndicationProxy hdmiIndicationProxy <- mkHdmiInternalIndicationProxy(HdmiInternalIndication);
   HdmiGenerator#(Rgb888) hdmiGen <- mkHdmiGenerator(defaultClock, defaultReset,
       vsyncPulse, hdmiIndicationProxy.ifc, clocked_by hdmi_clock, reset_by hdmi_reset);
   Rgb888ToYyuv converter <- mkRgb888ToYyuv(clocked_by hdmi_clock, reset_by hdmi_reset);
   mkConnection(hdmiGen.rgb888, converter.rgb888);
   HDMI#(Bit#(HdmiBits)) hdmisignals <- mkHDMI(converter.yyuv, clocked_by hdmi_clock, reset_by hdmi_reset);
   HdmiInternalRequestWrapper hdmiRequestWrapper <- mkHdmiInternalRequestWrapper(HdmiInternalRequest,hdmiGen.control);

   Reg#(Bool) frameStart <- mkReg(False, clocked_by imageon_clock, reset_by imageon_reset);
   Reg#(Bit#(32)) frameCount <- mkReg(0, clocked_by imageon_clock, reset_by imageon_reset);
   SyncFIFOIfc#(Tuple2#(Bit#(2),Bit#(32))) frameStartSynchronizer <- mkSyncFIFO(2, imageon_clock, imageon_reset, defaultClock);

   rule frameStartRule;
       let monitor = fromSensor.monitor();
       Bool fs = unpack(monitor[0]);
       if (fs && !frameStart) begin
	  // start of frame?
	  // need to cross the clock domain
	  frameStartSynchronizer.enq(tuple2(monitor, frameCount));
	  frameCount <= frameCount + 1;
       end
      frameStart <= fs;
   endrule
   rule frameStartIndication;
      let tpl = frameStartSynchronizer.first();
      frameStartSynchronizer.deq();
      let monitor = tpl_1(tpl);
      let count = tpl_2(tpl);
      //captureIndicationProxy.ifc.frameStart(monitor, count);
   endrule

Reg#(Bit#(10)) xsvi <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);
   rule xsviConnection;
       // copy data from sensor to hdmi output
       let xsvit <- fromSensor.get_data();
       xsvi <= xsvit;
   endrule
   rule xsviput;
       Bit#(32) pixel = {8'b0, xsvi[9:2], xsvi[9:2], xsvi[9:2]};
       hdmiGen.request.put(pixel);
   endrule
   Reg#(Bit#(1)) bozobit <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);
    rule bozobit_rule;
        bozobit <= ~bozobit;
    endrule

   Vector#(6,StdPortal) portal_array;
   portal_array[0] = serdesRequestWrapper.portalIfc;
   portal_array[1] = serdesIndicationProxy.portalIfc;
   portal_array[2] = sensorRequestWrapper.portalIfc;
   portal_array[3] = sensorIndicationProxy.portalIfc;
   portal_array[4] = hdmiRequestWrapper.portalIfc;
   portal_array[5] = hdmiIndicationProxy.portalIfc;
   interface Vector portals = portal_array;

   interface ImageCapturePins pins;
       interface ImageonSensorPins pins = fromSensor.pins;
       interface ImageonSerdesPins serpins = serdes.pins;
       interface HDMI hdmi = hdmisignals;
   endinterface
   interface XADC             xadc;
        method Bit#(4) gpio;
            return { bozobit, hdmisignals.hdmi_vsync,
                //hdmisignals.hdmi_data[8], hdmisignals.hdmi_data[0]};
                hdmisignals.hdmi_hsync, hdmisignals.hdmi_de};
        endmethod
   endinterface
endmodule

module mkPortalTop(PortalTop#(PhysAddrWidth,64,ImageCapturePins,0));
   //Clock defaultClock <- exposeCurrentClock();
   //Reset defaultReset <- exposeCurrentReset();
   B2C1 iclock <- mkB2C1();
   Clock iclock_buf <- mkClockBUFG(clocked_by iclock.c);
   ImageCapture ic <- mkImageCapture(iclock_buf);

   // instantiate system directory
   StdDirectory dir <- mkStdDirectory(ic.portals);
   let ctrl_mux <- mkSlaveMux(dir,ic.portals);

   interface interrupt = getInterruptVector(ic.portals);
   interface slave = ctrl_mux;
   interface masters = nil;
   //interface leds = captureRequestInternal.leds;
   interface xadc = ic.xadc;
   interface ImageCapturePins pins;
       method Action fmc_video_clk1(Bit#(1) v);
           iclock.inputclock(v);
       endmethod
       interface ImageonSensorPins pins = ic.pins.pins;
       interface ImageonSerdesPins serpins = ic.pins.serpins;
       interface HDMI hdmi = ic.pins.hdmi;
   endinterface
endmodule : mkPortalTop


disable RxChannel in tdm pipeline

disable RxChannel in tdm pipeline

// Copyright (c) 2016 Cornell University.

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

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

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

import FIFO::*;
import FIFOF::*;
import DefaultValue::*;
import Vector::*;
import BuildVector::*;
import GetPut::*;
import ClientServer::*;
import Connectable::*;
import Clocks::*;
import Gearbox::*;
import Pipe::*;
import RegFile::*;
import MemTypes::*;

import DbgTypes::*;
import Ethernet::*;
import EthMac::*;
//import GenericMatchTable::*;
import HostChannel::*;
import TxChannel::*;
//import RxChannel::*;
import ModifyMac::*;
import IPv4Parser::*;
import IPv4Route::*;
import MMU::*;
import MemMgmt::*;
import PacketBuffer::*;
import SharedBuff::*;
import StoreAndForward::*;
import Tap::*;
import TDM::*;
import TdmTypes::*;

interface TdmPipeline;
   interface Put#(PacketDataT#(64)) macRx;
   interface Get#(PacketDataT#(64)) macTx;
   interface PktWriteServer writeServer;
   interface Put#(TableEntry) add_entry;
   interface Put#(FlowId) delete_entry;
   interface Put#(Tuple2#(FlowId, ActionArg)) modify_entry;
   method MemMgmtDbgRec memMgmtDbg;
   method TDMDbgRec tdmDbg;
   method ActionValue#(PktBuffDbgRec) pktBuffDbg(Bit#(8) id);
   method MatchTableDbgRec matchTableDbg;
   method TxThruDbgRec ringToMacDbg;
endinterface

module mkTdmPipeline#(Clock txClock, Reset txReset
                     ,Clock rxClock, Reset rxReset
                     ,MemoryTestIndication indication
                     ,ConnectalMemory::MemServerIndication memServerInd
`ifdef DEBUG
                     ,MemMgmtIndication memTestInd
                     ,ConnectalMemory::MMUIndication mmuInd
`endif
   )(TdmPipeline);

   //RxChannel rxchan <- mkRxChannel(rxClock, rxReset);
   HostChannel hostchan <- mkHostChannel();
   TxChannel txchan <- mkTxChannel(txClock, txReset);

   IPv4Route ipv4Route <- mkIPv4Route(hostchan.next);
   ModifyMac modMac <- mkModifyMac(ipv4Route.next);
   TDM sched <- mkTDM(modMac.next, txchan);

   SharedBuffer#(12, 128, 1) mem <- mkSharedBuffer(vec(txchan.readClient)
                                                  ,vec(txchan.freeClient)
                                                  ,vec(hostchan.writeClient, modMac.writeClient)
                                                  ,vec(hostchan.mallocClient)
                                                  ,memServerInd
`ifdef DEBUG
                                                  ,memTestInd
                                                  ,mmuInd
`endif
                                                  );

   rule read_flow_id;
      let v <- toGet(ipv4Route.entry_added).get;
      indication.addEntryResp(v);
   endrule

   //interface macRx = rxchan.macRx;
   interface macTx = txchan.macTx;
   interface writeServer = hostchan.writeServer;
   interface add_entry = ipv4Route.add_entry;
   interface delete_entry = ipv4Route.delete_entry;
   interface modify_entry = ipv4Route.modify_entry;
   method matchTableDbg = ipv4Route.mdbg;
   method memMgmtDbg = mem.dbg;
   method tdmDbg = sched.dbg;
   //method ringToMacDbg = txchan.dbg;
   method ActionValue#(PktBuffDbgRec) pktBuffDbg(Bit#(8) id);
      PktBuffDbgRec v = defaultValue;
      case (id) matches
         0: v = hostchan.dbg;
         1: v = txchan.dbg;
         2: v = rxchan.dbg;
      endcase
      return v;
   endmethod
endmodule

// Copyright (c) 2016 Cornell University.

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

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

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

import FIFO::*;
import FIFOF::*;
import DefaultValue::*;
import Vector::*;
import BuildVector::*;
import GetPut::*;
import ClientServer::*;
import Connectable::*;
import Clocks::*;
import Gearbox::*;
import Pipe::*;
import RegFile::*;
import MemTypes::*;

import DbgTypes::*;
import Ethernet::*;
import EthMac::*;
//import GenericMatchTable::*;
import HostChannel::*;
import TxChannel::*;
import RxChannel::*;
import ModifyMac::*;
import IPv4Parser::*;
import IPv4Route::*;
import MMU::*;
import MemMgmt::*;
import PacketBuffer::*;
import SharedBuff::*;
import StoreAndForward::*;
import Tap::*;
import TDM::*;
import TdmTypes::*;

interface TdmPipeline;
   interface Put#(PacketDataT#(64)) macRx;
   interface Get#(PacketDataT#(64)) macTx;
   interface PktWriteServer writeServer;
   interface Put#(TableEntry) add_entry;
   interface Put#(FlowId) delete_entry;
   interface Put#(Tuple2#(FlowId, ActionArg)) modify_entry;
   method MemMgmtDbgRec memMgmtDbg;
   method TDMDbgRec tdmDbg;
   method ActionValue#(PktBuffDbgRec) pktBuffDbg(Bit#(8) id);
   method MatchTableDbgRec matchTableDbg;
   method TxThruDbgRec ringToMacDbg;
endinterface

module mkTdmPipeline#(Clock txClock, Reset txReset
                     ,Clock rxClock, Reset rxReset
                     ,MemoryTestIndication indication
                     ,ConnectalMemory::MemServerIndication memServerInd
`ifdef DEBUG
                     ,MemMgmtIndication memTestInd
                     ,ConnectalMemory::MMUIndication mmuInd
`endif
   )(TdmPipeline);

   RxChannel rxchan <- mkRxChannel(rxClock, rxReset);
   HostChannel hostchan <- mkHostChannel();
   TxChannel txchan <- mkTxChannel(txClock, txReset);

   IPv4Route ipv4Route <- mkIPv4Route(hostchan.next);
   ModifyMac modMac <- mkModifyMac(ipv4Route.next);
   TDM sched <- mkTDM(modMac.next, txchan);

   SharedBuffer#(12, 128, 1) mem <- mkSharedBuffer(vec(txchan.readClient)
                                                  ,vec(txchan.freeClient)
                                                  ,vec(hostchan.writeClient, modMac.writeClient)
                                                  ,vec(hostchan.mallocClient)
                                                  ,memServerInd
`ifdef DEBUG
                                                  ,memTestInd
                                                  ,mmuInd
`endif
                                                  );

   rule read_flow_id;
      let v <- toGet(ipv4Route.entry_added).get;
      indication.addEntryResp(v);
   endrule

   interface macRx = rxchan.macRx;
   interface macTx = txchan.macTx;
   interface writeServer = hostchan.writeServer;
   interface add_entry = ipv4Route.add_entry;
   interface delete_entry = ipv4Route.delete_entry;
   interface modify_entry = ipv4Route.modify_entry;
   method matchTableDbg = ipv4Route.mdbg;
   method memMgmtDbg = mem.dbg;
   method tdmDbg = sched.dbg;
   //method ringToMacDbg = txchan.dbg;
   method ActionValue#(PktBuffDbgRec) pktBuffDbg(Bit#(8) id);
      PktBuffDbgRec v = defaultValue;
      case (id) matches
         0: v = hostchan.dbg;
         1: v = txchan.dbg;
         2: v = rxchan.dbg;
      endcase
      return v;
   endmethod
endmodule


update rule names for consistency

update rule names for consistency

// 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 BRAMFIFO::*;
import FIFO::*;
import FIFOF::*;
import Vector::*;
import GetPut::*;
import ClientServer::*;
import Assert::*;
import BRAM::*;
import RegFile::*;

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

interface TagGen#(numeric type numTags);
   method ActionValue#(Bit#(TLog#(numTags))) getTag;
   method Action returnTag(Bit#(TLog#(numTags)) tag);
   method ActionValue#(Bit#(TLog#(numTags))) complete;
endinterface

module mkTagGen(TagGen#(numTags))
   provisos(Log#(numTags,tsz));

   BRAM_Configure cfg = defaultValue;
   cfg.outFIFODepth = 1;
   //BRAM2Port#(Bit#(tsz),Bool) tags <- mkBRAM2Server(cfg);
   Vector#(numTags, Reg#(Bool)) tags <- replicateM(mkReg(False));
   //RegFile#(Bit#(tsz),Bool)     tags <- mkRegFile(0, fromInteger(valueOf(numTags)-1));
   Reg#(Bool)              notFull <- mkReg(False);
   Reg#(Bit#(tsz))        head_ptr <- mkReg(0);
   Reg#(Bit#(tsz))        tail_ptr <- mkReg(0);
   Reg#(Bool)               inited <- mkReg(False);
   FIFO#(Bit#(tsz))      comp_fifo <- mkFIFO;
   Reg#(Bit#(numTags))  comp_state <- mkReg(0);

   let retFifo <- mkFIFO;
   let tagFifo <- mkFIFO;

   //rule complete_rule0 (comp_state[0] != 0);
      //tags.portB.request.put(BRAMRequest{write:False, address:tail_ptr, datain: ?, responseOnWrite: ?});
   //endrule

   rule complete_rule1 (comp_state[0] != 0);
      //let rv <- tags.portB.response.get;
      //let rv = tags.sub(tail_ptr);
      let rv = tags[tail_ptr];
      if (!rv) begin
	 tail_ptr <= tail_ptr+1;
	 comp_state <= comp_state >> 1;
	 comp_fifo.enq(tail_ptr);
      end
   endrule

   // this used to be in the body of returnTag, but form some reason bsc does not
   // consider access to portA and portB to be conflict free **sigh**
   rule ret_rule;
      let tag <- toGet(retFifo).get;
      //tags.portB.request.put(BRAMRequest{write:True, responseOnWrite:False, address:tag, datain:False});
      //tags.upd(tag, False);
      tags[tag] <= False;
      comp_state <= 1 | (comp_state << 1);
   endrule

   rule init_rule(!inited);
      //tags.portA.request.put(BRAMRequest{write:True,address:head_ptr,responseOnWrite:False,datain:False});
      //tags.upd(head_ptr, False);
      //Not needed: tags[head_ptr] <= False;
      head_ptr <= head_ptr+1;
      inited <= head_ptr+1==0;
      notFull <= head_ptr+1==0;
   endrule

   rule tag_rule if (notFull);
      //tags.portA.request.put(BRAMRequest{write:True, responseOnWrite:False, address:head_ptr, datain:True});
      //tags.upd(head_ptr, True);
      tags[head_ptr] <= True;
      head_ptr <= head_ptr+1;
      notFull <= (head_ptr+2 != tail_ptr);
      tagFifo.enq(head_ptr);
   endrule

   method ActionValue#(Bit#(tsz)) getTag();
      let tag <- toGet(tagFifo).get();
      return tag;
   endmethod

   method Action returnTag(Bit#(tsz) tag) if (inited);
      retFifo.enq(tag);
   endmethod

   method ActionValue#(Bit#(tsz)) complete;
      comp_fifo.deq;
      return comp_fifo.first;
   endmethod

endmodule

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

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

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

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

// BSV Libraries
import BRAMFIFO::*;
import FIFO::*;
import FIFOF::*;
import Vector::*;
import GetPut::*;
import ClientServer::*;
import Assert::*;
import BRAM::*;
import RegFile::*;

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

interface TagGen#(numeric type numTags);
   method ActionValue#(Bit#(TLog#(numTags))) getTag;
   method Action returnTag(Bit#(TLog#(numTags)) tag);
   method ActionValue#(Bit#(TLog#(numTags))) complete;
endinterface

module mkTagGen(TagGen#(numTags))
   provisos(Log#(numTags,tsz));

   BRAM_Configure cfg = defaultValue;
   cfg.outFIFODepth = 1;
   //BRAM2Port#(Bit#(tsz),Bool) tags <- mkBRAM2Server(cfg);
   Vector#(numTags, Reg#(Bool)) tags <- replicateM(mkReg(False));
   //RegFile#(Bit#(tsz),Bool)     tags <- mkRegFile(0, fromInteger(valueOf(numTags)-1));
   Reg#(Bool)              notFull <- mkReg(False);
   Reg#(Bit#(tsz))        head_ptr <- mkReg(0);
   Reg#(Bit#(tsz))        tail_ptr <- mkReg(0);
   Reg#(Bool)               inited <- mkReg(False);
   FIFO#(Bit#(tsz))      comp_fifo <- mkFIFO;
   Reg#(Bit#(numTags))  comp_state <- mkReg(0);

   let retFifo <- mkFIFO;
   let tagFifo <- mkFIFO;

   //rule complete_rule0 (comp_state[0] != 0);
      //tags.portB.request.put(BRAMRequest{write:False, address:tail_ptr, datain: ?, responseOnWrite: ?});
   //endrule

   rule complete_rule1 (comp_state[0] != 0);
      //let rv <- tags.portB.response.get;
      //let rv = tags.sub(tail_ptr);
      let rv = tags[tail_ptr];
      if (!rv) begin
	 tail_ptr <= tail_ptr+1;
	 comp_state <= comp_state >> 1;
	 comp_fifo.enq(tail_ptr);
      end
   endrule

   // this used to be in the body of returnTag, but form some reason bsc does not
   // consider access to portA and portB to be conflict free **sigh**
   rule ret;
      let tag <- toGet(retFifo).get;
      //tags.portB.request.put(BRAMRequest{write:True, responseOnWrite:False, address:tag, datain:False});
      //tags.upd(tag, False);
      tags[tag] <= False;
      comp_state <= 1 | (comp_state << 1);
   endrule

   rule init(!inited);
      //tags.portA.request.put(BRAMRequest{write:True,address:head_ptr,responseOnWrite:False,datain:False});
      //tags.upd(head_ptr, False);
      //Not needed: tags[head_ptr] <= False;
      head_ptr <= head_ptr+1;
      inited <= head_ptr+1==0;
      notFull <= head_ptr+1==0;
   endrule

   rule tag if (notFull);
      //tags.portA.request.put(BRAMRequest{write:True, responseOnWrite:False, address:head_ptr, datain:True});
      //tags.upd(head_ptr, True);
      tags[head_ptr] <= True;
      head_ptr <= head_ptr+1;
      notFull <= (head_ptr+2 != tail_ptr);
      tagFifo.enq(head_ptr);
   endrule

   method ActionValue#(Bit#(tsz)) getTag();
      let tag <- toGet(tagFifo).get();
      return tag;
   endmethod

   method Action returnTag(Bit#(tsz) tag) if (inited);
      retFifo.enq(tag);
   endmethod

   method ActionValue#(Bit#(tsz)) complete;
      comp_fifo.deq;
      return comp_fifo.first;
   endmethod

endmodule


adjust memread end condition

adjust memread end condition

Change-Id: Ia1330d42d1b8d265f9e267e3ed4911a2f196a802

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

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

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

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

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

import Arith::*;
import Pipe::*;
import MemTypes::*;
import MemreadEngine::*;
import Pipe::*;

`ifdef NumEngineServers
typedef `NumEngineServers NumEngineServers;
`else
typedef 1 NumEngineServers;
`endif

interface MemreadRequest;
   method Action startRead(Bit#(32) pointer, Bit#(32) numWords, Bit#(32) burstLen, Bit#(32) iterCnt);
   method Action getStateDbg();
endinterface

interface Memread;
   interface MemreadRequest request;
   interface ObjectReadClient#(64) dmaClient;
endinterface

interface MemreadIndication;
   method Action started(Bit#(32) numWords);
   method Action reportStateDbg(Bit#(32) streamRdCnt, Bit#(32) mismatchCount);
   method Action readDone(Bit#(32) mismatchCount);
endinterface

module mkMemread#(MemreadIndication indication) (Memread);

   Reg#(ObjectPointer)   pointer <- mkReg(0);
   Reg#(Bit#(32))       numWords <- mkReg(0);
   Reg#(Bit#(32))       burstLen <- mkReg(0);
   Reg#(Bit#(32))    mismatchCnt <- mkReg(0);
   FIFO#(void)                cf <- mkSizedFIFO(1);

   Reg#(Bit#(32))                                   iterCnt <- mkReg(0);
   Vector#(NumEngineServers, Reg#(Bit#(32)))       iterCnts <- replicateM(mkReg(0));
   Vector#(NumEngineServers, Reg#(Bit#(32)))        srcGens <- replicateM(mkReg(0));
   Vector#(NumEngineServers, Reg#(Bit#(32)))   valuesToRead <- replicateM(mkReg(0));
   Vector#(NumEngineServers, Reg#(Bit#(32))) mismatchCounts <- replicateM(mkReg(0));
   MemreadEngineV#(64,2,NumEngineServers)                re <- mkMemreadEngine;
   Vector#(NumEngineServers, FIFOF#(Bit#(32))) mismatchFifos <- replicateM(mkFIFOF);
   Bit#(ObjectOffsetSize) chunk = (extend(numWords)/fromInteger(valueOf(NumEngineServers)))*4;

   Vector#(NumEngineServers, RangePipeIfc#(Bit#(32)))     rangePipeIfcs <- replicateM(mkRangePipeOut);
   function PipeOut#(a) getRangePipePipe(RangePipeIfc#(a) rpi); return rpi.pipe; endfunction
   Vector#(NumEngineServers, PipeOut#(Vector#(1,Bit#(32)))) rangePipes = map(mapPipe(replicate), map(getRangePipePipe, rangePipeIfcs));
   Vector#(NumEngineServers, PipeOut#(Vector#(2,Bit#(32)))) srcGenPipes <- mapM(mkUnfunnel, rangePipes);
   function Vector#(2,Bit#(32)) split(Bit#(64) v); return unpack(v); endfunction
   Vector#(NumEngineServers, PipeOut#(Vector#(2,Bit#(32)))) readPipes <- mapM(mkMapPipe(split), re.dataPipes);

   function Vector#(n, Bool) vcompare(Vector#(n, a) x, Vector#(n, a) y) provisos (Eq#(a));
      return map(uncurry(eq), zip(x,y));
   endfunction
   Vector#(NumEngineServers, PipeOut#(Vector#(2, Bool)))  mismatchPipes <- mapM(uncurry(mkJoinBuffered(vcompare)), zip(readPipes, srcGenPipes));

   for(Integer i = 0; i < valueOf(NumEngineServers); i=i+1) begin
      rule start (iterCnts[i] > 0);
	 re.readServers[i].request.put(MemengineCmd{pointer:pointer, base:fromInteger(i)*chunk, len:truncate(chunk), burstLen:truncate(burstLen*4)});
	 $display("start %d, %d", i, iterCnts[i]);
	 iterCnts[i] <= iterCnts[i]-1;

	 Bit#(32) base = fromInteger(i)*(truncate(chunk)/4);
	 Bit#(32) limit = base + truncate(chunk)/4;
	 let rangeConfig = RangeConfig { xbase: base, xlimit: limit, xstep: 1 };
	 rangePipeIfcs[i].start(rangeConfig);

      endrule
      rule finish;
	 $display("finish %d", i);
	 let rv <- re.readServers[i].response.get;
      endrule
      rule check;
	 let bv <- toGet(mismatchPipes[i]).get();
	 let mismatch = !bv[0] || !bv[1];
	 let mc = mismatchCounts[i] + (mismatch ? 1 : 0);

	 mismatchCounts[i] <= mc;

	 let newValuesToRead = valuesToRead[i] - 2;

	 if (valuesToRead[i] <= 2) begin
	    mismatchFifos[i].enq(mc);
	    newValuesToRead = truncate(chunk/4);
	 end
	 valuesToRead[i] <= newValuesToRead;

      endrule
   end

   PipeOut#(Vector#(NumEngineServers, Bit#(32))) mismatchCountsPipe <- mkJoinVector(id, map(toPipeOut, mismatchFifos));
   PipeOut#(Bit#(32)) mismatchCountPipe <- mkReducePipe(uncurry(add), mismatchCountsPipe);

   rule indicate_finish;
      let mc <- toGet(mismatchCountPipe).get();
      mc = mc + mismatchCnt;
      if (iterCnt == 1) begin
	 cf.deq;
	 indication.readDone(mc);
	 mc = 0;
      end
      mismatchCnt <= mc;
      iterCnt <= iterCnt - 1;
   endrule

   interface dmaClient = re.dmaClient;
   interface MemreadRequest request;
      method Action startRead(Bit#(32) rp, Bit#(32) nw, Bit#(32) bl, Bit#(32) ic);
	 indication.started(nw);
	 pointer <= rp;
	 cf.enq(?);
	 numWords  <= nw;
	 burstLen  <= bl;
	 iterCnt <= ic;
	 for(Integer i = 0; i < valueOf(NumEngineServers); i=i+1) begin
	    iterCnts[i] <= ic;
	    mismatchCounts[i] <= 0;
	    valuesToRead[i] <= truncate(chunk/4);
	 end
      endmethod
   endinterface
endmodule

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

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

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

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

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

import Arith::*;
import Pipe::*;
import MemTypes::*;
import MemreadEngine::*;
import Pipe::*;

`ifdef NumEngineServers
typedef `NumEngineServers NumEngineServers;
`else
typedef 1 NumEngineServers;
`endif

interface MemreadRequest;
   method Action startRead(Bit#(32) pointer, Bit#(32) numWords, Bit#(32) burstLen, Bit#(32) iterCnt);
   method Action getStateDbg();
endinterface

interface Memread;
   interface MemreadRequest request;
   interface ObjectReadClient#(64) dmaClient;
endinterface

interface MemreadIndication;
   method Action started(Bit#(32) numWords);
   method Action reportStateDbg(Bit#(32) streamRdCnt, Bit#(32) mismatchCount);
   method Action readDone(Bit#(32) mismatchCount);
endinterface

module mkMemread#(MemreadIndication indication) (Memread);

   Reg#(ObjectPointer)   pointer <- mkReg(0);
   Reg#(Bit#(32))       numWords <- mkReg(0);
   Reg#(Bit#(32))       burstLen <- mkReg(0);
   Reg#(Bit#(32))    mismatchCnt <- mkReg(0);
   FIFO#(void)                cf <- mkSizedFIFO(1);

   Reg#(Bit#(32))                                   iterCnt <- mkReg(0);
   Vector#(NumEngineServers, Reg#(Bit#(32)))       iterCnts <- replicateM(mkReg(0));
   Vector#(NumEngineServers, Reg#(Bit#(32)))        srcGens <- replicateM(mkReg(0));
   Vector#(NumEngineServers, Reg#(Bit#(32))) mismatchCounts <- replicateM(mkReg(0));
   MemreadEngineV#(64,2,NumEngineServers)                re <- mkMemreadEngine;
   Vector#(NumEngineServers, FIFOF#(Bit#(32))) mismatchFifos <- replicateM(mkFIFOF);
   Bit#(ObjectOffsetSize) chunk = (extend(numWords)/fromInteger(valueOf(NumEngineServers)))*4;

   Vector#(NumEngineServers, RangePipeIfc#(Bit#(32)))     rangePipeIfcs <- replicateM(mkRangePipeOut);
   function PipeOut#(a) getRangePipePipe(RangePipeIfc#(a) rpi); return rpi.pipe; endfunction
   Vector#(NumEngineServers, PipeOut#(Vector#(1,Bit#(32)))) rangePipes = map(mapPipe(replicate), map(getRangePipePipe, rangePipeIfcs));
   Vector#(NumEngineServers, PipeOut#(Vector#(2,Bit#(32)))) srcGenPipes <- mapM(mkUnfunnel, rangePipes);
   function Vector#(2,Bit#(32)) split(Bit#(64) v); return unpack(v); endfunction
   Vector#(NumEngineServers, PipeOut#(Vector#(2,Bit#(32)))) readPipes <- mapM(mkMapPipe(split), re.dataPipes);

   function Vector#(n, Bool) vcompare(Vector#(n, a) x, Vector#(n, a) y) provisos (Eq#(a));
      return map(uncurry(eq), zip(x,y));
   endfunction
   Vector#(NumEngineServers, PipeOut#(Vector#(2, Bool)))  mismatchPipes <- mapM(uncurry(mkJoinBuffered(vcompare)), zip(readPipes, srcGenPipes));

   for(Integer i = 0; i < valueOf(NumEngineServers); i=i+1) begin
      rule start (iterCnts[i] > 0);
	 re.readServers[i].request.put(MemengineCmd{pointer:pointer, base:fromInteger(i)*chunk, len:truncate(chunk), burstLen:truncate(burstLen*4)});
	 $display("start %d, %d", i, iterCnts[i]);
	 iterCnts[i] <= iterCnts[i]-1;

	 Bit#(32) base = fromInteger(i)*(truncate(chunk)/4);
	 Bit#(32) limit = base + truncate(chunk)/4;
	 let rangeConfig = RangeConfig { xbase: base, xlimit: limit, xstep: 1 };
	 rangePipeIfcs[i].start(rangeConfig);

      endrule
      rule finish;
	 $display("finish %d", i);
	 let rv <- re.readServers[i].response.get;
	 // need to pipeline this also
	 //mismatchCnt <= mismatchCnt+mismatchCounts[i];
	 mismatchCounts[i] <= 0;
	 mismatchFifos[i].enq(mismatchCounts[i]);
      endrule
      rule check;
	 let bv <- toGet(mismatchPipes[i]).get();
	 let misMatch = !bv[0] || !bv[1];
	 mismatchCounts[i] <= mismatchCounts[i] + (misMatch ? 1 : 0);

      endrule
   end

   PipeOut#(Vector#(NumEngineServers, Bit#(32))) mismatchCountsPipe <- mkJoinVector(id, map(toPipeOut, mismatchFifos));
   PipeOut#(Bit#(32)) mismatchCountPipe <- mkReducePipe(uncurry(add), mismatchCountsPipe);

   rule indicate_finish;
      let mc <- toGet(mismatchCountPipe).get();
      mc = mc + mismatchCnt;
      if (iterCnt == 1) begin
	 cf.deq;
	 indication.readDone(mc);
	 mc = 0;
      end
      mismatchCnt <= mc;
      iterCnt <= iterCnt - 1;
   endrule

   interface dmaClient = re.dmaClient;
   interface MemreadRequest request;
      method Action startRead(Bit#(32) rp, Bit#(32) nw, Bit#(32) bl, Bit#(32) ic);
	 indication.started(nw);
	 pointer <= rp;
	 cf.enq(?);
	 numWords  <= nw;
	 burstLen  <= bl;
	 iterCnt <= ic;
	 for(Integer i = 0; i < valueOf(NumEngineServers); i=i+1) begin
	    iterCnts[i] <= ic;
	    mismatchCounts[i] <= 0;
	 end
      endmethod
   endinterface
endmodule