/* calculate required # of delay slots between the instruction that * assigns a value and the one that consumes */ int ir3_delayslots(struct ir3_instruction *assigner, struct ir3_instruction *consumer, unsigned n) { /* worst case is cat1-3 (alu) -> cat4/5 needing 6 cycles, normal * alu -> alu needs 3 cycles, cat4 -> alu and texture fetch * handled with sync bits */ if (is_meta(assigner)) return 0; if (writes_addr(assigner)) return 6; /* handled via sync flags: */ if (is_sfu(assigner) || is_tex(assigner) || is_mem(assigner)) return 0; /* assigner must be alu: */ if (is_flow(consumer) || is_sfu(consumer) || is_tex(consumer) || is_mem(consumer)) { return 6; } else if ((consumer->category == 3) && (is_mad(consumer->opc) || is_madsh(consumer->opc)) && (n == 2)) { /* special case, 3rd src to cat3 not required on first cycle */ return 1; } else { return 3; } }
void ActivationObj::non_primitive_send(oop_t rcvr, oop_t* argsp, fint arg_count, bool isImplicitSelf, oop_t sel, bool isUndirected, oop_t delegatee, oop_t this_act, oop_t* new_actp) { // todo optimize time For block method activations, could cache the result of outermost_lexical_frame()->get_methodHolder() // (or just outermost_lexical_frame(), so that it could be useful for NLRs too) in the methodHolder indexable. -- Adam, 3/06 oop_t holder_of_sender_method = (isUndirected || delegatee) ? outermost_lexical_frame()->get_methodHolder() : The::oop_of(The::nil_object); oop_t holder; SlotDesc* sd; oop_t contents = Lookup::findObject( rcvr, sel, &holder, &sd, new_actp, this_act, isUndirected, delegatee, holder_of_sender_method, isImplicitSelf ); if (contents == badOop) { // lookup failure } else { if (sd->is_assignment()) { assert(arg_count == 1); sd->set_assignable_contents(holder, argsp[0]); remote_push(rcvr); } else if (is_mem(contents) && MemObj::from(contents)->is_activationMap()) { // todo optimize time: pass in the contents address, too, since we've already got it. -- Adam, 5/06 *new_actp = ActivationObj::clone_for(contents, holder, rcvr, argsp, arg_count, this_act); } else { assert(arg_count == 0); remote_push(contents); } } }
bool interconnect_has_buffer(unsigned int input_node, unsigned int tot_req_size) { unsigned int input = node_map[input_node]; bool has_buffer = false; unsigned int n_flits = tot_req_size / _flit_size + ((tot_req_size % _flit_size)? 1:0); if (!(fixed_lat_icnt || perfect_icnt)) { has_buffer = (traffic[0]->_partial_packets[input][0].size() + n_flits) <= input_buffer_capacity; if ((net_c>1) && is_mem(input)) has_buffer = (traffic[1]->_partial_packets[input][0].size() + n_flits) <= input_buffer_capacity; } else { has_buffer = true; } return has_buffer; }
oop_t ActivationObj::clone_for(oop_t method, oop_t method_holder, oop_t rcvr, oop_t* args, fint arg_count, oop_t sender_act) { assert(is_mem(method)); ActivationMapObj* m_addr = ActivationMapObj::from(method); assert(m_addr->is_activationMap()); oop_t self = self_for_new_activation(m_addr, rcvr); fint partSizes = m_addr->get_activationPartSizes(); assert( ActivationMapObj::get_argCount(partSizes) == arg_count ); fint assignable_local_count = ActivationMapObj::get_assignableLocalCount( partSizes ); fint max_stack_size = ActivationMapObj::get_maxStackSize( partSizes ); smi new_indexable_origin = first_arg_offset + arg_count + assignable_local_count; smi new_indexable_size = first_stack_offset + max_stack_size; ActivationObj* addr; oop_t a = ((ObjVectorObj*) The::addr_of( The::vector_proto )) ->clone_and_resize( new_indexable_size, badOop, (ObjVectorObj**)&addr, new_indexable_origin ); addr->initialize(m_addr, method, method_holder, self, rcvr, args, arg_count, assignable_local_count, max_stack_size, sender_act); return a; }
bool is_block(oop_t x) { return is_mem(x) && MemObj::from(x)->is_block(); }
bool is_objVector(oop_t x) { return is_mem(x) && MemObj::from(x)->is_objVector(); }
bool is_method(oop_t x) { return is_mem(x) && MemObj::from(x)->is_activationMap(); }
static bool is_sfu_or_mem(struct ir3_instruction *instr) { return is_sfu(instr) || is_mem(instr); }