static cycles_t ts_operate(conf_object_t *mem_hier, conf_object_t *space, map_list_t *map, generic_transaction_t *mem_op) { trans_splitter_t *ts = (trans_splitter_t *) mem_hier; int total_stall_time; cache_memory_transaction_t trans; generic_address_t offset; ts->transactions++; /* Transactions that don't span multiple cache lines or are * uncacheable are not modified */ if (likely(TS_CL_TAG(ts, mem_op->physical_address) == (TS_CL_TAG(ts, mem_op->physical_address+mem_op->size-1))) || unlikely(is_uncacheable(ts->cache, mem_op, map, &ts->log))) return ts->tm_ifc->operate(ts->timing_model, space, map, mem_op); /* Here we have a cacheable cache line crossing transaction */ ts->split_transactions++; total_stall_time = 0; trans.s = *mem_op; trans.s.ini_type = Sim_Initiator_Cache; trans.s.ini_ptr = (conf_object_t *) ts; /* we won't need reissue */ mem_op->reissue = 0; /* update the initial_trans field */ if ((mem_op->ini_type & 0xFF00) == Sim_Initiator_Cache) { cache_memory_transaction_t *ct = (cache_memory_transaction_t *) mem_op; trans.initial_trans = ct->initial_trans; } else { trans.initial_trans = mem_op; } offset = 0; while (offset < mem_op->size) { int stall_time; trans.s.physical_address = mem_op->physical_address + offset; trans.s.logical_address = mem_op->logical_address + offset; trans.s.size = MIN(mem_op->size - offset, TS_CL_ADDR(ts, trans.s.physical_address + ts->next_cache_line_size) - trans.s.physical_address); trans.s.id = 0; stall_time = ts->tm_ifc->operate(ts->timing_model, space, map, &trans.s); total_stall_time = MAX(total_stall_time, stall_time); if (trans.s.exception != Sim_PE_No_Exception) mem_op->exception = trans.s.exception; offset += trans.s.size; } return total_stall_time; }
cycles_t ts_operate(conf_object_t *mem_hier, conf_object_t *space, map_list_t *map, generic_transaction_t *mem_op) { trans_splitter_t *ts = (trans_splitter_t *) mem_hier; int stall_time, index; double_trans_t *dt; /* uncacheable transactions are not modified */ if (likely(TS_TAG(ts, mem_op->physical_address) == (TS_TAG(ts, mem_op->physical_address + mem_op->size - 1))) || (ts->cache && unlikely(is_uncacheable(ts->cache, mem_op, map, &ts->log)))) { stall_time = ts->tm_ifc->operate(ts->timing_model, space, map, mem_op); if (!stall_time || !mem_op->reissue) ts->transactions++; return stall_time; } /* here we have a cacheable, cache line crossing transaction */ index = mem_op->id & TABLE_SPLITTER_MASK; if ((dt = ts->table[index]) == NULL) { int first_size; /* first time transaction */ dt = new_trans(ts); ts->table[index] = dt; /* setup the two transactions */ dt->a.s = *mem_op; dt->b.s = *mem_op; first_size = TS_CL_ADDR(ts, mem_op->physical_address + mem_op->size - 1) - mem_op->physical_address; dt->a.s.size = first_size; dt->a.s.ini_type = Sim_Initiator_Cache; dt->a.s.ini_ptr = (conf_object_t *) ts; dt->b.s.physical_address += first_size; dt->b.s.logical_address += first_size; dt->b.s.size -= first_size; dt->b.s.ini_type = Sim_Initiator_Cache; dt->b.s.ini_ptr = (conf_object_t *) ts; dt->b.s.id = SIM_get_unique_memory_transaction_id( GC_CPU(mem_op)); dt->stall_a = 0; dt->stall_b = 0; dt->a.s.reissue = 1; dt->b.s.reissue = 1; } /* update the initial_trans field */ if ((mem_op->ini_type & 0xFF00) == Sim_Initiator_Cache) { cache_memory_transaction_t *ct = (cache_memory_transaction_t *) mem_op; dt->a.initial_trans = ct->initial_trans; dt->b.initial_trans = ct->initial_trans; } else { dt->a.initial_trans = mem_op; dt->b.initial_trans = mem_op; } if (!dt->stall_a && dt->a.s.reissue) { dt->a.s.reissue = 0; dt->stall_a = ts->tm_ifc->operate(ts->timing_model, space, map, &dt->a.s); if (!dt->stall_a) dt->a.s.reissue = 0; } if (!dt->stall_b && dt->b.s.reissue) { dt->b.s.reissue = 0; dt->stall_b = ts->tm_ifc->operate(ts->timing_model, space, map, &dt->b.s); if (!dt->stall_b) dt->b.s.reissue = 0; } /* if at least one of the two needs reissue */ if (dt->a.s.reissue || dt->b.s.reissue) { stall_time = MIN((dt->a.s.reissue) ? dt->stall_a : 0x7FFFFFFF, (dt->b.s.reissue) ? dt->stall_b : 0x7FFFFFFF); dt->stall_a -= stall_time; dt->stall_b -= stall_time; mem_op->reissue = 1; } else { /* no reissue */ stall_time = MAX(dt->stall_a, dt->stall_b); dt->used = 0; ts->table[index] = NULL; mem_op->reissue = 0; ts->split_transactions++; ts->transactions++; } return stall_time; }