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