Example #1
0
    def construct(s,
                  MasterType=SomeMasterBlockingFL,
                  MinionType=SomeMinionFL,
                  nregs=16):
        ReqType, RespType = mk_xcel_msg(addr=clog2(nregs), data=32)
        s.master = MasterType(ReqType, RespType, nregs=nregs)
        s.minion = MinionType(ReqType, RespType, nregs=nregs)

        connect(s.master.xcel, s.minion.xcel)
Example #2
0
    def construct(s, DutType=ChecksumXcelCL, src_msgs=[], sink_msgs=[]):

        ReqType, RespType = mk_xcel_msg(5, 32)

        s.src = TestSrcCL(ReqType, src_msgs)
        s.dut = DutType()
        s.sink = TestSinkCL(ReqType, sink_msgs)

        connect(s.src.send, s.dut.xcel.req)
        connect(s.dut.xcel.resp, s.sink.recv)
Example #3
0
    def construct(s):

        # Interface

        ReqType, RespType = mk_xcel_msg(5, 32)

        s.xcel = XcelMinionIfcFL(read=s.read, write=s.write)

        # Components

        s.reg_file = [b32(0) for _ in range(6)]

        s.trace = "            "

        @s.update
        def up_clear_trace():
            s.trace = "            "

        s.add_constraints(U(up_clear_trace) < M(s.read))
        s.add_constraints(U(up_clear_trace) < M(s.write))
Example #4
0
from examples.ex02_cksum.ChecksumFL import checksum
from examples.ex02_cksum.utils import words_to_b128
from pymtl3 import *
from pymtl3.stdlib.queues import BypassQueueCL
from pymtl3.stdlib.connects import connect_pairs
from pymtl3.stdlib.ifcs import XcelMsgType, mk_xcel_msg
from pymtl3.stdlib.test_utils import TestSinkCL, TestSrcCL, run_sim

from ..ChecksumXcelCL import ChecksumXcelCL

#-------------------------------------------------------------------------
# Helper functions to create a sequence of req/resp msg
#-------------------------------------------------------------------------

Req, Resp = mk_xcel_msg(5, 32)
rd = XcelMsgType.READ
wr = XcelMsgType.WRITE


def mk_xcel_transaction(words):
    words = [b16(x) for x in words]
    bits = words_to_b128(words)
    reqs = []
    reqs.append(Req(wr, 0, bits[0:32]))
    reqs.append(Req(wr, 1, bits[32:64]))
    reqs.append(Req(wr, 2, bits[64:96]))
    reqs.append(Req(wr, 3, bits[96:128]))
    reqs.append(Req(wr, 4, 1))
    reqs.append(Req(rd, 5, 0))
