finish writing, ready to debug
This commit is contained in:
236
include/csu.h
236
include/csu.h
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <cstdint>
|
||||||
#include "concept.h"
|
#include "concept.h"
|
||||||
#ifndef CSU_H
|
#ifndef CSU_H
|
||||||
#include <array>
|
#include <array>
|
||||||
@ -57,24 +58,27 @@ struct CentralScheduleUnit_Output {
|
|||||||
dark::Register<32> rs2_in_ROB_value;
|
dark::Register<32> rs2_in_ROB_value;
|
||||||
dark::Register<32> decoded_imm;
|
dark::Register<32> decoded_imm;
|
||||||
dark::Register<6> decoded_shamt;
|
dark::Register<6> decoded_shamt;
|
||||||
dark::Register<1> cache_hit;
|
// dark::Register<1> cache_hit;
|
||||||
dark::Register<5> cache_hit_ROB_index;
|
// dark::Register<5> cache_hit_ROB_index;
|
||||||
dark::Register<32> cache_hit_data;
|
// dark::Register<32> cache_hit_data;
|
||||||
dark::Register<1> is_committing;
|
dark::Register<1> is_committing;
|
||||||
|
dark::Register<1> commit_has_resulting_register;
|
||||||
dark::Register<5> commit_reg_index;
|
dark::Register<5> commit_reg_index;
|
||||||
dark::Register<32> commit_reg_value;
|
dark::Register<32> commit_reg_value;
|
||||||
dark::Register<5> commit_ins_ROB_index;
|
dark::Register<5> commit_ins_ROB_index;
|
||||||
};
|
};
|
||||||
struct ROBRecordType {
|
struct ROBRecordType {
|
||||||
dark::Register<4> state;
|
dark::Register<4> state; // 0: no entry; 1: just issued; 2: waiting; 3: ready to commit
|
||||||
dark::Register<32> instruction;
|
dark::Register<32> instruction;
|
||||||
|
dark::Register<1> has_resulting_register;
|
||||||
dark::Register<5> resulting_register_idx;
|
dark::Register<5> resulting_register_idx;
|
||||||
dark::Register<32> resulting_register_value;
|
dark::Register<32> resulting_register_value;
|
||||||
dark::Register<1> resulting_PC_ready;
|
dark::Register<1> resulting_PC_ready;
|
||||||
dark::Register<32> resulting_PC;
|
dark::Register<32> resulting_PC;
|
||||||
dark::Register<4> mem_request_type; // see memory.h
|
dark::Register<1> PC_mismatch_mark;
|
||||||
dark::Register<32> mem_request_addr;
|
// dark::Register<4> mem_request_type; // see memory.h
|
||||||
dark::Register<32> mem_request_data;
|
// dark::Register<32> mem_request_addr;
|
||||||
|
// dark::Register<32> mem_request_data;
|
||||||
};
|
};
|
||||||
struct CentralScheduleUnit_Private {
|
struct CentralScheduleUnit_Private {
|
||||||
dark::Register<32> predicted_PC;
|
dark::Register<32> predicted_PC;
|
||||||
@ -187,7 +191,8 @@ struct CentralScheduleUnit
|
|||||||
decoded_imm = static_cast<uint32_t>(decoded_imm) | 0xFFE00000;
|
decoded_imm = static_cast<uint32_t>(decoded_imm) | 0xFFE00000;
|
||||||
}
|
}
|
||||||
full_ins_id = opcode;
|
full_ins_id = opcode;
|
||||||
} else throw std::runtime_error("Unknown instruction in Decode");
|
} else
|
||||||
|
throw std::runtime_error("Unknown instruction in Decode");
|
||||||
return std::make_tuple(full_ins_id, decoded_rd, has_decoded_rd, decoded_rs1, has_decoded_rs1, decoded_rs2,
|
return std::make_tuple(full_ins_id, decoded_rd, has_decoded_rd, decoded_rs1, has_decoded_rs1, decoded_rs2,
|
||||||
has_decoded_rs2, decoded_imm, decoded_shamt);
|
has_decoded_rs2, decoded_imm, decoded_shamt);
|
||||||
}
|
}
|
||||||
@ -207,12 +212,225 @@ struct CentralScheduleUnit
|
|||||||
ROB_head <= 0;
|
ROB_head <= 0;
|
||||||
ROB_tail <= 0;
|
ROB_tail <= 0;
|
||||||
ROB_remain_space <= kROBSize;
|
ROB_remain_space <= kROBSize;
|
||||||
|
for (auto &record : ROB_records) {
|
||||||
|
record.state <= 0;
|
||||||
|
record.PC_mismatch_mark <= 0;
|
||||||
|
}
|
||||||
|
has_instruction_issued_last_cycle <= 0;
|
||||||
|
is_issuing <= 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (bool(force_clear_announcer)) {
|
||||||
|
force_clear_announcer <= 0;
|
||||||
|
ROB_head <= 0;
|
||||||
|
ROB_tail <= 0;
|
||||||
|
ROB_remain_space <= kROBSize;
|
||||||
|
for (auto &record : ROB_records) {
|
||||||
|
record.state <= 0;
|
||||||
|
record.PC_mismatch_mark <= 0;
|
||||||
|
}
|
||||||
|
predicted_PC <= actual_PC;
|
||||||
|
has_predicted_PC <= 1;
|
||||||
|
has_instruction_issued_last_cycle <= 0;
|
||||||
|
is_issuing <= 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// STEP1: try to commit and see if we need to rollback
|
// STEP1: try to commit and see if we need to rollback
|
||||||
// process memory access request from LSQ
|
uint32_t ROB_next_remain_space = static_cast<max_size_t>(ROB_remain_space);
|
||||||
|
{
|
||||||
|
uint32_t i = -1;
|
||||||
|
for (auto &record : ROB_records) {
|
||||||
|
++i;
|
||||||
|
if (static_cast<max_size_t>(record.state) != 3) continue;
|
||||||
|
ROB_head <= (static_cast<max_size_t>(ROB_head) + 1) % kROBSize;
|
||||||
|
is_committing <= 1;
|
||||||
|
commit_has_resulting_register <= record.has_resulting_register;
|
||||||
|
commit_reg_index <= record.resulting_register_idx;
|
||||||
|
commit_reg_value <= record.resulting_register_value;
|
||||||
|
commit_ins_ROB_index <= i;
|
||||||
|
actual_PC <= static_cast<max_size_t>(record.resulting_PC);
|
||||||
|
if (static_cast<max_size_t>(record.PC_mismatch_mark) == 1) {
|
||||||
|
force_clear_announcer <= 1;
|
||||||
|
}
|
||||||
|
ROB_next_remain_space++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (force_clear_announcer.peek()) {
|
||||||
|
ROB_remain_space <= ROB_next_remain_space;
|
||||||
|
return;
|
||||||
|
}
|
||||||
// listen to the data from Memory and ALU
|
// listen to the data from Memory and ALU
|
||||||
|
auto process_data = [&](uint32_t res_ROB_index, uint32_t res_data, uint32_t res_PC) {
|
||||||
|
uint32_t i = -1;
|
||||||
|
for (auto &record : ROB_records) {
|
||||||
|
++i;
|
||||||
|
if (static_cast<max_size_t>(record.state) != 2) continue;
|
||||||
|
if (i == res_ROB_index) {
|
||||||
|
record.resulting_register_value <= res_data;
|
||||||
|
if (!bool(record.resulting_PC_ready)) {
|
||||||
|
record.resulting_PC <= res_PC;
|
||||||
|
if (res_PC != static_cast<max_size_t>(record.resulting_PC)) {
|
||||||
|
record.PC_mismatch_mark <= 1;
|
||||||
|
}
|
||||||
|
record.resulting_PC_ready <= 1;
|
||||||
|
if ((static_cast<max_size_t>(record.instruction) & 0x7F) == 0b1100111) {
|
||||||
|
has_predicted_PC <= 1;
|
||||||
|
predicted_PC <= record.resulting_PC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
record.state <= 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (static_cast<max_size_t>(mem_status_receiver) == 0b10) {
|
||||||
|
process_data(static_cast<max_size_t>(completed_memins_ROB_index),
|
||||||
|
static_cast<max_size_t>(completed_memins_read_data), 0);
|
||||||
|
}
|
||||||
|
if (static_cast<max_size_t>(alu_status_receiver) == 0b10) {
|
||||||
|
process_data(static_cast<max_size_t>(completed_aluins_ROB_index),
|
||||||
|
static_cast<max_size_t>(completed_aluins_result),
|
||||||
|
static_cast<max_size_t>(completed_alu_resulting_PC));
|
||||||
|
}
|
||||||
// try to issue and check if we need to stall
|
// try to issue and check if we need to stall
|
||||||
|
if (bool(has_predicted_PC)) { // currently not in stall state
|
||||||
|
uint32_t instruction = instruction_fetcher(static_cast<max_size_t>(predicted_PC));
|
||||||
|
auto decoded_tuple = Decode(instruction);
|
||||||
|
uint32_t full_ins_id = static_cast<max_size_t>(std::get<0>(decoded_tuple));
|
||||||
|
uint8_t decoded_rd = static_cast<max_size_t>(std::get<1>(decoded_tuple));
|
||||||
|
uint8_t has_decoded_rd = static_cast<max_size_t>(std::get<2>(decoded_tuple));
|
||||||
|
uint8_t decoded_rs1 = static_cast<max_size_t>(std::get<3>(decoded_tuple));
|
||||||
|
uint8_t has_decoded_rs1 = static_cast<max_size_t>(std::get<4>(decoded_tuple));
|
||||||
|
uint8_t decoded_rs2 = static_cast<max_size_t>(std::get<5>(decoded_tuple));
|
||||||
|
uint8_t has_decoded_rs2 = static_cast<max_size_t>(std::get<6>(decoded_tuple));
|
||||||
|
uint32_t decoded_imm = static_cast<max_size_t>(std::get<7>(decoded_tuple));
|
||||||
|
uint8_t decoded_shamt = static_cast<max_size_t>(std::get<8>(decoded_tuple));
|
||||||
|
if ((full_ins_id & 0x7F) == 0b0000011 || (full_ins_id & 0x7F) == 0b0100011) {
|
||||||
|
// memory instruction
|
||||||
|
int32_t actual_remain_space = static_cast<max_size_t>(load_store_queue_emptyspace_receiver) -
|
||||||
|
static_cast<max_size_t>(has_instruction_issued_last_cycle);
|
||||||
|
if (ROB_next_remain_space > 0 && actual_remain_space > 0) {
|
||||||
|
// can issue
|
||||||
|
is_issuing <= 1;
|
||||||
|
has_instruction_issued_last_cycle <= 1;
|
||||||
|
uint32_t tail = static_cast<max_size_t>(ROB_tail);
|
||||||
|
ROB_tail <= (tail + 1) % kROBSize;
|
||||||
|
ROB_next_remain_space--;
|
||||||
|
predicted_PC <= static_cast<max_size_t>(predicted_PC) + 4;
|
||||||
|
ROB_records[tail].state <= 1;
|
||||||
|
ROB_records[tail].instruction <= instruction;
|
||||||
|
ROB_records[tail].has_resulting_register <= has_decoded_rd;
|
||||||
|
ROB_records[tail].resulting_register_idx <= decoded_rd;
|
||||||
|
ROB_records[tail].resulting_PC_ready <= 1;
|
||||||
|
ROB_records[tail].resulting_PC <= static_cast<max_size_t>(predicted_PC) + 4;
|
||||||
|
ROB_records[tail].PC_mismatch_mark <= 0;
|
||||||
|
this->issue_type <= 1;
|
||||||
|
this->issue_ROB_index <= tail;
|
||||||
|
this->full_ins_id <= full_ins_id;
|
||||||
|
this->full_ins <= instruction;
|
||||||
|
this->issuing_PC <= static_cast<max_size_t>(predicted_PC);
|
||||||
|
this->decoded_rd <= decoded_rd;
|
||||||
|
this->has_decoded_rd <= has_decoded_rd;
|
||||||
|
this->decoded_rs1 <= decoded_rs1;
|
||||||
|
this->has_decoded_rs1 <= has_decoded_rs1;
|
||||||
|
this->decoded_rs2 <= decoded_rs2;
|
||||||
|
this->has_decoded_rs2 <= has_decoded_rs2;
|
||||||
|
this->decoded_imm <= decoded_imm;
|
||||||
|
this->decoded_shamt <= decoded_shamt;
|
||||||
|
} else {
|
||||||
|
has_instruction_issued_last_cycle <= 0;
|
||||||
|
is_issuing <= 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// alu instruction
|
||||||
|
int32_t actual_remain_space = static_cast<max_size_t>(reservestation_emptyspace_receiver) -
|
||||||
|
static_cast<max_size_t>(has_instruction_issued_last_cycle);
|
||||||
|
if (ROB_next_remain_space > 0 && actual_remain_space > 0) {
|
||||||
|
// can issue
|
||||||
|
is_issuing <= 1;
|
||||||
|
has_instruction_issued_last_cycle <= 1;
|
||||||
|
uint32_t tail = static_cast<max_size_t>(ROB_tail);
|
||||||
|
ROB_tail <= (tail + 1) % kROBSize;
|
||||||
|
ROB_next_remain_space--;
|
||||||
|
ROB_records[tail].state <= 1;
|
||||||
|
ROB_records[tail].instruction <= instruction;
|
||||||
|
ROB_records[tail].has_resulting_register <= has_decoded_rd;
|
||||||
|
ROB_records[tail].resulting_register_idx <= decoded_rd;
|
||||||
|
if ((full_ins_id & 0x7F) == 0b1100011 || ((full_ins_id & 0x7F) == 0b1100111) ||
|
||||||
|
((full_ins_id & 0x7F) == 0b1101111)) {
|
||||||
|
switch (full_ins_id & 0x7F) {
|
||||||
|
case 0b1101111:
|
||||||
|
// jal
|
||||||
|
ROB_records[tail].resulting_PC_ready <= 1;
|
||||||
|
ROB_records[tail].resulting_PC <= static_cast<max_size_t>(predicted_PC) + decoded_imm;
|
||||||
|
break;
|
||||||
|
case 0b1100111:
|
||||||
|
// jalr
|
||||||
|
ROB_records[tail].resulting_PC_ready <= 0;
|
||||||
|
has_predicted_PC <= 0;
|
||||||
|
break;
|
||||||
|
case 0b1100011:
|
||||||
|
// branch
|
||||||
|
ROB_records[tail].resulting_PC_ready <= 0;
|
||||||
|
ROB_records[tail].resulting_PC <= static_cast<max_size_t>(predicted_PC) + decoded_imm; // just guess
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ROB_records[tail].resulting_PC_ready <= 1;
|
||||||
|
ROB_records[tail].resulting_PC <= static_cast<max_size_t>(predicted_PC) + 4;
|
||||||
|
}
|
||||||
|
predicted_PC <= ROB_records[tail].resulting_PC.peek();
|
||||||
|
ROB_records[tail].PC_mismatch_mark <= 0;
|
||||||
|
this->issue_type <= 0;
|
||||||
|
this->issue_ROB_index <= tail;
|
||||||
|
this->full_ins_id <= full_ins_id;
|
||||||
|
this->full_ins <= instruction;
|
||||||
|
this->issuing_PC <= static_cast<max_size_t>(predicted_PC);
|
||||||
|
this->decoded_rd <= decoded_rd;
|
||||||
|
this->has_decoded_rd <= has_decoded_rd;
|
||||||
|
this->decoded_rs1 <= decoded_rs1;
|
||||||
|
this->has_decoded_rs1 <= has_decoded_rs1;
|
||||||
|
this->decoded_rs2 <= decoded_rs2;
|
||||||
|
this->has_decoded_rs2 <= has_decoded_rs2;
|
||||||
|
this->decoded_imm <= decoded_imm;
|
||||||
|
this->decoded_shamt <= decoded_shamt;
|
||||||
|
} else {
|
||||||
|
has_instruction_issued_last_cycle <= 0;
|
||||||
|
is_issuing <= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
has_instruction_issued_last_cycle <= 0;
|
||||||
|
is_issuing <= 0;
|
||||||
|
}
|
||||||
// provide the potentially missing data for instruction issued last cycle
|
// provide the potentially missing data for instruction issued last cycle
|
||||||
|
if (bool(has_instruction_issued_last_cycle)) {
|
||||||
|
uint8_t rs1 = static_cast<max_size_t>(this->decoded_rs1);
|
||||||
|
uint8_t found_rs1 = 0;
|
||||||
|
uint32_t rs1_v;
|
||||||
|
uint8_t rs2 = static_cast<max_size_t>(this->decoded_rs2);
|
||||||
|
uint8_t found_rs2 = 0;
|
||||||
|
uint32_t rs2_v;
|
||||||
|
for (uint32_t ptr = static_cast<max_size_t>(ROB_head); ptr != static_cast<max_size_t>(ROB_tail);
|
||||||
|
ptr = (ptr + 1) % kROBSize) {
|
||||||
|
if (ROB_records[ptr].state.peek() == 3) {
|
||||||
|
if (static_cast<max_size_t>(ROB_records[ptr].resulting_register_idx) == rs1) {
|
||||||
|
rs1_v = ROB_records[ptr].resulting_register_value.peek();
|
||||||
|
found_rs1 = 1;
|
||||||
|
}
|
||||||
|
if (static_cast<max_size_t>(ROB_records[ptr].resulting_register_idx) == rs2) {
|
||||||
|
rs2_v = ROB_records[ptr].resulting_register_value.peek();
|
||||||
|
found_rs2 = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->rs1_is_in_ROB <= found_rs1;
|
||||||
|
this->rs1_in_ROB_value <= rs1_v;
|
||||||
|
this->rs2_is_in_ROB <= found_rs2;
|
||||||
|
this->rs2_in_ROB_value <= rs2_v;
|
||||||
|
}
|
||||||
|
// other data
|
||||||
|
ROB_remain_space <= ROB_next_remain_space;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace ZYM
|
} // namespace ZYM
|
||||||
|
@ -43,9 +43,9 @@ struct LoadStoreQueue_Input {
|
|||||||
dark::Wire<5> completed_memins_ROB_index;
|
dark::Wire<5> completed_memins_ROB_index;
|
||||||
dark::Wire<32> completed_memins_read_data;
|
dark::Wire<32> completed_memins_read_data;
|
||||||
// receive status signal from L0 cache
|
// receive status signal from L0 cache
|
||||||
dark::Wire<1> cache_hit;
|
// dark::Wire<1> cache_hit;
|
||||||
dark::Wire<5> cache_hit_ROB_index;
|
// dark::Wire<5> cache_hit_ROB_index;
|
||||||
dark::Wire<32> cache_hit_data;
|
// dark::Wire<32> cache_hit_data;
|
||||||
};
|
};
|
||||||
struct LoadStoreQueue_Output {
|
struct LoadStoreQueue_Output {
|
||||||
// request signal, Memory and the L0 cache in ROB will listen to this
|
// request signal, Memory and the L0 cache in ROB will listen to this
|
||||||
@ -159,7 +159,7 @@ struct LoadStoreQueue : public dark::Module<LoadStoreQueue_Input, LoadStoreQueue
|
|||||||
bool(has_accepted_ins_last_cycle) && bool(LSQ_queue[last_idx].E1) && !last_cycle_V1_proccessed;
|
bool(has_accepted_ins_last_cycle) && bool(LSQ_queue[last_idx].E1) && !last_cycle_V1_proccessed;
|
||||||
bool should_monitor_V2 =
|
bool should_monitor_V2 =
|
||||||
bool(has_accepted_ins_last_cycle) && bool(LSQ_queue[last_idx].E2) && !last_cycle_V2_proccessed;
|
bool(has_accepted_ins_last_cycle) && bool(LSQ_queue[last_idx].E2) && !last_cycle_V2_proccessed;
|
||||||
// now alu, memory (and L0 cache of memory) may provide data to satisfy the dependency
|
// now alu, memory may provide data to satisfy the dependency
|
||||||
auto process_listend_data = [&](uint32_t res_ROB_index, uint32_t res_value) -> void {
|
auto process_listend_data = [&](uint32_t res_ROB_index, uint32_t res_value) -> void {
|
||||||
uint32_t ptr = static_cast<max_size_t>(LSQ_head);
|
uint32_t ptr = static_cast<max_size_t>(LSQ_head);
|
||||||
while (ptr != static_cast<max_size_t>(LSQ_tail)) {
|
while (ptr != static_cast<max_size_t>(LSQ_tail)) {
|
||||||
@ -196,9 +196,9 @@ struct LoadStoreQueue : public dark::Module<LoadStoreQueue_Input, LoadStoreQueue
|
|||||||
process_listend_data(static_cast<max_size_t>(completed_memins_ROB_index),
|
process_listend_data(static_cast<max_size_t>(completed_memins_ROB_index),
|
||||||
static_cast<max_size_t>(completed_memins_read_data));
|
static_cast<max_size_t>(completed_memins_read_data));
|
||||||
}
|
}
|
||||||
if (static_cast<max_size_t>(cache_hit) == 1) {
|
// if (static_cast<max_size_t>(cache_hit) == 1) {
|
||||||
process_listend_data(static_cast<max_size_t>(cache_hit_ROB_index), static_cast<max_size_t>(cache_hit_data));
|
// process_listend_data(static_cast<max_size_t>(cache_hit_ROB_index), static_cast<max_size_t>(cache_hit_data));
|
||||||
}
|
// }
|
||||||
if (should_monitor_V1) {
|
if (should_monitor_V1) {
|
||||||
LSQ_queue[last_idx].D1 <= 0;
|
LSQ_queue[last_idx].D1 <= 0;
|
||||||
LSQ_queue[last_idx].Q1 <= rs1_deps;
|
LSQ_queue[last_idx].Q1 <= rs1_deps;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#ifndef MEMORY_H
|
#ifndef MEMORY_H
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
using dark::max_size_t;
|
using dark::max_size_t;
|
||||||
@ -16,22 +17,56 @@ struct Memory_Input {
|
|||||||
dark::Wire<32> address_input;
|
dark::Wire<32> address_input;
|
||||||
dark::Wire<32> data_input;
|
dark::Wire<32> data_input;
|
||||||
dark::Wire<5> request_ROB_index;
|
dark::Wire<5> request_ROB_index;
|
||||||
|
dark::Wire<1> is_committing;
|
||||||
|
dark::Wire<5> commit_ins_ROB_index;
|
||||||
};
|
};
|
||||||
struct Memory_Output {
|
struct Memory_Output {
|
||||||
dark::Register<2> data_sign;
|
dark::Register<2> data_sign;
|
||||||
dark::Register<5> completed_memins_ROB_index;
|
dark::Register<5> completed_memins_ROB_index;
|
||||||
dark::Register<32> completed_memins_read_data;
|
dark::Register<32> completed_memins_read_data;
|
||||||
};
|
};
|
||||||
|
struct Change {
|
||||||
|
dark::Register<1> this_byte_changed;
|
||||||
|
dark::Register<32> addr;
|
||||||
|
dark::Register<8> before;
|
||||||
|
};
|
||||||
|
struct OperationPlayback {
|
||||||
|
dark::Register<1> has_uncommitted_write;
|
||||||
|
dark::Register<32> timestamp;
|
||||||
|
std::array<Change, 4> changes;
|
||||||
|
};
|
||||||
struct Memory_Private {
|
struct Memory_Private {
|
||||||
dark::Register<3> status;
|
dark::Register<3> status;
|
||||||
dark::Register<32> cur_opt_addr;
|
dark::Register<32> cur_opt_addr;
|
||||||
dark::Register<32> cur_opt_data;
|
dark::Register<32> cur_opt_data;
|
||||||
dark::Register<2> cur_opt_type;
|
dark::Register<2> cur_opt_type;
|
||||||
dark::Register<2> cur_opt_bytes;
|
dark::Register<2> cur_opt_bytes;
|
||||||
|
std::array<OperationPlayback, 32> playback;
|
||||||
|
dark::Register<32> cur_timestamp;
|
||||||
};
|
};
|
||||||
struct Memory : dark::Module<Memory_Input, Memory_Output, Memory_Private> {
|
struct Memory : dark::Module<Memory_Input, Memory_Output, Memory_Private> {
|
||||||
private:
|
private:
|
||||||
std::vector<uint8_t> memory_data;
|
std::vector<uint8_t> memory_data;
|
||||||
|
void Undo() {
|
||||||
|
std::set<std::pair<uint32_t, std::pair<uint32_t, uint8_t>>> undo_list; // (timestamp, (addr, before))
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
if (bool(playback[i].has_uncommitted_write)) {
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
if (bool(playback[i].changes[j].this_byte_changed)) {
|
||||||
|
undo_list.insert(std::make_pair(static_cast<max_size_t>(playback[i].timestamp),
|
||||||
|
std::make_pair(static_cast<max_size_t>(playback[i].changes[j].addr),
|
||||||
|
static_cast<max_size_t>(playback[i].changes[j].before))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t sz = undo_list.size();
|
||||||
|
auto it = undo_list.end();
|
||||||
|
for (int i = 0; i < sz; i++) {
|
||||||
|
it--;
|
||||||
|
memory_data[it->second.first] = it->second.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Memory() { memory_data.resize(1 << 20, 0); }
|
Memory() { memory_data.resize(1 << 20, 0); }
|
||||||
@ -40,13 +75,22 @@ struct Memory : dark::Module<Memory_Input, Memory_Output, Memory_Private> {
|
|||||||
// do some initialization
|
// do some initialization
|
||||||
status <= 0;
|
status <= 0;
|
||||||
data_sign <= 1;
|
data_sign <= 1;
|
||||||
|
cur_timestamp <= 0;
|
||||||
|
for (int i = 0; i < 32; i++) playback[i].has_uncommitted_write <= 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (bool(force_clear_receiver)) {
|
if (bool(force_clear_receiver)) {
|
||||||
status <= 0;
|
status <= 0;
|
||||||
data_sign <= 1;
|
data_sign <= 1;
|
||||||
|
Undo();
|
||||||
|
cur_timestamp <= 0;
|
||||||
|
for (int i = 0; i < 32; i++) playback[i].has_uncommitted_write <= 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (bool(is_committing)) {
|
||||||
|
playback[static_cast<max_size_t>(commit_ins_ROB_index)].has_uncommitted_write <= 0;
|
||||||
|
}
|
||||||
|
cur_timestamp <= static_cast<max_size_t>(cur_timestamp) + 1;
|
||||||
max_size_t request_type_signal = max_size_t(request_type_input);
|
max_size_t request_type_signal = max_size_t(request_type_input);
|
||||||
uint8_t rw_type = request_type_signal & 3; // 0b00->none,0b01->read,0b10->write,0b11->invalid
|
uint8_t rw_type = request_type_signal & 3; // 0b00->none,0b01->read,0b10->write,0b11->invalid
|
||||||
uint8_t opt_bytes = (request_type_signal >> 2) & 3; // 0->1, 1->2, 2->4
|
uint8_t opt_bytes = (request_type_signal >> 2) & 3; // 0->1, 1->2, 2->4
|
||||||
@ -91,25 +135,60 @@ struct Memory : dark::Module<Memory_Input, Memory_Output, Memory_Private> {
|
|||||||
default:
|
default:
|
||||||
throw std::runtime_error("Invalid bytes");
|
throw std::runtime_error("Invalid bytes");
|
||||||
}
|
}
|
||||||
|
data_sign <= 2; // has data and free
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
size_t len = 1 << max_size_t(cur_opt_bytes);
|
size_t len = 1 << max_size_t(cur_opt_bytes);
|
||||||
|
uint32_t cur_opt_ROB_index = static_cast<max_size_t>(completed_memins_ROB_index);
|
||||||
switch (len) {
|
switch (len) {
|
||||||
case 1:
|
case 1:
|
||||||
|
playback[cur_opt_ROB_index].has_uncommitted_write <= 1;
|
||||||
|
playback[cur_opt_ROB_index].timestamp <= cur_timestamp;
|
||||||
|
playback[cur_opt_ROB_index].changes[0].this_byte_changed <= 1;
|
||||||
|
playback[cur_opt_ROB_index].changes[0].addr <= cur_opt_addr;
|
||||||
|
playback[cur_opt_ROB_index].changes[0].before <= memory_data[max_size_t(cur_opt_addr)];
|
||||||
|
playback[cur_opt_ROB_index].changes[1].this_byte_changed <= 0;
|
||||||
|
playback[cur_opt_ROB_index].changes[2].this_byte_changed <= 0;
|
||||||
|
playback[cur_opt_ROB_index].changes[3].this_byte_changed <= 0;
|
||||||
memory_data[max_size_t(cur_opt_addr)] = max_size_t(cur_opt_data) & 0xff;
|
memory_data[max_size_t(cur_opt_addr)] = max_size_t(cur_opt_data) & 0xff;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
playback[cur_opt_ROB_index].has_uncommitted_write <= 1;
|
||||||
|
playback[cur_opt_ROB_index].timestamp <= cur_timestamp;
|
||||||
|
playback[cur_opt_ROB_index].changes[0].this_byte_changed <= 1;
|
||||||
|
playback[cur_opt_ROB_index].changes[0].addr <= cur_opt_addr;
|
||||||
|
playback[cur_opt_ROB_index].changes[0].before <= memory_data[max_size_t(cur_opt_addr)];
|
||||||
|
playback[cur_opt_ROB_index].changes[1].this_byte_changed <= 1;
|
||||||
|
playback[cur_opt_ROB_index].changes[1].addr <= cur_opt_addr + 1;
|
||||||
|
playback[cur_opt_ROB_index].changes[1].before <= memory_data[max_size_t(cur_opt_addr) + 1];
|
||||||
|
playback[cur_opt_ROB_index].changes[2].this_byte_changed <= 0;
|
||||||
|
playback[cur_opt_ROB_index].changes[3].this_byte_changed <= 0;
|
||||||
*reinterpret_cast<uint16_t *>(&memory_data[max_size_t(cur_opt_addr)]) = max_size_t(cur_opt_data) & 0xffff;
|
*reinterpret_cast<uint16_t *>(&memory_data[max_size_t(cur_opt_addr)]) = max_size_t(cur_opt_data) & 0xffff;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
|
playback[cur_opt_ROB_index].has_uncommitted_write <= 1;
|
||||||
|
playback[cur_opt_ROB_index].timestamp <= cur_timestamp;
|
||||||
|
playback[cur_opt_ROB_index].changes[0].this_byte_changed <= 1;
|
||||||
|
playback[cur_opt_ROB_index].changes[0].addr <= cur_opt_addr;
|
||||||
|
playback[cur_opt_ROB_index].changes[0].before <= memory_data[max_size_t(cur_opt_addr)];
|
||||||
|
playback[cur_opt_ROB_index].changes[1].this_byte_changed <= 1;
|
||||||
|
playback[cur_opt_ROB_index].changes[1].addr <= cur_opt_addr + 1;
|
||||||
|
playback[cur_opt_ROB_index].changes[1].before <= memory_data[max_size_t(cur_opt_addr) + 1];
|
||||||
|
playback[cur_opt_ROB_index].changes[2].this_byte_changed <= 1;
|
||||||
|
playback[cur_opt_ROB_index].changes[2].addr <= cur_opt_addr + 2;
|
||||||
|
playback[cur_opt_ROB_index].changes[2].before <= memory_data[max_size_t(cur_opt_addr) + 2];
|
||||||
|
playback[cur_opt_ROB_index].changes[3].this_byte_changed <= 1;
|
||||||
|
playback[cur_opt_ROB_index].changes[3].addr <= cur_opt_addr + 3;
|
||||||
|
playback[cur_opt_ROB_index].changes[3].before <= memory_data[max_size_t(cur_opt_addr) + 3];
|
||||||
*reinterpret_cast<uint32_t *>(&memory_data[max_size_t(cur_opt_addr)]) = max_size_t(cur_opt_data);
|
*reinterpret_cast<uint32_t *>(&memory_data[max_size_t(cur_opt_addr)]) = max_size_t(cur_opt_data);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Invalid bytes");
|
throw std::runtime_error("Invalid bytes");
|
||||||
}
|
}
|
||||||
}
|
data_sign <= 1; // free
|
||||||
data_sign <= 2; // has data and free
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// now the memory is not busy
|
// now the memory is not busy
|
||||||
if (request_type_signal == 0) {
|
if (request_type_signal == 0) {
|
||||||
data_sign <= 1; // free
|
data_sign <= 1; // free
|
||||||
|
@ -8,7 +8,7 @@ const static size_t kTotalRegisters = 32;
|
|||||||
struct RegisterFile_Input {
|
struct RegisterFile_Input {
|
||||||
// receive control signal from CSU
|
// receive control signal from CSU
|
||||||
dark::Wire<1> reset;
|
dark::Wire<1> reset;
|
||||||
dark::Wire<1> force_clear_receiver;
|
// dark::Wire<1> force_clear_receiver;
|
||||||
dark::Wire<1> is_issuing;
|
dark::Wire<1> is_issuing;
|
||||||
dark::Wire<1> issue_type;
|
dark::Wire<1> issue_type;
|
||||||
dark::Wire<5> issue_ROB_index;
|
dark::Wire<5> issue_ROB_index;
|
||||||
@ -21,6 +21,7 @@ struct RegisterFile_Input {
|
|||||||
dark::Wire<5> decoded_rs2;
|
dark::Wire<5> decoded_rs2;
|
||||||
dark::Wire<1> has_decoded_rs2;
|
dark::Wire<1> has_decoded_rs2;
|
||||||
dark::Wire<1> is_committing;
|
dark::Wire<1> is_committing;
|
||||||
|
dark::Wire<1> has_resulting_register;
|
||||||
dark::Wire<5> commit_ins_ROB_index;
|
dark::Wire<5> commit_ins_ROB_index;
|
||||||
dark::Wire<5> commit_reg_index;
|
dark::Wire<5> commit_reg_index;
|
||||||
dark::Wire<32> commit_reg_value;
|
dark::Wire<32> commit_reg_value;
|
||||||
@ -56,17 +57,19 @@ struct RegisterFile : public dark::Module<RegisterFile_Input, RegisterFile_Outpu
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (bool(is_committing)) {
|
if (bool(is_committing)) {
|
||||||
|
if (bool(has_resulting_register)) {
|
||||||
registers[static_cast<max_size_t>(commit_reg_index)] <= commit_reg_value;
|
registers[static_cast<max_size_t>(commit_reg_index)] <= commit_reg_value;
|
||||||
if (register_deps[static_cast<max_size_t>(commit_reg_index)] == commit_ins_ROB_index) {
|
if (register_deps[static_cast<max_size_t>(commit_reg_index)] == commit_ins_ROB_index) {
|
||||||
register_nodep[static_cast<max_size_t>(commit_reg_index)] <= 1;
|
register_nodep[static_cast<max_size_t>(commit_reg_index)] <= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (bool(is_issuing)) {
|
if (bool(is_issuing)) {
|
||||||
if (bool(has_decoded_rs1)) {
|
if (bool(has_decoded_rs1)) {
|
||||||
if ((!bool(is_committing)) || (commit_reg_index != decoded_rs1)) {
|
if ((!bool(is_committing)) || (commit_reg_index != decoded_rs1)) {
|
||||||
rs1_deps <= register_deps[static_cast<max_size_t>(decoded_rs1)];
|
rs1_deps <= register_deps[static_cast<max_size_t>(decoded_rs1)].peek();
|
||||||
rs1_value <= registers[static_cast<max_size_t>(decoded_rs1)];
|
rs1_value <= registers[static_cast<max_size_t>(decoded_rs1)].peek();
|
||||||
rs1_nodep <= register_nodep[static_cast<max_size_t>(decoded_rs1)];
|
rs1_nodep <= register_nodep[static_cast<max_size_t>(decoded_rs1)].peek();
|
||||||
} else {
|
} else {
|
||||||
rs1_deps <= 0;
|
rs1_deps <= 0;
|
||||||
rs1_value <= commit_reg_value;
|
rs1_value <= commit_reg_value;
|
||||||
@ -75,9 +78,9 @@ struct RegisterFile : public dark::Module<RegisterFile_Input, RegisterFile_Outpu
|
|||||||
}
|
}
|
||||||
if (bool(has_decoded_rs2)) {
|
if (bool(has_decoded_rs2)) {
|
||||||
if ((!bool(is_committing)) || (commit_reg_index != decoded_rs2)) {
|
if ((!bool(is_committing)) || (commit_reg_index != decoded_rs2)) {
|
||||||
rs2_deps <= register_deps[static_cast<max_size_t>(decoded_rs2)];
|
rs2_deps <= register_deps[static_cast<max_size_t>(decoded_rs2)].peek();
|
||||||
rs2_value <= registers[static_cast<max_size_t>(decoded_rs2)];
|
rs2_value <= registers[static_cast<max_size_t>(decoded_rs2)].peek();
|
||||||
rs2_nodep <= register_nodep[static_cast<max_size_t>(decoded_rs2)];
|
rs2_nodep <= register_nodep[static_cast<max_size_t>(decoded_rs2)].peek();
|
||||||
} else {
|
} else {
|
||||||
rs2_deps <= 0;
|
rs2_deps <= 0;
|
||||||
rs2_value <= commit_reg_value;
|
rs2_value <= commit_reg_value;
|
||||||
|
@ -42,9 +42,9 @@ struct ReserveStation_Input {
|
|||||||
dark::Wire<5> completed_memins_ROB_index;
|
dark::Wire<5> completed_memins_ROB_index;
|
||||||
dark::Wire<32> completed_memins_read_data;
|
dark::Wire<32> completed_memins_read_data;
|
||||||
// receive status signal from L0 cache(data from Memory)
|
// receive status signal from L0 cache(data from Memory)
|
||||||
dark::Wire<1> cache_hit;
|
// dark::Wire<1> cache_hit;
|
||||||
dark::Wire<5> cache_hit_ROB_index;
|
// dark::Wire<5> cache_hit_ROB_index;
|
||||||
dark::Wire<32> cache_hit_data;
|
// dark::Wire<32> cache_hit_data;
|
||||||
};
|
};
|
||||||
struct ReserveStation_Output {
|
struct ReserveStation_Output {
|
||||||
// alu will listen for these:
|
// alu will listen for these:
|
||||||
@ -156,7 +156,7 @@ struct ReserveStation : public dark::Module<ReserveStation_Input, ReserveStation
|
|||||||
last_cycle_V2_proccessed = true;
|
last_cycle_V2_proccessed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: now alu, memory (and L0 cache of memory) may provide data to satisfy the dependency
|
// TODO: now alu, memory may provide data to satisfy the dependency
|
||||||
bool should_monitor_V1 =
|
bool should_monitor_V1 =
|
||||||
bool(has_accepted_ins_last_cycle) && bool(RS_records[last_idx].E1) && (!last_cycle_V1_proccessed);
|
bool(has_accepted_ins_last_cycle) && bool(RS_records[last_idx].E1) && (!last_cycle_V1_proccessed);
|
||||||
bool should_monitor_V2 =
|
bool should_monitor_V2 =
|
||||||
@ -197,8 +197,16 @@ struct ReserveStation : public dark::Module<ReserveStation_Input, ReserveStation
|
|||||||
process_listend_data(static_cast<max_size_t>(completed_memins_ROB_index),
|
process_listend_data(static_cast<max_size_t>(completed_memins_ROB_index),
|
||||||
static_cast<max_size_t>(completed_memins_read_data));
|
static_cast<max_size_t>(completed_memins_read_data));
|
||||||
}
|
}
|
||||||
if (static_cast<max_size_t>(cache_hit) == 1) {
|
// if (static_cast<max_size_t>(cache_hit) == 1) {
|
||||||
process_listend_data(static_cast<max_size_t>(cache_hit_ROB_index), static_cast<max_size_t>(cache_hit_data));
|
// process_listend_data(static_cast<max_size_t>(cache_hit_ROB_index), static_cast<max_size_t>(cache_hit_data));
|
||||||
|
// }
|
||||||
|
if (should_monitor_V1) {
|
||||||
|
RS_records[last_idx].Q1 <= rs1_deps;
|
||||||
|
RS_records[last_idx].D1 <= 0;
|
||||||
|
}
|
||||||
|
if (should_monitor_V2) {
|
||||||
|
RS_records[last_idx].Q2 <= rs2_deps;
|
||||||
|
RS_records[last_idx].D2 <= 0;
|
||||||
}
|
}
|
||||||
// TODO: now, we can check if we can execute the instruction, memory and L0 cache will listen to this
|
// TODO: now, we can check if we can execute the instruction, memory and L0 cache will listen to this
|
||||||
if (bool(has_accepted_ins_last_cycle)) RS_records[last_idx].state <= 2;
|
if (bool(has_accepted_ins_last_cycle)) RS_records[last_idx].state <= 2;
|
||||||
|
17
src/main.cpp
17
src/main.cpp
@ -37,6 +37,8 @@ int main(int argc, char **argv) {
|
|||||||
// now connect the wires, see the comment and docs for help
|
// now connect the wires, see the comment and docs for help
|
||||||
// csu <-> memory
|
// csu <-> memory
|
||||||
RWConnect(csu.force_clear_announcer, memory.force_clear_receiver);
|
RWConnect(csu.force_clear_announcer, memory.force_clear_receiver);
|
||||||
|
RWConnect(csu.is_committing, memory.is_committing);
|
||||||
|
RWConnect(csu.commit_ins_ROB_index, memory.commit_ins_ROB_index);
|
||||||
RWConnect(memory.data_sign, csu.mem_status_receiver);
|
RWConnect(memory.data_sign, csu.mem_status_receiver);
|
||||||
RWConnect(memory.completed_memins_ROB_index, csu.completed_memins_ROB_index);
|
RWConnect(memory.completed_memins_ROB_index, csu.completed_memins_ROB_index);
|
||||||
RWConnect(memory.completed_memins_read_data, csu.completed_memins_read_data);
|
RWConnect(memory.completed_memins_read_data, csu.completed_memins_read_data);
|
||||||
@ -59,9 +61,9 @@ int main(int argc, char **argv) {
|
|||||||
RWConnect(csu.rs2_is_in_ROB, lsq.rs2_is_in_ROB);
|
RWConnect(csu.rs2_is_in_ROB, lsq.rs2_is_in_ROB);
|
||||||
RWConnect(csu.rs2_in_ROB_value, lsq.rs2_in_ROB_value);
|
RWConnect(csu.rs2_in_ROB_value, lsq.rs2_in_ROB_value);
|
||||||
RWConnect(csu.decoded_imm, lsq.decoded_imm);
|
RWConnect(csu.decoded_imm, lsq.decoded_imm);
|
||||||
RWConnect(csu.cache_hit, lsq.cache_hit);
|
// RWConnect(csu.cache_hit, lsq.cache_hit);
|
||||||
RWConnect(csu.cache_hit_ROB_index, lsq.cache_hit_ROB_index);
|
// RWConnect(csu.cache_hit_ROB_index, lsq.cache_hit_ROB_index);
|
||||||
RWConnect(csu.cache_hit_data, lsq.cache_hit_data);
|
// RWConnect(csu.cache_hit_data, lsq.cache_hit_data);
|
||||||
RWConnect(lsq.mem_request_full_ins_id, csu.mem_request_full_ins_id);
|
RWConnect(lsq.mem_request_full_ins_id, csu.mem_request_full_ins_id);
|
||||||
RWConnect(lsq.request_type_output, csu.mem_request_type_input);
|
RWConnect(lsq.request_type_output, csu.mem_request_type_input);
|
||||||
RWConnect(lsq.request_ROB_index, csu.mem_request_ROB_index);
|
RWConnect(lsq.request_ROB_index, csu.mem_request_ROB_index);
|
||||||
@ -74,7 +76,7 @@ int main(int argc, char **argv) {
|
|||||||
RWConnect(alu.result, csu.completed_aluins_result);
|
RWConnect(alu.result, csu.completed_aluins_result);
|
||||||
RWConnect(alu.completed_alu_resulting_PC, csu.completed_alu_resulting_PC);
|
RWConnect(alu.completed_alu_resulting_PC, csu.completed_alu_resulting_PC);
|
||||||
// csu <-> register file
|
// csu <-> register file
|
||||||
RWConnect(csu.force_clear_announcer, rf.force_clear_receiver);
|
// RWConnect(csu.force_clear_announcer, rf.force_clear_receiver);
|
||||||
RWConnect(csu.is_issuing, rf.is_issuing);
|
RWConnect(csu.is_issuing, rf.is_issuing);
|
||||||
RWConnect(csu.issue_type, rf.issue_type);
|
RWConnect(csu.issue_type, rf.issue_type);
|
||||||
RWConnect(csu.issue_ROB_index, rf.issue_ROB_index);
|
RWConnect(csu.issue_ROB_index, rf.issue_ROB_index);
|
||||||
@ -91,6 +93,7 @@ int main(int argc, char **argv) {
|
|||||||
// RWConnect(rf.rs2_nodep, csu.rs2_nodep);
|
// RWConnect(rf.rs2_nodep, csu.rs2_nodep);
|
||||||
// RWConnect(rf.rs2_deps, csu.rs2_deps);
|
// RWConnect(rf.rs2_deps, csu.rs2_deps);
|
||||||
RWConnect(csu.is_committing, rf.is_committing);
|
RWConnect(csu.is_committing, rf.is_committing);
|
||||||
|
RWConnect(csu.commit_has_resulting_register, rf.has_resulting_register);
|
||||||
RWConnect(csu.commit_reg_index, rf.commit_reg_index);
|
RWConnect(csu.commit_reg_index, rf.commit_reg_index);
|
||||||
RWConnect(csu.commit_reg_value, rf.commit_reg_value);
|
RWConnect(csu.commit_reg_value, rf.commit_reg_value);
|
||||||
RWConnect(csu.commit_ins_ROB_index, rf.commit_ins_ROB_index);
|
RWConnect(csu.commit_ins_ROB_index, rf.commit_ins_ROB_index);
|
||||||
@ -114,9 +117,9 @@ int main(int argc, char **argv) {
|
|||||||
RWConnect(csu.rs2_in_ROB_value, rs.rs2_in_ROB_value);
|
RWConnect(csu.rs2_in_ROB_value, rs.rs2_in_ROB_value);
|
||||||
RWConnect(csu.decoded_imm, rs.decoded_imm);
|
RWConnect(csu.decoded_imm, rs.decoded_imm);
|
||||||
RWConnect(csu.decoded_shamt, rs.decoded_shamt);
|
RWConnect(csu.decoded_shamt, rs.decoded_shamt);
|
||||||
RWConnect(csu.cache_hit, rs.cache_hit);
|
// RWConnect(csu.cache_hit, rs.cache_hit);
|
||||||
RWConnect(csu.cache_hit_ROB_index, rs.cache_hit_ROB_index);
|
// RWConnect(csu.cache_hit_ROB_index, rs.cache_hit_ROB_index);
|
||||||
RWConnect(csu.cache_hit_data, rs.cache_hit_data);
|
// RWConnect(csu.cache_hit_data, rs.cache_hit_data);
|
||||||
RWConnect(rs.RS_remain_space_output, csu.reservestation_emptyspace_receiver);
|
RWConnect(rs.RS_remain_space_output, csu.reservestation_emptyspace_receiver);
|
||||||
// memory <-> lsq
|
// memory <-> lsq
|
||||||
RWConnect(memory.data_sign, lsq.mem_data_sign);
|
RWConnect(memory.data_sign, lsq.mem_data_sign);
|
||||||
|
Reference in New Issue
Block a user