def construct(s, nbits=32): dtype = mk_bits(32) xreq_class, xresp_class = mk_xcel_msg(5, nbits) s.xcel = XcelMinionIfcRTL(xreq_class, xresp_class) s.xcelreq_q = NormalQueueRTL(xreq_class, 2) s.xcelreq_q.enq //= s.xcel.req s.xr0 = RegEn(dtype) s.xr0.in_ //= s.xcelreq_q.deq.ret.data @update def up_null_xcel(): if s.xcelreq_q.deq.rdy & s.xcel.resp.rdy: s.xcelreq_q.deq.en @= 1 s.xcel.resp.en @= 1 s.xcel.resp.msg.type_ @= s.xcelreq_q.deq.ret.type_ if s.xcelreq_q.deq.ret.type_ == XcelMsgType.WRITE: s.xr0.en @= 1 s.xcel.resp.msg.data @= 0 else: s.xr0.en @= 0 s.xcel.resp.msg.data @= s.xr0.out else: s.xcelreq_q.deq.en @= 0 s.xcel.resp.en @= 0 s.xr0.en @= 0 s.xcel.resp.msg.data @= 0 s.xcel.resp.msg.type_ @= 0
def construct( s, nbits=32 ): dtype = mk_bits(32) XcelMsgType_WRITE = XcelMsgType.WRITE xreq_class, xresp_class = mk_xcel_msg( 5,nbits ) s.xcel = XcelMinionIfcRTL( xreq_class, xresp_class ) s.xcelreq_q = NormalQueueRTL( xreq_class, 2 )( enq = s.xcel.req ) s.xr0 = RegEn( dtype )( in_ = s.xcelreq_q.deq.msg.data ) @s.update def up_null_xcel(): if s.xcelreq_q.deq.rdy & s.xcel.resp.rdy: s.xcelreq_q.deq.en = b1(1) s.xcel.resp.en = b1(1) s.xcel.resp.msg.type_ = s.xcelreq_q.deq.msg.type_ if s.xcelreq_q.deq.msg.type_ == XcelMsgType_WRITE: s.xr0.en = b1(1) s.xcel.resp.msg.data = dtype(0) else: s.xr0.en = b1(0) s.xcel.resp.msg.data = s.xr0.out else: s.xcelreq_q.deq.en = b1(0) s.xcel.resp.en = b1(0) s.xr0.en = b1(0) s.xcel.resp.msg.data = dtype(0) s.xcel.resp.msg.type_ = b1(0)
def construct( s ): # Interface, Buffers to hold request/response messages s.commit_inst = OutPort( Bits1 ) s.imem = MemMasterIfcFL() s.dmem = MemMasterIfcFL() s.xcel = XcelMasterIfcFL( *mk_xcel_msg( 5, 32 ) ) s.proc2mngr = SendIfcFL() s.mngr2proc = GetIfcFL() # Internal data structures s.PC = b32( 0x200 ) s.R = RegisterFile(32) s.raw_inst = None @s.update def up_ProcFL(): if s.reset: s.PC = b32( 0x200 ) return s.commit_inst = Bits1( 0 ) try: s.raw_inst = s.imem.read( s.PC, 4 ) # line trace inst = TinyRV0Inst( s.raw_inst ) inst_name = inst.name #----------------------------------------------------------------------- # Register-register arithmetic, logical, and comparison instructions #----------------------------------------------------------------------- if inst_name == "nop": s.PC += 4 elif inst_name == "add": s.R[inst.rd] = s.R[inst.rs1] + s.R[inst.rs2] s.PC += 4 elif inst_name == "sub": s.R[inst.rd] = s.R[inst.rs1] - s.R[inst.rs2] s.PC += 4 elif inst_name == "mul": s.R[ inst.rd ] = s.R[inst.rs1] * s.R[inst.rs2] s.PC += 4 elif inst_name == "sll": s.R[inst.rd] = s.R[inst.rs1] << (s.R[inst.rs2] & 0x1F) s.PC += 4 elif inst_name == "slt": s.R[inst.rd] = s.R[inst.rs1].int() < s.R[inst.rs2].int() s.PC += 4 elif inst_name == "sltu": s.R[inst.rd] = s.R[inst.rs1] < s.R[inst.rs2] s.PC += 4 elif inst_name == "sra": s.R[inst.rd] = s.R[inst.rs1].int() >> (s.R[inst.rs2].uint() & 0x1F) s.PC += 4 elif inst_name == "srl": s.R[inst.rd] = s.R[inst.rs1] >> (s.R[inst.rs2].uint() & 0x1F) s.PC += 4 elif inst_name == "and": s.R[inst.rd] = s.R[inst.rs1] & s.R[inst.rs2] s.PC += 4 elif inst_name == "or": s.R[inst.rd] = s.R[inst.rs1] | s.R[inst.rs2] s.PC += 4 elif inst_name == "xor": s.R[inst.rd] = s.R[inst.rs1] ^ s.R[inst.rs2] s.PC += 4 #----------------------------------------------------------------------- # Register-immediate arithmetic, logical, and comparison instructions #----------------------------------------------------------------------- elif inst_name == "addi": s.R[inst.rd] = s.R[inst.rs1] + sext( inst.i_imm, 32 ) s.PC += 4 elif inst_name == "andi": s.R[inst.rd] = s.R[inst.rs1] & sext( inst.i_imm, 32 ) s.PC += 4 elif inst_name == "ori": s.R[inst.rd] = s.R[inst.rs1] | sext( inst.i_imm, 32 ) s.PC += 4 elif inst_name == "xori": s.R[inst.rd] = s.R[inst.rs1] ^ sext( inst.i_imm, 32 ) s.PC += 4 elif inst_name == "slli": s.R[inst.rd] = s.R[inst.rs1] << inst.shamt s.PC += 4 elif inst_name == "srli": s.R[inst.rd] = s.R[inst.rs1] >> inst.shamt s.PC += 4 elif inst_name == "srai": s.R[inst.rd] = s.R[inst.rs1].int() >> inst.shamt.uint() s.PC += 4 elif inst_name == "slti": s.R[inst.rd] = s.R[inst.rs1].int() < inst.i_imm.int() s.PC += 4 elif inst_name == "sltiu": s.R[inst.rd] = s.R[inst.rs1] < sext( inst.i_imm, 32 ) s.PC += 4 #----------------------------------------------------------------------- # Other instructions #----------------------------------------------------------------------- elif inst_name == "auipc": s.R[inst.rd] = inst.u_imm + s.PC s.PC += 4 elif inst_name == "lui": s.R[inst.rd] = inst.u_imm s.PC += 4 #----------------------------------------------------------------------- # Load/store instructions #----------------------------------------------------------------------- elif inst_name == "sh": addr = s.R[inst.rs1] + sext( inst.s_imm, 32 ) #s.M[addr:addr+2] = s.R[inst.rs2][0:16] s.dmem.write(addr, 2, s.R[inst.rs2][0:16]) s.PC += 4 elif inst_name == "sb": addr = s.R[inst.rs1] + sext( inst.s_imm, 32 ) #s.M[addr] = s.R[inst.rs2][0:8] s.dmem.write(addr, 1, s.R[inst.rs2][0:8]) s.PC += 4 elif inst_name == "sw": addr = s.R[inst.rs1] + sext( inst.s_imm, 32 ) s.dmem.write( addr, 4, s.R[inst.rs2] ) s.PC += 4 elif inst_name == "lw": addr = s.R[inst.rs1] + sext( inst.i_imm, 32 ) s.R[inst.rd] = s.dmem.read( addr, 4 ) s.PC += 4 elif inst_name == "lb": addr = s.R[inst.rs1] + sext( inst.i_imm, 32 ) dmem_data = s.dmem.read( addr, 1 )[0:8] s.R[inst.rd] = sext( dmem_data, 32 ) s.PC += 4 elif inst_name == "lbu": addr = s.R[inst.rs1] + sext( inst.i_imm, 32 ) dmem_data = s.dmem.read( addr, 1 )[0:8] s.R[inst.rd] = zext( dmem_data, 32 ) s.PC += 4 elif inst_name == "lh": addr = s.R[inst.rs1] + sext( inst.i_imm, 32 ) dmem_data = s.dmem.read( addr, 2 )[0:16] s.R[inst.rd] = sext( dmem_data, 32 ) s.PC += 4 elif inst_name == "lhu": addr = s.R[inst.rs1] + sext( inst.i_imm, 32 ) dmem_data = s.dmem.read( addr, 2 )[0:16] s.R[inst.rd] = zext( dmem_data, 32 ) s.PC += 4 #----------------------------------------------------------------------- # Unconditional jump instructions #----------------------------------------------------------------------- elif inst_name == "jal": s.R[inst.rd] = s.PC + 4 s.PC = s.PC + sext( inst.j_imm, 32 ) elif inst_name == "jalr": temp = s.R[inst.rs1] + sext( inst.i_imm, 32 ) s.R[inst.rd] = s.PC + 4 s.PC = temp & 0xFFFFFFFE #----------------------------------------------------------------------- # Conditional branch instructions #----------------------------------------------------------------------- elif inst_name == "bne": if s.R[inst.rs1] != s.R[inst.rs2]: s.PC = s.PC + sext( inst.b_imm, 32 ) else: s.PC += 4 elif inst_name == "beq": if s.R[inst.rs1] == s.R[inst.rs2]: s.PC = s.PC + sext( inst.b_imm, 32 ) else: s.PC += 4 elif inst_name == "blt": if s.R[inst.rs1].int() < s.R[inst.rs2].int(): s.PC = s.PC + sext( inst.b_imm, 32 ) else: s.PC += 4 elif inst_name == "bge": if s.R[inst.rs1].int() >= s.R[inst.rs2].int(): s.PC = s.PC + sext( inst.b_imm, 32 ) else: s.PC += 4 elif inst_name == "bltu": if s.R[inst.rs1] < s.R[inst.rs2]: s.PC = s.PC + sext( inst.b_imm, 32 ) else: s.PC += 4 elif inst_name == "bgeu": if s.R[inst.rs1] >= s.R[inst.rs2]: s.PC = s.PC + sext( inst.b_imm, 32 ) else: s.PC += 4 elif inst_name == "csrw": if inst.csrnum == 0x7C0: s.proc2mngr( s.R[inst.rs1] ) elif 0x7E0 <= inst.csrnum <= 0x7FF: s.xcel.write( inst.csrnum[0:5], s.R[inst.rs1] ) else: raise TinyRV2Semantics.IllegalInstruction( "Unrecognized CSR register ({}) for csrw at PC={}" \ .format(inst.csrnum.uint(),s.PC) ) s.PC += 4 elif inst_name == "csrr": if inst.csrnum == 0xFC0: s.R[inst.rd] = s.mngr2proc() elif 0x7E0 <= inst.csrnum <= 0x7FF: s.R[inst.rd] = s.xcel.read( inst.csrnum[0:5] ) else: raise TinyRV2Semantics.IllegalInstruction( "Unrecognized CSR register ({}) for csrr at PC={}" \ .format(inst.csrnum.uint(),s.PC) ) s.PC += 4 except: print( "Unexpected error at PC={:0>8s}!".format( str(s.PC) ) ) raise s.commit_inst = b1( 1 )
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 = NonBlockingCallerIfc() s.mngr2proc = NonBlockingCalleeIfc() # Buffers to hold input messages s.imemresp_q = DelayPipeDeqCL(0)(enq=s.imem.resp) s.dmemresp_q = DelayPipeDeqCL(1)(enq=s.dmem.resp) s.mngr2proc_q = DelayPipeDeqCL(1)(enq=s.mngr2proc) s.xcelresp_q = DelayPipeDeqCL(0)(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 @s.update 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) @s.update 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 == "sub": s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1] - s.R[inst.rs2], DXM_W.arith)) elif inst_name == "mul": 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 == "slt": s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1].int() < s.R[inst.rs2].int(), DXM_W.arith)) elif inst_name == "sltu": s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1] < s.R[inst.rs2], DXM_W.arith)) elif inst_name == "sra": s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1].int() >> (s.R[inst.rs2].uint() & 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 == "or": s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1] | s.R[inst.rs2], DXM_W.arith)) elif inst_name == "xor": 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] + inst.i_imm.int(), DXM_W.arith)) elif inst_name == "andi": s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1] & inst.i_imm.int(), DXM_W.arith)) elif inst_name == "ori": s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1] | inst.i_imm.int(), DXM_W.arith)) elif inst_name == "xori": s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1] ^ inst.i_imm.int(), DXM_W.arith)) elif inst_name == "slli": s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1] << inst.i_imm.int(), DXM_W.arith)) elif inst_name == "srli": s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1] >> inst.i_imm.int(), DXM_W.arith)) elif inst_name == "srai": s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1].int() >> (inst.i_imm.uint() & 0x1F), DXM_W.arith)) elif inst_name == "slti": s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1].int() < inst.i_imm.int(), DXM_W.arith)) elif inst_name == "sltiu": s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1] < sext(inst.i_imm, 32), DXM_W.arith)) elif inst_name == "auipc": s.DXM_W_queue.enq((inst.rd, (s.pc - 4) + inst.u_imm, DXM_W.arith)) #not elegant elif inst_name == "lui": s.DXM_W_queue.enq((inst.rd, inst.u_imm, DXM_W.arith)) elif inst_name == "sh": if s.dmem.req.rdy(): s.dmem.req( memreq_cls(MemMsgType.WRITE, 0, s.R[inst.rs1] + inst.s_imm.int(), 2, s.R[inst.rs2][0:16])) s.DXM_W_queue.enq((0, 0, DXM_W.mem)) else: s.DXM_status = PipelineStatus.stall elif inst_name == "sb": if s.dmem.req.rdy(): s.dmem.req( memreq_cls(MemMsgType.WRITE, 0, s.R[inst.rs1] + inst.s_imm.int(), 1, s.R[inst.rs2][0:8])) s.DXM_W_queue.enq((0, 0, DXM_W.mem)) else: s.DXM_status = PipelineStatus.stall elif inst_name == "sw": if s.dmem.req.rdy(): s.dmem.req( memreq_cls(MemMsgType.WRITE, 0, s.R[inst.rs1] + inst.s_imm.int(), 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] + inst.i_imm.int(), 0)) s.DXM_W_queue.enq((inst.rd, 0, DXM_W.mem)) else: s.DXM_status = PipelineStatus.stall elif inst_name == "lb": if s.dmem.req.rdy(): s.dmem.req( memreq_cls(MemMsgType.READ, 0, s.R[inst.rs1] + inst.i_imm.int(), 1)) s.DXM_W_queue.enq((inst.rd, 0, DXM_W.mem_signed)) else: s.DXM_status = PipelineStatus.stall elif inst_name == "lh": if s.dmem.req.rdy(): s.dmem.req( memreq_cls(MemMsgType.READ, 0, s.R[inst.rs1] + inst.i_imm.int(), 2)) s.DXM_W_queue.enq((inst.rd, 0, DXM_W.mem_signed)) else: s.DXM_status = PipelineStatus.stall elif inst_name == "lbu": if s.dmem.req.rdy(): s.dmem.req( memreq_cls(MemMsgType.READ, 0, s.R[inst.rs1] + inst.i_imm.int(), 1)) s.DXM_W_queue.enq((inst.rd, 0, DXM_W.mem)) else: s.DXM_status = PipelineStatus.stall elif inst_name == "lhu": if s.dmem.req.rdy(): s.dmem.req( memreq_cls(MemMsgType.READ, 0, s.R[inst.rs1] + inst.i_imm.int(), 2)) s.DXM_W_queue.enq((inst.rd, 0, DXM_W.mem)) else: s.DXM_status = PipelineStatus.stall elif inst_name == "jal": s.DXM_W_queue.enq((inst.rd, s.pc, DXM_W.arith)) s.pc = s.pc + sext(inst.j_imm, 32) - 4 elif inst_name == "jalr": s.DXM_W_queue.enq((inst.rd, s.pc, DXM_W.arith)) s.pc = (s.R[inst.rs1] + sext(inst.i_imm, 32)) & 0xFFFFFFFE elif inst_name == "bne": if s.R[inst.rs1] != s.R[inst.rs2]: s.redirected_pc_DXM = pc + inst.b_imm.int() s.DXM_W_queue.enq(None) elif inst_name == "beq": if s.R[inst.rs1] == s.R[inst.rs2]: s.redirected_pc_DXM = pc + inst.b_imm.int() s.DXM_W_queue.enq(None) elif inst_name == "blt": if s.R[inst.rs1].int() < s.R[inst.rs2].int(): s.redirected_pc_DXM = pc + inst.b_imm.int() s.DXM_W_queue.enq(None) elif inst_name == "bge": if s.R[inst.rs1].int() >= s.R[inst.rs2].int(): s.redirected_pc_DXM = pc + inst.b_imm.int() s.DXM_W_queue.enq(None) elif inst_name == "bltu": if s.R[inst.rs1] < s.R[inst.rs2]: s.redirected_pc_DXM = pc + inst.b_imm.int() s.DXM_W_queue.enq(None) elif inst_name == "bgeu": if s.R[inst.rs1] >= s.R[inst.rs2]: s.redirected_pc_DXM = pc + inst.b_imm.int() 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) @s.update def W(): s.commit_inst = Bits1(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.mem_signed: if s.dmemresp_q.deq.rdy(): if rd > 0: # load s.R[rd] = Bits32( sext(s.dmemresp_q.deq().data, 32)) 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 = Bits1(1)
def construct(s): # Interface, Buffers to hold request/response messages s.commit_inst = OutPort(Bits1) s.imem = MemMasterIfcFL() s.dmem = MemMasterIfcFL() s.xcel = XcelMasterIfcFL(*mk_xcel_msg(5, 32)) s.proc2mngr = SendIfcFL() s.mngr2proc = GetIfcFL() # Internal data structures s.PC = b32(0x200) s.R = RegisterFile(32) s.raw_inst = None @s.update def up_ProcFL(): if s.reset: s.PC = b32(0x200) return s.commit_inst = Bits1(0) try: s.raw_inst = s.imem.read(s.PC, 4) # line trace inst = TinyRV0Inst(s.raw_inst) inst_name = inst.name if inst_name == "nop": s.PC += 4 elif inst_name == "add": s.R[inst.rd] = s.R[inst.rs1] + s.R[inst.rs2] s.PC += 4 elif inst_name == "sll": s.R[inst.rd] = s.R[inst.rs1] << (s.R[inst.rs2] & 0x1F) s.PC += 4 elif inst_name == "srl": s.R[inst.rd] = s.R[inst.rs1] >> (s.R[inst.rs2].uint() & 0x1F) s.PC += 4 # ''' TUTORIAL TASK '''''''''''''''''''''''''''''''''''''''''''''' # Implement instruction AND in FL processor # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''\/ #; Make an "elif" statement here to implement instruction AND #; that applies bit-wise "and" operator to rs1 and rs2 and stores #; the result to rd elif inst_name == "and": s.R[inst.rd] = s.R[inst.rs1] & s.R[inst.rs2] s.PC += 4 # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''/\ elif inst_name == "addi": s.R[inst.rd] = s.R[inst.rs1] + sext(inst.i_imm, 32) s.PC += 4 elif inst_name == "sw": addr = s.R[inst.rs1] + sext(inst.s_imm, 32) s.dmem.write(addr, 4, s.R[inst.rs2]) s.PC += 4 elif inst_name == "lw": addr = s.R[inst.rs1] + sext(inst.i_imm, 32) s.R[inst.rd] = s.dmem.read(addr, 4) s.PC += 4 elif inst_name == "bne": if s.R[inst.rs1] != s.R[inst.rs2]: s.PC = s.PC + sext(inst.b_imm, 32) else: s.PC += 4 elif inst_name == "csrw": if inst.csrnum == 0x7C0: s.proc2mngr(s.R[inst.rs1]) elif 0x7E0 <= inst.csrnum <= 0x7FF: s.xcel.write(inst.csrnum[0:5], s.R[inst.rs1]) else: raise TinyRV2Semantics.IllegalInstruction( "Unrecognized CSR register ({}) for csrw at PC={}" \ .format(inst.csrnum.uint(),s.PC) ) s.PC += 4 elif inst_name == "csrr": if inst.csrnum == 0xFC0: s.R[inst.rd] = s.mngr2proc() elif 0x7E0 <= inst.csrnum <= 0x7FF: s.R[inst.rd] = s.xcel.read(inst.csrnum[0:5]) else: raise TinyRV2Semantics.IllegalInstruction( "Unrecognized CSR register ({}) for csrr at PC={}" \ .format(inst.csrnum.uint(),s.PC) ) s.PC += 4 except: print("Unexpected error at PC={:0>8s}!".format(str(s.PC))) raise s.commit_inst = b1(1)
# +------+-------+-----------+ # | type | raddr | data | # +------+-------+-----------+ # #------------------------------------------------------------------------- # XcelRespMsg #------------------------------------------------------------------------- # Accelerator response messages can either be from a read or write of an # accelerator register. Read requests include the actual value read from # the accelerator register, while write requests currently include # nothing other than the type. # # Message Format: # # 1b 32b # +------+-----------+ # | type | data | # +------+-----------+ # XcelReqMsg, XcelRespMsg = mk_xcel_msg(5, 32) XCEL_TYPE_READ = b1(0) XCEL_TYPE_WRITE = b1(1) class XcelMsgs: req = XcelReqMsg resp = XcelRespMsg