Example #5
0
  def construct( s ):

    req_class, resp_class = mk_mem_msg( 8, 32, 32 )

    # Proc/Mngr Interface

    s.mngr2proc = RecvIfcRTL( Bits32 )
    s.proc2mngr = SendIfcRTL( Bits32 )

    # Instruction Memory Request/Response Interface

    s.imem = MemMasterIfcRTL( req_class, resp_class )

    # Data Memory Request/Response Interface

    s.dmem = MemMasterIfcRTL( req_class, resp_class )

    # Xcel Request/Response Interface

    xreq_class, xresp_class = mk_xcel_msg( 5, 32 )

    s.xcel = XcelMasterIfcRTL( xreq_class, xresp_class )

    # val_W port used for counting commited insts.

    s.commit_inst = OutPort( Bits1 )

    # Bypass queues

    s.imemreq_q   = BypassQueue2RTL( req_class, 2 )

    # We have to turn input receive interface into get interface

    s.imemresp_q  = BypassQueueRTL( resp_class, 1 )
    s.dmemresp_q  = BypassQueueRTL( resp_class, 1 )
    s.mngr2proc_q = BypassQueueRTL( Bits32, 1 )
    s.xcelresp_q  = BypassQueueRTL( xresp_class, 1 )

    # imem drop unit

    s.imemresp_drop = m = DropUnitRTL( Bits32 )
    m.in_.en  //= s.imemresp_q.deq.en
    m.in_.rdy //= s.imemresp_q.deq.rdy
    m.in_.ret //= s.imemresp_q.deq.ret.data

    # connect all the queues

    s.imemreq_q.deq   //= s.imem.req
    s.imemresp_q.enq  //= s.imem.resp
    s.dmemresp_q.enq  //= s.dmem.resp
    s.mngr2proc_q.enq //= s.mngr2proc
    s.xcelresp_q.enq  //= s.xcel.resp

    # Control

    s.ctrl = m = ProcCtrl()

    # imem port
    m.imemresp_drop //= s.imemresp_drop.drop
    m.imemreq_en    //= s.imemreq_q.enq.en
    m.imemreq_rdy   //= s.imemreq_q.enq.rdy
    m.imemresp_en   //= s.imemresp_drop.out.en
    m.imemresp_rdy  //= s.imemresp_drop.out.rdy

    # dmem port
    m.dmemreq_en    //= s.dmem.req.en
    m.dmemreq_rdy   //= s.dmem.req.rdy
    m.dmemreq_type  //= s.dmem.req.msg.type_
    m.dmemresp_en   //= s.dmemresp_q.deq.en
    m.dmemresp_rdy  //= s.dmemresp_q.deq.rdy

    # xcel port
    m.xcelreq_type  //= s.xcel.req.msg.type_

    m.xcelreq_en    //= s.xcel.req.en
    m.xcelreq_rdy   //= s.xcel.req.rdy
    m.xcelresp_en   //= s.xcelresp_q.deq.en
    m.xcelresp_rdy  //= s.xcelresp_q.deq.rdy

    # proc2mngr and mngr2proc
    m.proc2mngr_en  //= s.proc2mngr.en
    m.proc2mngr_rdy //= s.proc2mngr.rdy
    m.mngr2proc_en  //= s.mngr2proc_q.deq.en
    m.mngr2proc_rdy //= s.mngr2proc_q.deq.rdy

    # commit inst for counting
    m.commit_inst //= s.commit_inst

    # Dpath

    s.dpath = m = ProcDpath()

    # imem ports
    m.imemreq_addr  //= s.imemreq_q.enq.msg.addr
    m.imemresp_data //= s.imemresp_drop.out.ret

    # dmem ports
    m.dmemreq_addr  //= s.dmem.req.msg.addr
    m.dmemreq_data  //= s.dmem.req.msg.data
    m.dmemresp_data //= s.dmemresp_q.deq.ret.data

    # xcel ports
    m.xcelreq_addr  //= s.xcel.req.msg.addr
    m.xcelreq_data  //= s.xcel.req.msg.data
    m.xcelresp_data //= s.xcelresp_q.deq.ret.data

    # mngr
    m.mngr2proc_data //= s.mngr2proc_q.deq.ret
    m.proc2mngr_data //= s.proc2mngr.msg

    # Ctrl <-> Dpath

    s.ctrl.reg_en_F        //= s.dpath.reg_en_F
    s.ctrl.pc_sel_F        //= s.dpath.pc_sel_F

    s.ctrl.reg_en_D        //= s.dpath.reg_en_D
    s.ctrl.op1_byp_sel_D   //= s.dpath.op1_byp_sel_D
    s.ctrl.op2_byp_sel_D   //= s.dpath.op2_byp_sel_D
    s.ctrl.op2_sel_D       //= s.dpath.op2_sel_D
    s.ctrl.imm_type_D      //= s.dpath.imm_type_D

    s.ctrl.reg_en_X        //= s.dpath.reg_en_X
    s.ctrl.alu_fn_X        //= s.dpath.alu_fn_X

    s.ctrl.reg_en_M        //= s.dpath.reg_en_M
    s.ctrl.wb_result_sel_M //= s.dpath.wb_result_sel_M

    s.ctrl.reg_en_W        //= s.dpath.reg_en_W
    s.ctrl.rf_waddr_W      //= s.dpath.rf_waddr_W
    s.ctrl.rf_wen_W        //= s.dpath.rf_wen_W

    s.dpath.inst_D         //= s.ctrl.inst_D
    s.dpath.ne_X           //= s.ctrl.ne_X
