This commit is contained in:
2024-08-01 04:13:59 +00:00
parent d6e6498eee
commit 1ff419b22d
9 changed files with 98 additions and 16 deletions

View File

@ -24,7 +24,8 @@ struct ALU : public dark::Module<ALU_Input, ALU_Output> {
}
void work() {
std::cerr << "ALU: cur request_full_id=" << std::hex << std::setw(8) << std::setfill('0') << std::uppercase
<< static_cast<max_size_t>(request_full_id) << std::endl;
<< static_cast<max_size_t>(request_full_id) << " request_ROB_index=" << std::dec
<< static_cast<max_size_t>(request_ROB_index) << std::endl;
switch (static_cast<max_size_t>(request_full_id)) {
case 0: {
alu_status <= 0b01;
@ -66,6 +67,8 @@ struct ALU : public dark::Module<ALU_Input, ALU_Output> {
alu_status <= 0b10;
result_ROB_index <= request_ROB_index;
result <= static_cast<max_size_t>(request_PC) + 4;
std::cerr << "alu: jalr: imm=" << std::hex << static_cast<max_size_t>(imm) << std::endl;
std::cerr << "alu: jalr: operand1=" << std::hex << static_cast<max_size_t>(operand1) << std::endl;
completed_alu_resulting_PC <= ((static_cast<max_size_t>(operand1) + static_cast<max_size_t>(imm)) & 0xfffffffe);
return;
}

View File

@ -1,4 +1,5 @@
#pragma once
#include "concept.h"
#include "module.h"
#include "wire.h"
#include <algorithm>
@ -64,11 +65,13 @@ public:
auto func = shuffle ? &CPU::run_once_shuffle : &CPU::run_once;
reset_signal=true;
while (max_cycles == 0 || cycles < max_cycles) {
std::cerr<<"clock: "<<std::dec<<global_clock<<std::endl;
std::cerr<<"\nclock: "<<std::dec<<global_clock<<std::endl;
(this->*func)();
reset_signal=false;
uint32_t halt_signal_value = max_size_t(halt_signal);
if(halt_signal_value &(1<<9)) {
halt_signal.sync();
uint32_t halt_signal_value = static_cast<max_size_t>(halt_signal);
std::cerr<<"simulator received halt_signal_value="<<std::dec<<halt_signal_value<<std::endl;
if(halt_signal_value &(1<<8)) {
return halt_signal_value&0xff;
}
global_clock++;

View File

@ -12,6 +12,7 @@ namespace ZYM {
const int kROBSize = 32;
const int kTotalRegister = 32;
struct CentralScheduleUnit_Input {
dark::Wire<8> a0;
dark::Wire<1> reset;
// data from load store queue
dark::Wire<6> load_store_queue_emptyspace_receiver;
@ -262,7 +263,8 @@ struct CentralScheduleUnit
}
ROB_next_remain_space++;
if (record.instruction == 0x0ff00513) {
halt_signal <= 0b100000000;
halt_signal <= (0b100000000 | static_cast<max_size_t>(a0));
std::cerr << "halting with code " << std::dec << int(halt_signal.peek()) << std::endl;
}
}
}
@ -281,23 +283,28 @@ struct CentralScheduleUnit
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)) {
if (res_PC != static_cast<max_size_t>(record.resulting_PC) &&
(static_cast<max_size_t>(record.instruction) & 0x7F) != 0b1100111) {
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;
predicted_PC <= res_PC;
std::cerr << "The jalr instruction is committed, now predicted_PC is " << std::hex << std::setw(8)
<< std::setfill('0') << std::uppercase << predicted_PC.peek() << std::endl;
}
}
record.state <= 3;
}
}
};
std::cerr << "csu is listening data from memory" << std::endl;
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);
}
std::cerr << "csu is listening data from alu" << std::endl;
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),
@ -383,7 +390,7 @@ struct CentralScheduleUnit
break;
case 0b1100111:
// jalr
std::cerr<<"encounter jalr"<<std::endl;
std::cerr << "encounter jalr" << std::endl;
ROB_records[tail].resulting_PC_ready <= 0;
has_predicted_PC <= 0;
break;
@ -427,23 +434,39 @@ struct CentralScheduleUnit
}
// provide the potentially missing data for instruction issued last cycle
if (bool(has_instruction_issued_last_cycle)) {
std::cerr << "CSU is processing potentially missing data for instruction issued last cycle" << std::endl;
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);
for (uint32_t ptr = static_cast<max_size_t>(ROB_head);
ptr != static_cast<max_size_t>(ROB_tail) && (ptr + 1) % kROBSize != 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) {
if (bool(ROB_records[ptr].has_resulting_register) &&
static_cast<max_size_t>(ROB_records[ptr].resulting_register_idx) == rs1) {
rs1_v = ROB_records[ptr].resulting_register_value.peek();
found_rs1 = 1;
std::cerr << "matching rs1=" << std::dec << int(rs1) << " ptr=" << std::dec << ptr << " rs1_v=" << std::hex
<< std::setw(8) << std::setfill('0') << rs1_v << std::endl;
}
if (static_cast<max_size_t>(ROB_records[ptr].resulting_register_idx) == rs2) {
if (bool(ROB_records[ptr].has_resulting_register) &&
static_cast<max_size_t>(ROB_records[ptr].resulting_register_idx) == rs2) {
rs2_v = ROB_records[ptr].resulting_register_value.peek();
found_rs2 = 1;
}
} else {
if (bool(ROB_records[ptr].has_resulting_register) &&
static_cast<max_size_t>(ROB_records[ptr].resulting_register_idx) == rs1) {
found_rs1 = 0;
std::cerr << "dematching rs1=" << std::dec << int(rs1) << " ptr=" << std::dec << ptr << std::endl;
}
if (bool(ROB_records[ptr].has_resulting_register) &&
static_cast<max_size_t>(ROB_records[ptr].resulting_register_idx) == rs2) {
found_rs2 = 0;
}
}
}
this->rs1_is_in_ROB <= found_rs1;

