finish design, ready to write
This commit is contained in:
@ -21,6 +21,12 @@ set_target_properties(interpreter
|
|||||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_executable(code src/main.cpp)
|
||||||
|
set_target_properties(code
|
||||||
|
PROPERTIES
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||||
|
)
|
||||||
|
|
||||||
# Enable sanitizer for debug builds
|
# Enable sanitizer for debug builds
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||||
|
0
include/alu.h
Normal file
0
include/alu.h
Normal file
0
include/bus.h
Normal file
0
include/bus.h
Normal file
@ -1,16 +1,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
#include "wire.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
namespace dark {
|
namespace dark {
|
||||||
|
|
||||||
class CPU {
|
class CPU {
|
||||||
private:
|
private:
|
||||||
std::vector<std::unique_ptr<ModuleBase>> mod_owned;
|
std::vector<std::unique_ptr<ModuleBase>> mod_owned;
|
||||||
std::vector<ModuleBase *> modules;
|
std::vector<ModuleBase *> modules;
|
||||||
|
bool reset_signal = false;
|
||||||
|
dark::Wire<1> halt_signal;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
unsigned long long cycles = 0;
|
unsigned long long cycles = 0;
|
||||||
@ -53,10 +57,16 @@ public:
|
|||||||
module->work();
|
module->work();
|
||||||
sync_all();
|
sync_all();
|
||||||
}
|
}
|
||||||
|
bool GetResetSignal(){
|
||||||
|
return reset_signal;
|
||||||
|
}
|
||||||
void run(unsigned long long max_cycles = 0, bool shuffle = false) {
|
void run(unsigned long long max_cycles = 0, bool shuffle = false) {
|
||||||
auto func = shuffle ? &CPU::run_once_shuffle : &CPU::run_once;
|
auto func = shuffle ? &CPU::run_once_shuffle : &CPU::run_once;
|
||||||
while (max_cycles == 0 || cycles < max_cycles)
|
reset_signal=true;
|
||||||
|
while (max_cycles == 0 || cycles < max_cycles) {
|
||||||
(this->*func)();
|
(this->*func)();
|
||||||
|
reset_signal=false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
24
include/csu.h
Normal file
24
include/csu.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef CSU_H
|
||||||
|
#include "tools.h"
|
||||||
|
namespace ZYM {
|
||||||
|
const int kROBSize = 32;
|
||||||
|
const int kTotalRegister = 32;
|
||||||
|
struct CentralScheduleUnit_Input {
|
||||||
|
dark::Wire<1> reset;
|
||||||
|
};
|
||||||
|
struct CentralScheduleUnit_Output {
|
||||||
|
dark::Register<1> ready;
|
||||||
|
dark::Register<1> force_clear_announcer;
|
||||||
|
};
|
||||||
|
struct CentralScheduleUnit_Private {
|
||||||
|
dark::Register<32> predicated_PC;
|
||||||
|
};
|
||||||
|
struct CentralScheduleUnit
|
||||||
|
: public dark::Module<CentralScheduleUnit_Input, CentralScheduleUnit_Output, CentralScheduleUnit_Private> {
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
CentralScheduleUnit() { ; }
|
||||||
|
};
|
||||||
|
} // namespace ZYM
|
||||||
|
#endif
|
@ -5,6 +5,13 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <source_location>
|
#include <source_location>
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define DEBUG_CERR std::cerr
|
||||||
|
#else
|
||||||
|
#define DEBUG_CERR if(0) std::cerr
|
||||||
|
#endif
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
namespace dark::debug {
|
namespace dark::debug {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
0
include/loadstorequeue.h
Normal file
0
include/loadstorequeue.h
Normal file
136
include/memory.h
Normal file
136
include/memory.h
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <cstddef>
|
||||||
|
#include "concept.h"
|
||||||
|
#ifndef MEMORY_H
|
||||||
|
#include <cstdint>
|
||||||
|
#include <ios>
|
||||||
|
#include <vector>
|
||||||
|
#include "tools.h"
|
||||||
|
using dark::max_size_t;
|
||||||
|
namespace ZYM {
|
||||||
|
struct Memory_Input {
|
||||||
|
dark::Wire<4> request_type_input;
|
||||||
|
dark::Wire<32> address_input;
|
||||||
|
dark::Wire<32> data_input;
|
||||||
|
dark::Wire<1> reset;
|
||||||
|
dark::Wire<1> force_clear_receiver;
|
||||||
|
};
|
||||||
|
struct Memory_Output {
|
||||||
|
dark::Register<1> ready;
|
||||||
|
dark::Register<32> data_output;
|
||||||
|
};
|
||||||
|
struct Memory_Private {
|
||||||
|
dark::Register<3> status;
|
||||||
|
dark::Register<32> cur_opt_addr;
|
||||||
|
dark::Register<32> cur_opt_data;
|
||||||
|
dark::Register<2> cur_opt_type;
|
||||||
|
dark::Register<2> cur_opt_bytes;
|
||||||
|
};
|
||||||
|
struct Memory : dark::Module<Memory_Input, Memory_Output, Memory_Private> {
|
||||||
|
private:
|
||||||
|
std::vector<uint8_t> memory_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Memory() { memory_data.resize(1 << 20, 0); }
|
||||||
|
void work() override final {
|
||||||
|
if (bool(reset)) {
|
||||||
|
// do some initialization
|
||||||
|
status <= 0;
|
||||||
|
ready <= 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(bool(force_clear_signal)) {
|
||||||
|
status <= 0;
|
||||||
|
ready <= 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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 opt_bytes = (request_type_signal >> 2) & 3; // 0->1, 1->2, 2->4
|
||||||
|
if (rw_type == 3) throw std::runtime_error("Invalid request type");
|
||||||
|
uint32_t current_status = max_size_t(status);
|
||||||
|
if (current_status > 0) {
|
||||||
|
// in working status
|
||||||
|
if (request_type_signal > 0) throw std::runtime_error("Memory is busy");
|
||||||
|
if (current_status == 1) {
|
||||||
|
status <= 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
status <= 0;
|
||||||
|
ready <= 1;
|
||||||
|
if(max_size_t(cur_opt_type) == 0b01) {
|
||||||
|
size_t len=1<<max_size_t(cur_opt_bytes);
|
||||||
|
switch(len) {
|
||||||
|
case 1:
|
||||||
|
data_output <= memory_data[max_size_t(cur_opt_addr)];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
data_output <= *reinterpret_cast<uint16_t*>(&memory_data[max_size_t(cur_opt_addr)]);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
data_output <= *reinterpret_cast<uint32_t*>(&memory_data[max_size_t(cur_opt_addr)]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("Invalid bytes");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size_t len=1<<max_size_t(cur_opt_bytes);
|
||||||
|
switch(len) {
|
||||||
|
case 1:
|
||||||
|
memory_data[max_size_t(cur_opt_addr)] = max_size_t(cur_opt_data)&0xff;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
*reinterpret_cast<uint16_t*>(&memory_data[max_size_t(cur_opt_addr)]) = max_size_t(cur_opt_data)&0xffff;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
*reinterpret_cast<uint32_t*>(&memory_data[max_size_t(cur_opt_addr)]) = max_size_t(cur_opt_data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("Invalid bytes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// now the memory is not busy
|
||||||
|
if (request_type_signal == 0) return;
|
||||||
|
status <= 1;
|
||||||
|
ready <= 0;
|
||||||
|
cur_opt_addr <= address_input;
|
||||||
|
cur_opt_data <= data_input;
|
||||||
|
cur_opt_type <= rw_type;
|
||||||
|
cur_opt_bytes <= opt_bytes;
|
||||||
|
}
|
||||||
|
max_size_t FetchInstruction(max_size_t addr) { // assume we have a super nb instruction fetch method that can fetch
|
||||||
|
// an instruction immediately
|
||||||
|
max_size_t res;
|
||||||
|
res = *reinterpret_cast<max_size_t *>(&memory_data[addr]);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
void LoadProgram(std::istream &fin) {
|
||||||
|
fin >> std::hex;
|
||||||
|
std::string rubbish_bin;
|
||||||
|
do {
|
||||||
|
while (!fin.eof() && fin.get() != '@')
|
||||||
|
;
|
||||||
|
if (fin.eof()) break;
|
||||||
|
int addr, tmp;
|
||||||
|
std::vector<uint8_t> buf;
|
||||||
|
fin >> addr;
|
||||||
|
DEBUG_CERR << "begin:" << std::hex << addr << std::endl;
|
||||||
|
while (fin >> tmp) {
|
||||||
|
buf.push_back(tmp);
|
||||||
|
}
|
||||||
|
if (memory_data.size() < addr + buf.size()) {
|
||||||
|
memory_data.resize(addr + buf.size());
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
fin.clear();
|
||||||
|
} while (!fin.eof());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace ZYM
|
||||||
|
#endif // MEMORY_H
|
4
include/registerfile.h
Normal file
4
include/registerfile.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef REGISTERFILE_H
|
||||||
|
#include "tools.h"
|
||||||
|
#endif
|
0
include/reservestation.h
Normal file
0
include/reservestation.h
Normal file
@ -7,6 +7,8 @@
|
|||||||
#include "wire.h"
|
#include "wire.h"
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "bus.h"
|
||||||
|
|
||||||
using dark::Bit;
|
using dark::Bit;
|
||||||
using dark::sign_extend;
|
using dark::sign_extend;
|
||||||
|
10
src/main.cpp
Normal file
10
src/main.cpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include "tools.h"
|
||||||
|
#include "csu.h"
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
dark::CPU cpu;
|
||||||
|
ZYM::Memory memory;
|
||||||
|
cpu.add_module(&memory);
|
||||||
|
memory.reset = [&]() { return cpu.GetResetSignal(); };
|
||||||
|
memory.LoadProgram(std::cin);
|
||||||
|
return 0;
|
||||||
|
}
|
Reference in New Issue
Block a user