Example #6
0
    def construct(s):
        # FIXME gc??
        # s.x = bytearray(2**25)

        # Interface

        ReqType, RespType = mk_xcel_msg(5, 32)
        s.xcel = XcelMinionIfcRTL(ReqType, RespType)

        # State encoding

        s.XCFG = b2(0)
        s.WAIT = b2(1)
        s.BUSY = b2(2)

        # Local parameters

        s.RD = XcelMsgType.READ
        s.WR = XcelMsgType.WRITE

        # Components

        s.in_q = NormalQueueRTL(ReqType, num_entries=2)
        s.reg_file = [Reg(Bits32) for _ in range(6)]
        s.checksum_unit = ChecksumRTL()

        s.state = Wire(Bits2)
        s.state_next = Wire(Bits2)
        s.start_pulse = Wire(Bits1)

        # Connections

        connect(s.xcel.req, s.in_q.enq)
        connect(s.checksum_unit.recv.msg[0:32], s.reg_file[0].out)
        connect(s.checksum_unit.recv.msg[32:64], s.reg_file[1].out)
        connect(s.checksum_unit.recv.msg[64:96], s.reg_file[2].out)
        connect(s.checksum_unit.recv.msg[96:128], s.reg_file[3].out)

        # Logic

        @s.update
        def up_start_pulse():
            s.start_pulse = (s.xcel.resp.en and s.in_q.deq.msg.type_ == s.WR
                             and s.in_q.deq.msg.addr == b5(4))

        @s.update
        def up_state_next():
            if s.state == s.XCFG:
                s.state_next = (s.WAIT if s.start_pulse
                                & ~s.checksum_unit.recv.rdy else
                                s.BUSY if s.start_pulse
                                & s.checksum_unit.recv.rdy else s.XCFG)

            elif s.state == s.WAIT:
                s.state_next = s.BUSY if s.checksum_unit.recv.rdy else s.WAIT

            else:  # s.state == s.BUSY
                s.state_next = s.XCFG if s.checksum_unit.send.en else s.BUSY

        @s.update_on_edge
        def up_state():
            if s.reset:
                s.state = s.XCFG
            else:
                s.state = s.state_next

        @s.update
        def up_fsm_output():
            if s.state == s.XCFG:
                s.in_q.deq.en = s.in_q.deq.rdy
                s.xcel.resp.en = s.in_q.deq.rdy
                s.checksum_unit.recv.en = s.start_pulse & s.checksum_unit.recv.rdy
                s.checksum_unit.send.rdy = b1(1)

            elif s.state == s.WAIT:
                s.in_q.deq.en = b1(0)
                s.xcel.resp.en = b1(0)
                s.checksum_unit.recv.en = s.checksum_unit.recv.rdy
                s.checksum_unit.send.rdy = b1(1)

            else:  # s.state == s.BUSY:
                s.in_q.deq.en = b1(0)
                s.xcel.resp.en = b1(0)
                s.checksum_unit.recv.en = b1(0)
                s.checksum_unit.send.rdy = b1(1)

        @s.update
        def up_resp_msg():
            s.xcel.resp.msg.type_ = s.in_q.deq.msg.type_
            s.xcel.resp.msg.data = b32(0)
            if s.in_q.deq.msg.type_ == s.RD:
                s.xcel.resp.msg.data = s.reg_file[s.in_q.deq.msg.addr[0:3]].out

        @s.update
        def up_wr_regfile():
            for i in range(6):
                s.reg_file[i].in_ = s.reg_file[i].out

            if s.in_q.deq.en and s.in_q.deq.msg.type_ == s.WR:
                for i in range(6):
                    s.reg_file[i].in_ = (s.in_q.deq.msg.data
                                         if b5(i) == s.in_q.deq.msg.addr else
                                         s.reg_file[i].out)

            if s.checksum_unit.send.en:
                s.reg_file[5].in_ = s.checksum_unit.send.msg
