Initial commit for 5-stage RISC-V without forwarding
MODIFY
external/VSRTL
external/VSRTL
-Subproject commit 7007e89f4a63d39963ab6a6112ad0dd8b46b8cf9
+Subproject commit a163f2c1e75e6cb31c3e20e72d908dd41deb6679

MODIFY
src/processorhandler.h
src/processorhandler.h
@@ -142,7 +142,7 @@ private slots:
private:
ProcessorHandler();
- ProcessorID m_currentID = ProcessorID::RISCV_SS;
+ ProcessorID m_currentID = ProcessorID::RISCV_5S_WOF;
std::unique_ptr<vsrtl::core::RipesProcessor> m_currentProcessor;
/**

MODIFY
src/processorregistry.h
src/processorregistry.h
#include "isainfo.h"
#include "processors/ripesprocessor.h"
+#include "processors/5s/riscv_5s.h"
#include "processors/ss/riscv_ss.h"
namespace Ripes {
@@ -38,7 +39,9 @@ public:
static const ProcessorDescription& getDescription(ProcessorID id) { return instance().m_descriptions[id]; }
static std::unique_ptr<vsrtl::core::RipesProcessor> constructProcessor(ProcessorID id) {
switch (id) {
- case ProcessorID::RISCV_5S_WOF:
+ case ProcessorID::RISCV_5S_WOF: {
+ return std::make_unique<vsrtl::core::FiveStageRISCV>();
+ }
case ProcessorID::RISCV_5S_WF:
case ProcessorID::RISCV_SS: {
return std::make_unique<vsrtl::core::SingleCycleRISCV>();
@@ -62,6 +65,7 @@ private:
m_descriptions[desc.id] = desc;
// RISC-V 5-Stage with forwarding
+ desc = ProcessorDescription();
desc.id = ProcessorID::RISCV_5S_WF;
desc.isa = ISAInfo<ISA::RV32IM>::instance();
desc.name = "RISC-V 5-Stage w/ forwarding";
@@ -71,13 +75,14 @@ private:
m_descriptions[desc.id] = desc;
// RISC-V 5-stage without forwarding
+ desc = ProcessorDescription();
desc.id = ProcessorID::RISCV_5S_WOF;
desc.isa = ISAInfo<ISA::RV32IM>::instance();
desc.name = "RISC-V 5-Stage wo/ forwarding";
desc.description =
"A 5-Stage in-order RISC-V processor with no hazard detection and forwarding. \n\nThe user is expected to "
"resolve all data hazard through insertions of NOP instructions to correctly schedule the code.";
- desc.layouts.push_back({"Standard", ":/layouts/ss/rv_ss_layout.json", false});
+ desc.layouts.push_back({});
desc.defaultRegisterVals = {{2, 0x7ffffff0}, {3, 0x10000000}};
m_descriptions[desc.id] = desc;
}

ADD
src/processors/5s/5s_ifid.h
+#pragma once
+
+#include "VSRTL/core/vsrtl_component.h"
+#include "VSRTL/core/vsrtl_register.h"
+
+#include "../ss/riscv.h"
+
+namespace vsrtl {
+namespace core {
+using namespace Ripes;
+
+class IFID : public Component {
+public:
+ IFID(std::string name, SimComponent* parent) : Component(name, parent) {
+ CONNECT_REGISTERED_CLEN_INPUT(pc4, clear, enable);
+ CONNECT_REGISTERED_CLEN_INPUT(pc, clear, enable);
+ CONNECT_REGISTERED_CLEN_INPUT(instr, clear, enable);
+ }
+
+ REGISTERED_CLEN_INPUT(pc4, RV_REG_WIDTH);
+ REGISTERED_CLEN_INPUT(instr, RV_REG_WIDTH);
+ REGISTERED_CLEN_INPUT(pc, RV_REG_WIDTH);
+
+ // Register controls
+ INPUTPORT(enable, 1);
+ INPUTPORT(clear, 1);
+};
+
+} // namespace core
+} // namespace vsrtl

ADD
src/processors/5s/riscv_5s.h
+#pragma once
+
+#include "VSRTL/core/vsrtl_adder.h"
+#include "VSRTL/core/vsrtl_constant.h"
+#include "VSRTL/core/vsrtl_design.h"
+#include "VSRTL/core/vsrtl_logicgate.h"
+#include "VSRTL/core/vsrtl_multiplexer.h"
+
+#include "../ripesprocessor.h"
+
+#include "../ss/alu.h"
+#include "../ss/branch.h"
+#include "../ss/control.h"
+#include "../ss/decode.h"
+#include "../ss/ecallchecker.h"
+#include "../ss/immediate.h"
+#include "../ss/registerfile.h"
+#include "../ss/riscv.h"
+#include "../ss/rvmemory.h"
+
+#include "5s_ifid.h"
+
+namespace vsrtl {
+namespace core {
+using namespace Ripes;
+
+class FiveStageRISCV : public RipesProcessor {
+public:
+ FiveStageRISCV() : RipesProcessor("5-Stage RISC-V Processor") {
+ // -----------------------------------------------------------------------
+ // Program counter
+ pc_reg->out >> pc_4->op1;
+ 4 >> pc_4->op2;
+ pc_src->out >> pc_reg->in;
+
+ // Note: pc_src works uses the PcSrc enum, but is selected by the boolean signal
+ // from the controlflow OR gate. PcSrc enum values must adhere to the boolean
+ // 0/1 values.
+ controlflow_or->out >> pc_src->select;
+
+ // -----------------------------------------------------------------------
+ // Instruction memory
+ pc_reg->out >> instr_mem->addr;
+ instr_mem->setMemory(m_memory);
+
+ // -----------------------------------------------------------------------
+ // Decode
+ instr_mem->data_out >> decode->instr;
+
+ // -----------------------------------------------------------------------
+ // Control signals
+ decode->opcode >> control->opcode;
+
+ // -----------------------------------------------------------------------
+ // Immediate
+ decode->opcode >> immediate->opcode;
+ instr_mem->data_out >> immediate->instr;
+
+ // -----------------------------------------------------------------------
+ // Registers
+ decode->wr_reg_idx >> registerFile->wr_addr;
+ decode->r1_reg_idx >> registerFile->r1_addr;
+ decode->r2_reg_idx >> registerFile->r2_addr;
+ control->reg_do_write_ctrl >> registerFile->wr_en;
+ reg_wr_src->out >> registerFile->data_in;
+
+ data_mem->data_out >> reg_wr_src->get(RegWrSrc::MEMREAD);
+ alu->res >> reg_wr_src->get(RegWrSrc::ALURES);
+ pc_4->out >> reg_wr_src->get(RegWrSrc::PC4);
+ control->reg_wr_src_ctrl >> reg_wr_src->select;
+
+ registerFile->setMemory(m_regMem);
+
+ // -----------------------------------------------------------------------
+ // Branch
+ control->comp_ctrl >> branch->comp_op;
+ registerFile->r1_out >> branch->op1;
+ registerFile->r2_out >> branch->op2;
+
+ branch->res >> *br_and->in[0];
+ control->do_branch >> *br_and->in[1];
+ br_and->out >> *controlflow_or->in[0];
+ control->do_jump >> *controlflow_or->in[1];
+ pc_4->out >> pc_src->get(PcSrc::PC4);
+ alu->res >> pc_src->get(PcSrc::ALU);
+
+ // -----------------------------------------------------------------------
+ // ALU
+ registerFile->r1_out >> alu_op1_src->get(AluSrc1::REG1);
+ pc_reg->out >> alu_op1_src->get(AluSrc1::PC);
+ control->alu_op1_ctrl >> alu_op1_src->select;
+
+ registerFile->r2_out >> alu_op2_src->get(AluSrc2::REG2);
+ immediate->imm >> alu_op2_src->get(AluSrc2::IMM);
+ control->alu_op2_ctrl >> alu_op2_src->select;
+
+ alu_op1_src->out >> alu->op1;
+ alu_op2_src->out >> alu->op2;
+
+ control->alu_ctrl >> alu->ctrl;
+
+ // -----------------------------------------------------------------------
+ // Data memory
+ alu->res >> data_mem->addr;
+ control->mem_do_write_ctrl >> data_mem->wr_en;
+ registerFile->r2_out >> data_mem->data_in;
+ control->mem_ctrl >> data_mem->op;
+ data_mem->mem->setMemory(m_memory);
+
+ // -----------------------------------------------------------------------
+ // Ecall checker
+ decode->opcode >> ecallChecker->opcode;
+ ecallChecker->setSysCallSignal(&handleSysCall);
+
+ // -----------------------------------------------------------------------
+ // IF/ID
+ pc_4->out >> ifid_reg->pc4_in;
+ pc_reg->out >> ifid_reg->pc_in;
+ instr_mem->data_out >> ifid_reg->instr_in;
+ 1 >> ifid_reg->enable;
+ 0 >> ifid_reg->clear;
+ }
+
+ // Design subcomponents
+ SUBCOMPONENT(registerFile, RegisterFile);
+ SUBCOMPONENT(alu, ALU);
+ SUBCOMPONENT(control, Control);
+ SUBCOMPONENT(immediate, Immediate);
+ SUBCOMPONENT(decode, Decode);
+ SUBCOMPONENT(branch, Branch);
+ SUBCOMPONENT(pc_4, Adder<RV_REG_WIDTH>);
+
+ // Registers
+ SUBCOMPONENT(pc_reg, Register<RV_REG_WIDTH>);
+
+ // Stage seperating registers
+ SUBCOMPONENT(ifid_reg, IFID);
+
+ // Multiplexers
+ SUBCOMPONENT(reg_wr_src, TYPE(EnumMultiplexer<RegWrSrc, RV_REG_WIDTH>));
+ SUBCOMPONENT(pc_src, TYPE(EnumMultiplexer<PcSrc, RV_REG_WIDTH>));
+ SUBCOMPONENT(alu_op1_src, TYPE(EnumMultiplexer<AluSrc1, RV_REG_WIDTH>));
+ SUBCOMPONENT(alu_op2_src, TYPE(EnumMultiplexer<AluSrc2, RV_REG_WIDTH>));
+
+ // Memories
+ SUBCOMPONENT(instr_mem, TYPE(ROM<RV_REG_WIDTH, RV_INSTR_WIDTH>));
+ SUBCOMPONENT(data_mem, TYPE(RVMemory<RV_REG_WIDTH, RV_REG_WIDTH>));
+
+ // Gates
+ SUBCOMPONENT(br_and, TYPE(And<1, 2>));
+ SUBCOMPONENT(controlflow_or, TYPE(Or<1, 2>));
+
+ // Address spaces
+ ADDRESSSPACE(m_memory);
+ ADDRESSSPACE(m_regMem);
+
+ SUBCOMPONENT(ecallChecker, EcallChecker);
+
+ // Ripes interface compliance
+ virtual const ISAInfoBase* implementsISA() const override { return ISAInfo<ISA::RV32IM>::instance(); }
+ unsigned int stageCount() const override { return 2; }
+ unsigned int getPcForStage(unsigned int idx) const override {
+ switch (idx) {
+ case 0:
+ return pc_reg->out.uValue();
+ case 1:
+ return ifid_reg->pc_out.uValue();
+ default:
+ return 0;
+ }
+ }
+ unsigned int nextFetchedAddress() const override { return pc_src->out.uValue(); }
+ QString stageName(unsigned int idx) const override {
+ switch (idx) {
+ case 0:
+ return "IF";
+ case 1:
+ return "ID";
+ default:
+ return "N/A";
+ }
+ }
+ StageInfo stageInfo(unsigned int idx) const override { return StageInfo({getPcForStage(idx), true}); }
+ void setProgramCounter(uint32_t address) override {
+ pc_reg->forceValue(0, address);
+ propagateDesign();
+ }
+ void setPCInitialValue(uint32_t address) override { pc_reg->setInitValue(address); }
+ SparseArray& getMemory() override { return *m_memory; }
+ unsigned int getRegister(unsigned i) const override { return registerFile->getRegister(i); }
+ SparseArray& getRegisters() override { return *m_regMem; }
+ void finalize() override {
+ // Allow one additional clock cycle to clear the current instruction
+ m_finishInNextCycle = true;
+ }
+ bool finished() const override { return m_finished; }
+
+ void setRegister(unsigned i, uint32_t v) override { setSynchronousValue(registerFile->_wr_mem, i, v); }
+
+ void clock() override {
+ // Single cycle processor; 1 instruction retired per cycle!
+ m_instructionsRetired++;
+
+ // m_finishInNextCycle may be set during Design::clock(). Store the value before clocking the processor, and
+ // emit finished if this was the final clock cycle.
+ const bool finishInThisCycle = m_finishInNextCycle;
+ RipesProcessor::clock();
+ if (finishInThisCycle) {
+ m_finished = true;
+ }
+ }
+
+ void reverse() override {
+ m_instructionsRetired--;
+ RipesProcessor::reverse();
+ // Ensure that reverses performed when we expected to finish in the following cycle, clears this
+ // expectation.
+ m_finishInNextCycle = false;
+ m_finished = false;
+ }
+
+ void reset() override {
+ RipesProcessor::reset();
+ m_finishInNextCycle = false;
+ m_finished = false;
+ }
+
+private:
+ bool m_finishInNextCycle = false;
+ bool m_finished = false;
+};
+
+} // namespace core
+} // namespace vsrtl

MODIFY
src/processors/CMakeLists.txt
src/processors/CMakeLists.txt
@@ -13,3 +13,4 @@ macro(create_processor name)
endmacro()
create_processor(ss)
+create_processor(5s)

Initial commit for 5-stage RISC-V without forwarding