View File

@ -124,6 +124,16 @@ struct LoadStoreQueue : public dark::Module<LoadStoreQueue_Input, LoadStoreQueue
LSQ_queue[cur_queue_tail].E2 <= has_decoded_rs2;
LSQ_queue[cur_queue_tail].D1 <= 1; // temporarily
LSQ_queue[cur_queue_tail].D2 <= 1; // temporarily
std::cerr << "LoadStoreQueue is accepting instruction" << std::endl;
std::cerr << "\tfull_ins_id: " << std::hex << static_cast<max_size_t>(full_ins_id) << std::endl;
std::cerr << "\tins_ROB_index: " << std::dec << static_cast<max_size_t>(issue_ROB_index) << std::endl;
std::cerr << "\tins_self_PC: " << std::hex << std::setw(8) << std::setfill('0')
<< static_cast<max_size_t>(issuing_PC) << std::endl;
std::cerr << "\tins_imm: " << std::hex << static_cast<max_size_t>(decoded_imm) << std::endl;
std::cerr << "\thas_decoded_rs1: " << std::hex << std::setw(8) << std::setfill('0')
<< static_cast<max_size_t>(has_decoded_rs1) << std::endl;
std::cerr << "\thas_decoded_rs2: " << std::hex << std::setw(8) << std::setfill('0')
<< static_cast<max_size_t>(has_decoded_rs2) << std::endl;
// LSQ_queue[cur_queue_tail].Q1 <= decoded_rs1; // temporarily, no use
// LSQ_queue[cur_queue_tail].Q2 <= decoded_rs2; // temporarily, no use
} else
@ -134,10 +144,13 @@ struct LoadStoreQueue : public dark::Module<LoadStoreQueue_Input, LoadStoreQueue
if (bool(has_accepted_ins_last_cycle)) {
// now dependency info can be read from the register file, in the mean time, CSU will provide the
// potentially missing data
std::cerr << "LoadStoreQueue is process dependency information from register file and ROB" << std::endl;
if (bool(LSQ_queue[last_idx].E1) && bool(rs1_nodep)) {
LSQ_queue[last_idx].V1 <= rs1_value;
LSQ_queue[last_idx].D1 <= 1;
last_cycle_V1_proccessed = true;
std::cerr << "\t from register file: LSQ_queue[last_idx].V1=" << std::hex << std::setw(8) << std::setfill('0')
<< static_cast<max_size_t>(LSQ_queue[last_idx].V1) << std::endl;
}
if (bool(LSQ_queue[last_idx].E2) && bool(rs2_nodep)) {
LSQ_queue[last_idx].V2 <= rs2_value;
@ -148,12 +161,15 @@ struct LoadStoreQueue : public dark::Module<LoadStoreQueue_Input, LoadStoreQueue
LSQ_queue[last_idx].V1 <= rs1_in_ROB_value;
LSQ_queue[last_idx].D1 <= 1;
last_cycle_V1_proccessed = true;
std::cerr << "\t from ROB: LSQ_queue[last_idx].V1=" << std::hex << std::setw(8) << std::setfill('0')
<< static_cast<max_size_t>(LSQ_queue[last_idx].V1) << std::endl;
}
if (bool(LSQ_queue[last_idx].E2) && (!bool(rs2_nodep)) && bool(rs2_is_in_ROB)) {
LSQ_queue[last_idx].V2 <= rs2_in_ROB_value;
LSQ_queue[last_idx].D2 <= 1;
last_cycle_V2_proccessed = true;
}
std::cerr << "End of processing dependency information from register file and ROB" << std::endl;
}
bool should_monitor_V1 =
bool(has_accepted_ins_last_cycle) && bool(LSQ_queue[last_idx].E1) && !last_cycle_V1_proccessed;
@ -188,10 +204,12 @@ struct LoadStoreQueue : public dark::Module<LoadStoreQueue_Input, LoadStoreQueue
ptr = (ptr + 1) % 32;
}
};
std::cerr << "Load Store Queue is listening data from alu" << std::endl;
if (static_cast<max_size_t>(alu_status_receiver) == 0b10) {
process_listend_data(static_cast<max_size_t>(completed_aluins_ROB_index),
static_cast<max_size_t>(completed_aluins_result));
}
std::cerr << "Load Store Queue is listening data from memory" << std::endl;
if (static_cast<max_size_t>(mem_data_sign) == 0b10) {
process_listend_data(static_cast<max_size_t>(completed_memins_ROB_index),
static_cast<max_size_t>(completed_memins_read_data));

View File

@ -116,6 +116,8 @@ struct Memory : dark::Module<Memory_Input, Memory_Output, Memory_Private> {
}
}
completed_memins_read_data <= tmp;
std::cerr << "memory read: " << std::hex << std::setfill('0') << std::setw(2) << tmp << " from " << std::hex
<< static_cast<max_size_t>(cur_opt_addr) << std::endl;
break;
}
case 2: {
@ -127,10 +129,15 @@ struct Memory : dark::Module<Memory_Input, Memory_Output, Memory_Private> {
}
}
completed_memins_read_data <= tmp;
std::cerr << "memory read: " << std::hex << std::setfill('0') << std::setw(4) << tmp << " from " << std::hex
<< static_cast<max_size_t>(cur_opt_addr) << std::endl;
break;
}
case 4:
completed_memins_read_data <= *reinterpret_cast<uint32_t *>(&memory_data[max_size_t(cur_opt_addr)]);
std::cerr << "memory read: " << std::hex << std::setfill('0') << std::setw(8)
<< *reinterpret_cast<uint32_t *>(&memory_data[max_size_t(cur_opt_addr)]) << " from " << std::hex
<< static_cast<max_size_t>(cur_opt_addr) << std::endl;
break;
default:
throw std::runtime_error("Invalid bytes");
@ -181,11 +188,12 @@ struct Memory : dark::Module<Memory_Input, Memory_Output, Memory_Private> {
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);
std::cerr << "Memory executing sw" << std::endl;
break;
default:
throw std::runtime_error("Invalid bytes");
}
data_sign <= 1; // free
data_sign <= 2; // free
return;
}
}
@ -201,6 +209,7 @@ struct Memory : dark::Module<Memory_Input, Memory_Output, Memory_Private> {
cur_opt_data <= data_input;
cur_opt_type <= rw_type;
cur_opt_bytes <= opt_bytes;
std::cerr << "Memory is accepting a request" << std::endl;
}
max_size_t FetchInstruction(max_size_t addr) { // assume we have a super nb instruction fetch method that can fetch
// an instruction immediately
@ -228,7 +237,7 @@ struct Memory : dark::Module<Memory_Input, Memory_Output, Memory_Private> {
for (int i = 0; i < buf.size(); i++) {
memory_data[addr + i] = buf[i];
// DEBUG_CERR << std::hex << addr + i << ' ' << std::uppercase << std::setw(2) << std::setfill('0') << std::hex
// << (int)buf[i] << std::endl;
// << (int)buf[i] << std::endl;
}
fin.clear();
} while (!fin.eof());

View File

@ -1,4 +1,5 @@
#pragma once
#include <iomanip>
#include "concept.h"
#ifndef REGISTERFILE_H
#include <array>
@ -43,6 +44,7 @@ struct RegisterFile : public dark::Module<RegisterFile_Input, RegisterFile_Outpu
RegisterFile() {
// Constructor
}
uint8_t ReturnExitCodeImmediately() { return registers[10].peek() & 0xff; }
void work() {
if (bool(reset)) {
for (auto &reg : registers) {
@ -65,8 +67,13 @@ struct RegisterFile : public dark::Module<RegisterFile_Input, RegisterFile_Outpu
}
}
if (bool(is_issuing)) {
std::cerr << "Register File Found CSU is issuing" << std::endl;
if (bool(has_decoded_rs1)) {
if ((!bool(is_committing)) || (commit_reg_index != decoded_rs1)) {
if (static_cast<max_size_t>(decoded_rs1) == 0) {
rs1_deps <= 0;
rs1_value <= 0;
rs1_nodep <= 1;
} else if ((!bool(is_committing)) || (commit_reg_index != decoded_rs1)) {
rs1_deps <= register_deps[static_cast<max_size_t>(decoded_rs1)].peek();
rs1_value <= registers[static_cast<max_size_t>(decoded_rs1)].peek();
rs1_nodep <= register_nodep[static_cast<max_size_t>(decoded_rs1)].peek();
@ -75,9 +82,16 @@ struct RegisterFile : public dark::Module<RegisterFile_Input, RegisterFile_Outpu
rs1_value <= commit_reg_value;
rs1_nodep <= 1;
}
std::cerr << std::dec << "rs1_deps=" << rs1_deps.peek() << std::endl;
std::cerr << std::hex << std::setw(8) << std::setfill('0') << "rs1_value=" << rs1_value.peek() << std::endl;
std::cerr << "rs1_nodep=" << rs1_nodep.peek() << std::endl;
}
if (bool(has_decoded_rs2)) {
if ((!bool(is_committing)) || (commit_reg_index != decoded_rs2)) {
if (static_cast<max_size_t>(decoded_rs2) == 0) {
rs2_deps <= 0;
rs2_value <= 0;
rs2_nodep <= 1;
} else if ((!bool(is_committing)) || (commit_reg_index != decoded_rs2)) {
rs2_deps <= register_deps[static_cast<max_size_t>(decoded_rs2)].peek();
rs2_value <= registers[static_cast<max_size_t>(decoded_rs2)].peek();
rs2_nodep <= register_nodep[static_cast<max_size_t>(decoded_rs2)].peek();
@ -86,6 +100,9 @@ struct RegisterFile : public dark::Module<RegisterFile_Input, RegisterFile_Outpu
rs2_value <= commit_reg_value;
rs2_nodep <= 1;
}
std::cerr << std::dec << "rs2_deps=" << rs2_deps.peek() << std::endl;
std::cerr << std::hex << std::setw(8) << std::setfill('0') << "rs2_value=" << rs2_value.peek() << std::endl;
std::cerr << "rs2_nodep=" << rs2_nodep.peek() << std::endl;
}
if (bool(has_decoded_rd)) {
register_deps[static_cast<max_size_t>(decoded_rd)] <= static_cast<max_size_t>(issue_ROB_index);

View File

@ -135,25 +135,30 @@ struct ReserveStation : public dark::Module<ReserveStation_Input, ReserveStation
if (bool(has_accepted_ins_last_cycle)) {
// TODO: now dependency info can be read from the register file, in the mean time, CSU will provide the
// potentially missing data
std::cerr << "Reserve Station is listening dependency info from Register File and CSU" << std::endl;
if (bool(RS_records[last_idx].E1) && bool(rs1_nodep)) {
RS_records[last_idx].V1 <= rs1_value;
RS_records[last_idx].D1 <= 1;
last_cycle_V1_proccessed = true;
std::cerr << "\t Register File: RS1 is not dependent" << std::endl;
}
if (bool(RS_records[last_idx].E2) && bool(rs2_nodep)) {
RS_records[last_idx].V2 <= rs2_value;
RS_records[last_idx].D2 <= 1;
last_cycle_V2_proccessed = true;
std::cerr << "\t Register File: RS2 is not dependent" << std::endl;
}
if (bool(RS_records[last_idx].E1) && (!bool(rs1_nodep)) && bool(rs1_is_in_ROB)) {
RS_records[last_idx].V1 <= rs1_in_ROB_value;
RS_records[last_idx].D1 <= 1;
last_cycle_V1_proccessed = true;
std::cerr << "\t ROB: RS1 is in ROB" << std::endl;
}
if (bool(RS_records[last_idx].E2) && (!bool(rs2_nodep)) && bool(rs2_is_in_ROB)) {
RS_records[last_idx].V2 <= rs2_in_ROB_value;
RS_records[last_idx].D2 <= 1;
last_cycle_V2_proccessed = true;
std::cerr << "\t ROB: RS2 is in ROB" << std::endl;
}
}
// TODO: now alu, memory may provide data to satisfy the dependency
@ -203,10 +208,12 @@ struct ReserveStation : public dark::Module<ReserveStation_Input, ReserveStation
if (should_monitor_V1) {
RS_records[last_idx].Q1 <= rs1_deps;
RS_records[last_idx].D1 <= 0;
std::cerr << "\t RS1 depend on ins of ROB index " << std::dec << RS_records[last_idx].Q1.peek() << std::endl;
}
if (should_monitor_V2) {
RS_records[last_idx].Q2 <= rs2_deps;
RS_records[last_idx].D2 <= 0;
std::cerr << "\t RS2 depend on ins of ROB index " << std::dec << RS_records[last_idx].Q2.peek() << std::endl;
}
// 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;

View File

@ -61,6 +61,7 @@ private:
private:
void sync() { this->_M_holds = false; }
friend class CPU;
template<details::WireFunction<_Len> _Fn>
static auto _M_new_func(_Fn &&fn) {

View File

@ -35,6 +35,7 @@ int main(int argc, char **argv) {
// alu.reset.assign([&]() { return cpu.GetResetSignal(); });
rf.reset.assign([&]() { return cpu.GetResetSignal(); });
rs.reset.assign([&]() { return cpu.GetResetSignal(); });
csu.a0.assign([&]() { return rf.ReturnExitCodeImmediately(); });
// now connect the wires, see the comment and docs for help
// csu <-> memory
RWConnect(csu.force_clear_announcer, memory.force_clear_receiver);
@ -169,6 +170,6 @@ int main(int argc, char **argv) {
RWConnect(rf.rs2_deps, rs.rs2_deps);
RWConnect(rf.rs2_value, rs.rs2_value);
// now start running
std::cout << cpu.run(100, false) << std::endl;
std::cout << uint32_t(cpu.run(1000, false)) << std::endl;
return 0;
}