Example #7
0
Author : Yanghui Ou
  Date : June 14, 2019
"""
from __future__ import absolute_import, division, print_function

from pymtl3 import *
from pymtl3.stdlib.ifcs import mk_xcel_msg

from ..ChecksumXcelFL import ChecksumXcelFL

#-------------------------------------------------------------------------
# Wrap Xcel into a function
#-------------------------------------------------------------------------

Req, Resp = mk_xcel_msg(3, 32)


def checksum_xcel_fl(words):
    assert len(words) == 8

    # Create a simulator using ChecksumXcelFL
    dut = ChecksumXcelFL()
    dut.elaborate()
    dut.apply(SimulationPass)

    # Transfer checksum input
    for i in range(4):
        data = concat(words[i * 2 + 1], words[i * 2])
        dut.xcel.write(i, data)
    def construct(s):

        # Interface

        ReqType, RespType = mk_xcel_msg(5, 32)
        s.RespType = RespType

        s.xcel = XcelMinionIfcCL(ReqType, RespType)

        # State encoding

        s.XCFG = 0
        s.WAIT = 1
        s.BUSY = 2

        # Local paramters

        RD = XcelMsgType.READ
        WR = XcelMsgType.WRITE

        # Components

        s.in_q = NormalQueueCL(num_entries=2)
        s.reg_file = [b32(0) for _ in range(6)]
        s.checksum_unit = ChecksumCL()

        s.state = s.XCFG

        s.out_q = BypassQueueCL(num_entries=1)

        s.connect(s.checksum_unit.send, s.out_q.enq)
        s.connect(s.xcel.req, s.in_q.enq)

        @s.update
        def up_tick():
            if s.state == s.XCFG:
                # Dequeue a request message from input queue and send response.
                if s.in_q.deq.rdy() and s.xcel.resp.rdy():
                    req = s.in_q.deq()
                    if req.type_ == RD:
                        s.xcel.resp(s.RespType(RD, s.reg_file[int(req.addr)]))
                    elif req.type_ == WR:
                        s.reg_file[int(req.addr)] = req.data
                        s.xcel.resp(s.RespType(WR, 0))

                        # If the go bit is written
                        if req.addr == 4:
                            if s.checksum_unit.recv.rdy():
                                s.state = s.BUSY
                                words = s.get_words()
                                s.checksum_unit.recv(words_to_b128(words))
                            else:
                                s.state = s.WAIT

            elif s.state == s.WAIT:
                if s.checksum_unit.recv.rdy():
                    words = s.get_words()
                    s.checksum_unit.recv(words_to_b128(words))
                    s.state = s.BUSY

            else:  # s.state == s.BUSY
                if s.out_q.deq.rdy():
                    s.reg_file[5] = s.out_q.deq()
                    s.state = s.XCFG
    def construct(s):

        req_class, resp_class = mk_mem_msg(8, 32, 32)

        # Proc/Mngr Interface

        s.mngr2proc = RecvIfcRTL(Bits32)
        s.proc2mngr = SendIfcRTL(Bits32)

        # Instruction Memory Request/Response Interface

        s.imem = MemMasterIfcRTL(req_class, resp_class)

        # Data Memory Request/Response Interface

        s.dmem = MemMasterIfcRTL(req_class, resp_class)

        # Xcel Request/Response Interface

        xreq_class, xresp_class = mk_xcel_msg(5, 32)

        s.xcel = XcelMasterIfcRTL(xreq_class, xresp_class)

        # val_W port used for counting commited insts.

        s.commit_inst = OutPort(Bits1)

        # imem drop unit

        s.imemresp_drop = m = DropUnitRTL(Bits32)
        connect_pairs(
            m.in_.en,
            s.imem.resp.en,
            m.in_.rdy,
            s.imem.resp.rdy,
            m.in_.msg,
            s.imem.resp.msg.data,
        )

        # Bypass queues

        s.imemreq_q = BypassQueue2RTL(req_class, 2)(deq=s.imem.req)

        # We have to turn input receive interface into get interface

        s.imemresp_q = BypassQueueRTL(Bits32, 1)(enq=s.imemresp_drop.out)
        s.dmemresp_q = BypassQueueRTL(resp_class, 1)(enq=s.dmem.resp)
        s.mngr2proc_q = BypassQueueRTL(Bits32, 1)(enq=s.mngr2proc)
        s.xcelresp_q = BypassQueueRTL(xresp_class, 1)(enq=s.xcel.resp)

        # Control

        s.ctrl = ProcCtrl()(

            # imem port
            imemresp_drop=s.imemresp_drop.drop,
            imemreq_en=s.imemreq_q.enq.en,
            imemreq_rdy=s.imemreq_q.enq.rdy,
            imemresp_en=s.imemresp_q.deq.en,
            imemresp_rdy=s.imemresp_q.deq.rdy,

            # dmem port
            dmemreq_en=s.dmem.req.en,
            dmemreq_rdy=s.dmem.req.rdy,
            dmemreq_type=s.dmem.req.msg.type_,
            dmemresp_en=s.dmemresp_q.deq.en,
            dmemresp_rdy=s.dmemresp_q.deq.rdy,

            # xcel port
            xcelreq_en=s.xcel.req.en,
            xcelreq_rdy=s.xcel.req.rdy,
            xcelresp_en=s.xcelresp_q.deq.en,
            xcelresp_rdy=s.xcelresp_q.deq.rdy,

            # proc2mngr and mngr2proc
            proc2mngr_en=s.proc2mngr.en,
            proc2mngr_rdy=s.proc2mngr.rdy,
            mngr2proc_en=s.mngr2proc_q.deq.en,
            mngr2proc_rdy=s.mngr2proc_q.deq.rdy,

            # commit inst for counting
            commit_inst=s.commit_inst)

        # Dpath

        s.dpath = ProcDpath()(

            # imem ports
            imemreq_addr=s.imemreq_q.enq.msg.addr,
            imemresp_data=s.imemresp_q.deq.msg,

            # dmem ports
            dmemreq_addr=s.dmem.req.msg.addr,
            dmemreq_data=s.dmem.req.msg.data,
            dmemresp_data=s.dmemresp_q.deq.msg.data,

            # xcel ports
            xcelresp_data=s.xcelresp_q.deq.msg.data,

            # mngr
            mngr2proc_data=s.mngr2proc_q.deq.msg,
            proc2mngr_data=s.proc2mngr.msg,
        )

        @s.update
        def up_xcelreq():
            s.xcel.req.msg = xreq_class(
                s.ctrl.xcelreq_type,
                s.dpath.xcelreq_addr,
                s.dpath.xcelreq_data,
            )

        # Ctrl <-> Dpath

        connect_pairs(
            s.ctrl.reg_en_F,
            s.dpath.reg_en_F,
            s.ctrl.pc_sel_F,
            s.dpath.pc_sel_F,
            s.ctrl.reg_en_D,
            s.dpath.reg_en_D,
            s.ctrl.op1_byp_sel_D,
            s.dpath.op1_byp_sel_D,
            s.ctrl.op2_byp_sel_D,
            s.dpath.op2_byp_sel_D,
            s.ctrl.op1_sel_D,
            s.dpath.op1_sel_D,
            s.ctrl.op2_sel_D,
            s.dpath.op2_sel_D,
            s.ctrl.imm_type_D,
            s.dpath.imm_type_D,
            s.ctrl.reg_en_X,
            s.dpath.reg_en_X,
            s.ctrl.alu_fn_X,
            s.dpath.alu_fn_X,
            s.ctrl.reg_en_M,
            s.dpath.reg_en_M,
            s.ctrl.wb_result_sel_M,
            s.dpath.wb_result_sel_M,
            s.ctrl.mask_sel_W,
            s.dpath.mask_sel_W,
            s.ctrl.reg_en_W,
            s.dpath.reg_en_W,
            s.ctrl.rf_waddr_W,
            s.dpath.rf_waddr_W,
            s.ctrl.rf_wen_W,
            s.dpath.rf_wen_W,
            s.dpath.inst_D,
            s.ctrl.inst_D,
            s.dpath.ne_X,
            s.ctrl.ne_X,
        )
Example #10
0
    def construct(s):
        # Interface

        ReqType, RespType = mk_xcel_msg(5, 32)
        s.xcel = XcelMinionIfcRTL(ReqType, RespType)

        # State encoding

        s.XCFG = b2(0)
        s.WAIT = b2(1)
        s.BUSY = b2(2)

        # Components

        s.in_q = NormalQueueRTL(ReqType, num_entries=2)
        s.reg_file = [Reg(Bits32) for _ in range(6)]
        s.checksum_unit = ChecksumRTL()

        s.state = Wire(Bits2)
        s.state_next = Wire(Bits2)
        s.start_pulse = Wire(Bits1)

        # Connections

        s.xcel.req //= s.in_q.enq
        s.checksum_unit.recv.msg[0:32] //= s.reg_file[0].out
        s.checksum_unit.recv.msg[32:64] //= s.reg_file[1].out
        s.checksum_unit.recv.msg[64:96] //= s.reg_file[2].out
        s.checksum_unit.recv.msg[96:128] //= s.reg_file[3].out

        # Logic

        @update
        def up_start_pulse():
            s.start_pulse @=   s.xcel.resp.en & \
                             ( s.in_q.deq.ret.type_ == XcelMsgType.WRITE ) & \
                             ( s.in_q.deq.ret.addr == 4 )

        @update
        def up_state_next():
            if s.state == s.XCFG:
                s.state_next @= (s.WAIT if s.start_pulse
                                 & ~s.checksum_unit.recv.rdy else
                                 s.BUSY if s.start_pulse
                                 & s.checksum_unit.recv.rdy else s.XCFG)

            elif s.state == s.WAIT:
                s.state_next @= s.BUSY if s.checksum_unit.recv.rdy else s.WAIT

            else:  # s.state == s.BUSY
                s.state_next @= s.XCFG if s.checksum_unit.send.en else s.BUSY

        @update_ff
        def up_state():
            if s.reset:
                s.state <<= s.XCFG
            else:
                s.state <<= s.state_next

        @update
        def up_fsm_output():
            if s.state == s.XCFG:
                s.in_q.deq.en @= s.in_q.deq.rdy
                s.xcel.resp.en @= s.in_q.deq.rdy
                s.checksum_unit.recv.en @= s.start_pulse & s.checksum_unit.recv.rdy
                s.checksum_unit.send.rdy @= 1

            elif s.state == s.WAIT:
                s.in_q.deq.en @= 0
                s.xcel.resp.en @= 0
                s.checksum_unit.recv.en @= s.checksum_unit.recv.rdy
                s.checksum_unit.send.rdy @= 1

            else:  # s.state == s.BUSY:
                s.in_q.deq.en @= 0
                s.xcel.resp.en @= 0
                s.checksum_unit.recv.en @= 0
                s.checksum_unit.send.rdy @= 1

        @update
        def up_resp_msg():
            s.xcel.resp.msg.type_ @= s.in_q.deq.ret.type_
            s.xcel.resp.msg.data @= 0
            if s.in_q.deq.ret.type_ == XcelMsgType.READ:
                s.xcel.resp.msg.data @= s.reg_file[
                    s.in_q.deq.ret.addr[0:3]].out

        @update
        def up_wr_regfile():
            for i in range(6):
                s.reg_file[i].in_ @= s.reg_file[i].out

            if s.in_q.deq.en & (s.in_q.deq.ret.type_ == XcelMsgType.WRITE):
                for i in range(6):
                    s.reg_file[i].in_ @= (s.in_q.deq.ret.data
                                          if b5(i) == s.in_q.deq.ret.addr else
                                          s.reg_file[i].out)

            if s.checksum_unit.send.en:
                s.reg_file[5].in_ @= s.checksum_unit.send.msg
Example #11
0
  def construct( s ):

    memreq_cls, memresp_cls = mk_mem_msg( 8,32,32 )
    xreq_class, xresp_class = mk_xcel_msg(5,32)

    # Interface

    s.commit_inst = OutPort( Bits1 )

    s.imem = MemMasterIfcCL( memreq_cls, memresp_cls )
    s.dmem = MemMasterIfcCL( memreq_cls, memresp_cls )

    s.xcel = XcelMasterIfcCL( xreq_class, xresp_class )

    s.proc2mngr = CallerIfcCL()
    s.mngr2proc = CalleeIfcCL()

    # Buffers to hold input messages

    s.imemresp_q  = DelayPipeDeqCL(0)
    s.imemresp_q.enq //= s.imem.resp

    s.dmemresp_q  = DelayPipeDeqCL(1)
    s.dmemresp_q.enq //= s.dmem.resp

    s.mngr2proc_q = DelayPipeDeqCL(1)
    s.mngr2proc_q.enq //= s.mngr2proc

    s.xcelresp_q  = DelayPipeDeqCL(0)
    s.xcelresp_q.enq //= s.xcel.resp

    s.pc = b32( 0x200 )
    s.R  = RegisterFile( 32 )

    s.F_DXM_queue = PipeQueueCL(1)
    s.DXM_W_queue = PipeQueueCL(1)

    s.F_status   = PipelineStatus.idle
    s.DXM_status = PipelineStatus.idle
    s.W_status   = PipelineStatus.idle

    @update_once
    def F():
      s.F_status = PipelineStatus.idle

      if s.reset:
        s.pc = b32( 0x200 )
        return

      if s.imem.req.rdy() and s.F_DXM_queue.enq.rdy():
        if s.redirected_pc_DXM >= 0:
          s.imem.req( memreq_cls( MemMsgType.READ, 0, s.redirected_pc_DXM ) )
          s.pc = s.redirected_pc_DXM
        else:
          s.imem.req( memreq_cls( MemMsgType.READ, 0, s.pc ) )

        s.F_DXM_queue.enq( s.pc )
        s.F_status = PipelineStatus.work
        s.pc += 4
      else:
        s.F_status = PipelineStatus.stall

    s.redirected_pc_DXM = -1

    s.raw_inst = b32(0)

    @update_once
    def DXM():
      s.redirected_pc_DXM = -1
      s.DXM_status = PipelineStatus.idle

      if s.F_DXM_queue.deq.rdy() and s.imemresp_q.deq.rdy():

        if not s.DXM_W_queue.enq.rdy():
          s.DXM_status = PipelineStatus.stall
        else:
          pc = s.F_DXM_queue.peek()

          s.raw_inst = s.imemresp_q.peek().data
          inst       = TinyRV0Inst( s.raw_inst )
          inst_name  = inst.name

          s.DXM_status = PipelineStatus.work

          if inst_name == "nop":
            pass
          elif inst_name == "add":
            s.DXM_W_queue.enq( (inst.rd, s.R[ inst.rs1 ] + s.R[ inst.rs2 ], DXM_W.arith) )
          elif inst_name == "sll":
            s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1] << (s.R[inst.rs2] & 0x1F), DXM_W.arith) )
          elif inst_name == "srl":
            s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1] >> (s.R[inst.rs2].uint() & 0x1F), DXM_W.arith) )

          # ''' TUTORIAL TASK ''''''''''''''''''''''''''''''''''''''''''''
          # Implement instruction AND in CL processor
          # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''\/
          #; Make an "elif" statement here to implement instruction AND
          #; that applies bit-wise "and" operator to rs1 and rs2 and
          #; pass the result to the pipeline.

          elif inst_name == "and":
            s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1] & s.R[inst.rs2], DXM_W.arith) )

          # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''/\

          elif inst_name == "addi":
            s.DXM_W_queue.enq( (inst.rd, s.R[ inst.rs1 ] + sext(inst.i_imm, 32), DXM_W.arith) )
          elif inst_name == "sw":
            if s.dmem.req.rdy():
              s.dmem.req( memreq_cls( MemMsgType.WRITE, 0,
                                      s.R[ inst.rs1 ] + sext(inst.s_imm, 32),
                                      0,
                                      s.R[ inst.rs2 ] ) )
              s.DXM_W_queue.enq( (0, 0, DXM_W.mem) )
            else:
              s.DXM_status = PipelineStatus.stall

          elif inst_name == "lw":
            if s.dmem.req.rdy():
              s.dmem.req( memreq_cls( MemMsgType.READ, 0,
                                      s.R[ inst.rs1 ] + sext(inst.i_imm, 32),
                                      0 ) )
              s.DXM_W_queue.enq( (inst.rd, 0, DXM_W.mem) )
            else:
              s.DXM_status = PipelineStatus.stall

          elif inst_name == "bne":
            if s.R[ inst.rs1 ] != s.R[ inst.rs2 ]:
              s.redirected_pc_DXM = pc + sext(inst.b_imm, 32)
            s.DXM_W_queue.enq( None )

          elif inst_name == "csrw":
            if inst.csrnum == 0x7C0: # CSR: proc2mngr
              # We execute csrw in W stage
              s.DXM_W_queue.enq( (0, s.R[ inst.rs1 ], DXM_W.mngr) )

            elif 0x7E0 <= inst.csrnum <= 0x7FF:
              if s.xcel.req.rdy():
                s.xcel.req( xreq_class( XcelMsgType.WRITE, inst.csrnum[0:5], s.R[inst.rs1]) )
                s.DXM_W_queue.enq( (0, 0, DXM_W.xcel) )
              else:
                s.DXM_status = PipelineStatus.stall
          elif inst_name == "csrr":
            if inst.csrnum == 0xFC0: # CSR: mngr2proc
              if s.mngr2proc_q.deq.rdy():
                s.DXM_W_queue.enq( (inst.rd, s.mngr2proc_q.deq(), DXM_W.arith) )
              else:
                s.DXM_status = PipelineStatus.stall
            elif 0x7E0 <= inst.csrnum <= 0x7FF:
              if s.xcel.req.rdy():
                s.xcel.req( xreq_class( XcelMsgType.READ, inst.csrnum[0:5], s.R[inst.rs1]) )
                s.DXM_W_queue.enq( (inst.rd, 0, DXM_W.xcel) )
              else:
                s.DXM_status = PipelineStatus.stall

          # If we execute any instruction, we pop from queues
          if s.DXM_status == PipelineStatus.work:
            s.F_DXM_queue.deq()
            s.imemresp_q.deq()

    s.rd = b5(0)

    @update_once
    def W():
      s.commit_inst @= 0
      s.W_status = PipelineStatus.idle

      if s.DXM_W_queue.deq.rdy():
        entry = s.DXM_W_queue.peek()
        if entry is not None:
          rd, data, entry_type = entry
          s.rd = rd

          if entry_type == DXM_W.mem:
            if s.dmemresp_q.deq.rdy():
              if rd > 0: # load
                s.R[ rd ] = Bits32( s.dmemresp_q.deq().data )
              else: # store
                s.dmemresp_q.deq()

              s.W_status = PipelineStatus.work

            else:
              s.W_status = PipelineStatus.stall

          elif entry_type == DXM_W.xcel:
            if s.xcelresp_q.deq.rdy():
              if rd > 0: # csrr
                s.R[ rd ] = Bits32( s.xcelresp_q.deq().data )
              else: # csrw
                s.xcelresp_q.deq()

              s.W_status = PipelineStatus.work
            else:
              s.W_status = PipelineStatus.stall

          elif entry_type == DXM_W.mngr:
            if s.proc2mngr.rdy():
              s.proc2mngr( data )
              s.W_status = PipelineStatus.work
            else:
              s.W_status = PipelineStatus.stall

          else: # other WB insts
            assert entry_type == DXM_W.arith
            if rd > 0: s.R[ rd ] = Bits32( data )
            s.W_status = PipelineStatus.work

        else: # non-WB insts
          s.W_status = PipelineStatus.work

      if s.W_status == PipelineStatus.work:
        s.DXM_W_queue.deq()
        s.commit_inst @= 1