int dram_system_get_request(struct dram_system_t *system) { unsigned int logical_channel_id; struct dram_controller_t *controller; struct dram_request_t *request; request = list_get(system->dram_request_list, 0); /* Do nothing if no request is passed */ if (!request) return 0; /* Decode request address */ dram_decode_address(system, request->addr, &logical_channel_id, NULL, NULL, NULL, NULL, NULL); /* Send request to the request queue*/ /* return 0 if request queue cannot take any request at this moment */ controller = list_get(system->dram_controller_list, logical_channel_id); if (!dram_controller_get_request(controller, request)) return 0; /* Return */ return 1; }
int dram_controller_get_request(struct dram_controller_t *controller, struct dram_request_t *request) { int i; unsigned int rank_id, bank_id, physical_channel_id; struct dram_bank_info_t *info; /* Do nothing if pointer is not passed*/ if (!request || !controller) return 0; /* Decode address*/ dram_decode_address(request->system, request->addr, NULL, &rank_id, NULL, &bank_id, NULL, &physical_channel_id); /* Locate bank info */ i = (physical_channel_id) * (controller->dram_num_ranks) * (controller->dram_num_banks_per_device) + (rank_id) * (controller->dram_num_banks_per_device) + (bank_id); info = list_get(controller->dram_bank_info_list, i); list_add(info->request_queue, request); return 1; }
void dram_controller_process_request(struct dram_controller_t *controller) { int i; unsigned int num_bank_info; unsigned int row_id, column_id; struct dram_request_t *request; struct dram_bank_info_t *info; struct dram_command_t *command_precharge; struct dram_command_t *command_activate; struct dram_command_t *command_access; /* Go through bank info list */ num_bank_info = list_count(controller->dram_bank_info_list); for (i = 0; i < num_bank_info; i++) { /* Locate bank info */ info = list_get(controller->dram_bank_info_list, i); /* Fetch a request from request queue */ request = list_dequeue(info->request_queue); if (request) { dram_decode_address(request->system, request->addr, NULL, NULL, &row_id, NULL, &column_id, NULL); /* Determine policy to be used */ switch (controller->rb_policy) { /* Open page row buffer policy */ case open_page_row_buffer_policy: /* Row hit */ if (info->row_buffer_valid && info->active_row_id == row_id) { /* Create single read/write command */ command_access = dram_command_create(); command_access->dram = list_get(controller->dram_list, info->channel_id); if (request->type == request_type_read) { command_access->type = dram_command_read; command_access->u.read.rank_id = info->rank_id; command_access->u.read.bank_id = info->bank_id; command_access->u.read.column_id = column_id; } else if (request->type == request_type_write) { command_access->type = dram_command_write; command_access->u.write.rank_id = info->rank_id; command_access->u.write.bank_id = info->bank_id; command_access->u.write.column_id = column_id; } /* Append command to queue */ list_add(info->command_queue, command_access); } /* Row miss - different row was activated */ else if (info->row_buffer_valid) { /* Create pre, act, rd/wr three commands */ command_precharge = dram_command_create(); command_activate = dram_command_create(); command_access = dram_command_create(); /* Precharge */ command_precharge->type = dram_command_precharge; command_precharge->dram = list_get(controller->dram_list, info->channel_id); command_precharge->u.precharge.rank_id = info->rank_id; command_precharge->u.precharge.bank_id = info->bank_id; /* Activate */ command_activate->type = dram_command_activate; command_activate->dram = list_get(controller->dram_list, info->channel_id); command_activate->u.activate.rank_id = info->rank_id; command_activate->u.activate.bank_id = info->bank_id; command_activate->u.activate.row_id = row_id; /* Access */ command_access->dram = list_get(controller->dram_list, info->channel_id); if (request->type == request_type_read) { command_access->type = dram_command_read; command_access->u.read.rank_id = info->rank_id; command_access->u.read.bank_id = info->bank_id; command_access->u.read.column_id = column_id; } else if (request->type == request_type_write) { command_access->type = dram_command_write; command_access->u.write.rank_id = info->rank_id; command_access->u.write.bank_id = info->bank_id; command_access->u.write.column_id = column_id; } list_add(info->command_queue, command_precharge); list_add(info->command_queue, command_activate); list_add(info->command_queue, command_access); /* Update the active row status */ info->active_row_id = row_id; } /* Row miss - no row was activated */ else { /* Create act, rd/wr two commands */ command_activate = dram_command_create(); command_access = dram_command_create(); /* Activate */ command_activate->type = dram_command_activate; command_activate->dram = list_get(controller->dram_list, info->channel_id); command_activate->u.activate.rank_id = info->rank_id; command_activate->u.activate.bank_id = info->bank_id; command_activate->u.activate.row_id = row_id; /* Access */ command_access->dram = list_get(controller->dram_list, info->channel_id); if (request->type == request_type_read) { command_access->type = dram_command_read; command_access->u.read.rank_id = info->rank_id; command_access->u.read.bank_id = info->bank_id; command_access->u.read.column_id = column_id; } else if (request->type == request_type_write) { command_access->type = dram_command_write; command_access->u.write.rank_id = info->rank_id; command_access->u.write.bank_id = info->bank_id; command_access->u.write.column_id = column_id; } list_add(info->command_queue, command_activate); list_add(info->command_queue, command_access); /* Update the active row status */ info->row_buffer_valid = 1; info->active_row_id = row_id; } break; /* Close page row buffer policy */ case close_page_row_buffer_policy: /* Create act, rd/wr, pre three commands */ command_activate = dram_command_create(); command_access = dram_command_create(); command_precharge = dram_command_create(); /* Activate */ command_activate->type = dram_command_activate; command_activate->dram = list_get(controller->dram_list, info->channel_id); command_activate->u.activate.rank_id = info->rank_id; command_activate->u.activate.bank_id = info->bank_id; command_activate->u.activate.row_id = row_id; /* Access */ command_access->dram = list_get(controller->dram_list, info->channel_id); if (request->type == request_type_read) { command_access->type = dram_command_read; command_access->u.read.rank_id = info->rank_id; command_access->u.read.bank_id = info->bank_id; command_access->u.read.column_id = column_id; } else if (request->type == request_type_write) { command_access->type = dram_command_write; command_access->u.write.rank_id = info->rank_id; command_access->u.write.bank_id = info->bank_id; command_access->u.write.column_id = column_id; } /* Precharge */ command_precharge->type = dram_command_precharge; command_precharge->dram = list_get(controller->dram_list, info->channel_id); command_precharge->u.precharge.rank_id = info->rank_id; command_precharge->u.precharge.bank_id = info->bank_id; list_add(info->command_queue, command_activate); list_add(info->command_queue, command_access); list_add(info->command_queue, command_precharge); /* Update the active row status */ info->row_buffer_valid = 0; break; case hybird_page_row_buffer_policy: break; default: break; } dram_request_free(request); } } }