def _emit(self, op_add, dst=REGISTERS['null'], opd1=REGISTERS['r0'], opd2=REGISTERS['r0'], sig='no signal', set_flags=True, **kwargs): muxes, raddr_a, raddr_b, use_imm, unpack, read_pm = \ self._encode_read_operands(opd1, opd2) if use_imm: if sig != 'no signal' and sig != 'alu small imm': raise AssembleError( '\'{}\' can not be used with immediate'.format(sig)) sig = 'alu small imm' sig_bits = enc._SIGNAL[sig] if op_add == enc._ADD_INSN['nop']: set_flags = False waddr_add, waddr_mul, write_swap, pack = \ self._encode_write_operands(dst) pm = 0 if unpack and pack: if read_pm != 0: raise AssembleError('Conflict of packing and unpacking') pm = read_pm elif unpack and not pack: pm = read_pm elif pack and not unpack: pm = 0 cond_add_str = kwargs.get('cond', 'always') cond_add = enc._COND[cond_add_str] cond_mul = enc._COND['never'] insn = enc.AluInsn( sig=sig_bits, unpack=unpack, pm=pm, pack=pack, sf=set_flags, ws=write_swap, cond_add=cond_add, cond_mul=cond_mul, op_add=op_add, op_mul=enc._MUL_INSN['nop'], waddr_add=waddr_add, waddr_mul=waddr_mul, raddr_a=raddr_a, raddr_b=raddr_b, add_a=muxes[0], add_b=muxes[1], mul_a=muxes[2], mul_b=muxes[3] ) if self.asm.sanity_check: insn.verbose = AddInstr(enc._ADD_INSN_REV[op_add], dst, opd1, opd2, sig, set_flags, cond_add_str) self.asm._emit(insn) # Create MulEmitter which holds arguments of Add ALU for dual # issuing. return MulEmitter( self.asm, op_add=op_add, add_dst=dst, add_opd1=opd1, add_opd2=opd2, cond_add=cond_add, sig=sig, set_flags=set_flags, increment=False)
def _emit_with_defaults(self, op_mul, mul_dst, mul_opd1, mul_opd2, rotate=0, pack='nop', **kwargs): mul_pack = enc._MUL_PACK[pack] muxes, raddr_a, raddr_b, use_imm, unpack, read_pm = \ self._encode_read_operands(self.add_opd1, self.add_opd2, mul_opd1, mul_opd2) waddr_add, waddr_mul, write_swap, regA_pack = \ self._encode_write_operands(self.add_dst, mul_dst) if mul_pack and regA_pack: raise AssembleError('Multiple pack operationss') write_pm = (mul_pack != 0) pack = mul_pack or regA_pack pm = 0 if unpack and pack: if read_pm != write_pm: raise AssembleError('Conflict of packing and unpacking') pm = read_pm elif unpack and not pack: pm = read_pm elif pack and not unpack: pm = write_pm sig = kwargs.get('sig', 'no signal') if self.sig != 'no signal': if sig != 'no signal': raise AssembleError('Conflict of signals') sig = self.sig if use_imm or rotate: if sig != 'no signal' and sig != 'alu small imm': raise AssembleError( '\'{}\' can not be used with immediate'.format(sig)) sig = 'alu small imm' sig_bits = enc._SIGNAL[sig] if rotate: if muxes[2] == 5 or muxes[2] == 7 or muxes[3] == 5 or muxes[3] == 7: raise AssembleError('Rotate operation is only available when' ' inputs are taken from r0-r4 or ra') if use_imm: # 'r5 rotate' represents -1. # 'n-upward rotate' represents n-16. # So these combinations can be used (1 <= n <= 15): # +-----------+--------+ # | small imm | rotate | # +-----------+--------+ # | -16 | r5 | # | -n | -n | # +-----------+--------+ # c.f. https://vc4-notes.tumblr.com/post/153467713064/ if rotate == REGISTERS['r5']: if raddr_b != enc._SMALL_IMM['-16']: raise AssembleError( 'Conflict immediate value and r5 rotate') elif raddr_b != enc._SMALL_IMM[str(rotate % 16 - 16)]: raise AssembleError( 'Conflict immediate value and n rotate') if rotate == REGISTERS['r5']: raddr_b = 48 else: raddr_b = 48 + rotate % 16 cond_add = self.cond_add cond_mul_str = kwargs.get('cond', 'always') cond_mul = enc._COND[cond_mul_str] insn = enc.AluInsn(sig=sig_bits, unpack=unpack, pm=pm, pack=pack, sf=self.set_flags, ws=write_swap, cond_add=cond_add, cond_mul=cond_mul, op_add=self.op_add, op_mul=op_mul, waddr_add=waddr_add, waddr_mul=waddr_mul, raddr_a=raddr_a, raddr_b=raddr_b, add_a=muxes[0], add_b=muxes[1], mul_a=muxes[2], mul_b=muxes[3]) if self.asm.sanity_check: insn.verbose = MulInstr(enc._MUL_INSN_REV[op_mul], mul_dst, mul_opd1, mul_opd2, sig, self.set_flags, cond_mul_str) self.asm._emit(insn, increment=self.increment)
reg = REGISTERS[name] assert(reg.name == name) assert(str(reg) == name) def test_pack_unpack(): REGISTERS['ra0'].pack('16a') # no throw assert_raises(AssembleError, REGISTERS['rb0'].pack, '16a') REGISTERS['ra0'].unpack('16a') # no throw REGISTERS['r4'].unpack('16a') # no throw assert_raises(AssembleError, REGISTERS['rb0'].unpack, '16a') #============================ Instruction encoding ============================ SAMPLE_ALU_INSN = enc.AluInsn( sig=0, unpack=1, pm=1, pack=2, cond_add=3, cond_mul=4, sf=1, ws=1, waddr_add=53, waddr_mul=12, op_mul=4, op_add=2, raddr_a=33, raddr_b=53, add_a=4, add_b=7, mul_a=6, mul_b=2 ) SAMPLE_BRANCH_INSN = enc.BranchInsn( sig=0xf, cond_br=13, rel=1, reg=0, raddr_a=27, ws=1, waddr_add=53, waddr_mul=12, immediate=0x12345678 ) SAMPLE_LOAD_INSN = enc.LoadInsn( sig=0xe, unpack=1, pm=1, pack=2, cond_add=3, cond_mul=4, sf=1, ws=1, waddr_add=53, waddr_mul=12, immediate=0x12345678 ) SAMPLE_SEMA_INSN = enc.SemaInsn( sig=0xe, unpack=4, pm=1, pack=2, cond_add=3, cond_mul=4, sf=1, ws=1,