From 1acccc74b1036d9d3847fdcc60c392125a03be85 Mon Sep 17 00:00:00 2001 From: Aditya Naik Date: Sat, 8 May 2021 12:51:18 -0400 Subject: Initial Added work on RV64 I core to date, including tb --- .gitignore | 2 + core/alu.v | 29 ++++++ core/aluctrl.v | 114 +++++++++++++++++++++++ core/ctrl.v | 201 +++++++++++++++++++++++++++++++++++++++++ core/obj_dir/Vtb.cpp | 99 ++++++++++++++++++++ core/obj_dir/Vtb.d | 3 + core/obj_dir/Vtb.h | 88 ++++++++++++++++++ core/obj_dir/Vtb.mk | 66 ++++++++++++++ core/obj_dir/Vtb__ALL.cpp | 5 + core/obj_dir/Vtb__ALL.d | 5 + core/obj_dir/Vtb__Slow.cpp | 117 ++++++++++++++++++++++++ core/obj_dir/Vtb__Syms.cpp | 21 +++++ core/obj_dir/Vtb__Syms.h | 35 +++++++ core/obj_dir/Vtb__ver.d | 1 + core/obj_dir/Vtb__verFiles.dat | 14 +++ core/obj_dir/Vtb_classes.mk | 49 ++++++++++ core/obj_dir/verilated.d | 8 ++ core/regs.v | 42 +++++++++ core/tb.v | 54 +++++++++++ 19 files changed, 953 insertions(+) create mode 100644 .gitignore create mode 100644 core/alu.v create mode 100644 core/aluctrl.v create mode 100644 core/ctrl.v create mode 100644 core/obj_dir/Vtb.cpp create mode 100644 core/obj_dir/Vtb.d create mode 100644 core/obj_dir/Vtb.h create mode 100644 core/obj_dir/Vtb.mk create mode 100644 core/obj_dir/Vtb__ALL.cpp create mode 100644 core/obj_dir/Vtb__ALL.d create mode 100644 core/obj_dir/Vtb__Slow.cpp create mode 100644 core/obj_dir/Vtb__Syms.cpp create mode 100644 core/obj_dir/Vtb__Syms.h create mode 100644 core/obj_dir/Vtb__ver.d create mode 100644 core/obj_dir/Vtb__verFiles.dat create mode 100644 core/obj_dir/Vtb_classes.mk create mode 100644 core/obj_dir/verilated.d create mode 100644 core/regs.v create mode 100644 core/tb.v diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..151a620 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +*.a \ No newline at end of file diff --git a/core/alu.v b/core/alu.v new file mode 100644 index 0000000..439df08 --- /dev/null +++ b/core/alu.v @@ -0,0 +1,29 @@ +module alu( + input wire [3:0] op, + input wire [63:0] in_x, + input wire [63:0] in_y, + output reg [63:0] out + ); + + always @* begin + case (op) + 4'b0000: out = in_x & in_y; // and + 4'b0001: out = in_x | in_y; // or + 4'b0010: out = in_x + in_y; // add + 4'b0011: out = in_x - in_y; // sub + 4'b0100: out = $signed(in_x) >>> $signed(in_y); // sra signed + 4'b0101: out = in_x < in_y; // stlu + 4'b0110: out = in_x ^ in_y; // xor + 4'b0111: out = in_x >> in_y; // srl + 4'b1000: out = $signed(in_x) < $signed(in_y); // slt signed + 4'b1001: out = in_x << in_y; // sll + 4'b1010: out = ~(in_x | in_y); // nor + 4'b1011: out = $signed(in_x) >= $signed(in_y); // sge + 4'b1100: out = in_x >= in_y; // sgeu + 4'b1101: out = in_x == in_y; // seq + 4'b1110: out = in_x != in_y; // sne + 4'b1111: out = 0; // invalid + endcase + end // always @ * + +endmodule // alu diff --git a/core/aluctrl.v b/core/aluctrl.v new file mode 100644 index 0000000..f078870 --- /dev/null +++ b/core/aluctrl.v @@ -0,0 +1,114 @@ +/** + This file contains ALU control logic. + + * The ALU control unit + * + * Input: aluop 00 for ld/st, 10 for R-type, 01 for branch + * Input: funct7 The most significant bits of the instruction + * Input: funct3 The middle three bits of the instruction (12-14) + * Output: operation What we want the ALU to do. + **/ + +module aluctrl( + input wire [1:0] aluop, + input wire itype, + input wire [6:0] funct7, + input wire [2:0] funct3, + output reg [3:0] operation + ); + + always @* begin + case (aluop) + 2'b00: + operation = 4'b0010; + 2'b10: begin + case (funct3) + 3'b000: begin + if (itype == 1'b1 || funct7 == 7'b0000000) + operation = 4'b0010; // add + else + operation = 4'b0011; //sub + end + 3'b001: operation = 4'b1001; // sll + 3'b010: operation = 4'b1000; // slt + 3'b011: operation = 4'b0101; // sltu + 3'b100: operation = 4'b0110; // xor + 3'b101: begin + if (funct7 == 7'b0000000) + assign operation = 4'b0111; // srl + else + assign operation = 4'b0100; // sra + end + 4'b110: operation = 4'b0001; // or + 4'b111: operation = 4'b0000; + endcase // case (funct3) + end // case: 2'b10 + 2'b01: begin + case (funct3) + 3'b000: operation = 4'b1101; // beq + 3'b001: operation = 4'b1110; // bne + 3'b100: operation = 4'b1000; // blt + 3'b101: operation = 4'b1011; // bge + 3'b110: operation = 4'b0101; // bltu + 3'b111: operation = 4'b1100; // bgeu + default: operation = 4'b1111; // invalid + endcase // case (funct3) + end // case: 2'b01 + default: operation = 4'b1111; // invalid + endcase // case (aluop) + end // always @ * + + // Direct translation from dino + // if (aluop == 2'b00) begin // ld/st + // assign operation = 4'b0010; + // end + // else if (aluop == 2'b10) begin + // if (funct3 == 3'b000) begin // R-type + // if (itype == 1'b1 || funct7 == 7'b0000000) + // assign operation = 4'b0010; // add + // else + // assign operation = 4'b0011; //sub + // end + // else if (funct3 == 3'b001) + // assign operation = 4'b1001; // sll + // else if (funct3 == 3'b010) + // assign operation = 4'b1000; // slt + // else if (funct3 == 3'b011) + // assign operation = 4'b0101; // sltu + // else if (funct3 == 3'b100) + // assign operation = 4'b0110; // xor + + // else if (funct3 == 3'b101) begin + // if (func7 == 7'b0000000) + // assign operation = 4'b0111; // srl + // else + // assign operation = 4'b0100; // sra + // end + // else if (funct3 == 4'b110) + // assign operation = 4'b0001; // or + // else + // assign operation = 4'b000; + // end + // else if (aluop == 2'b01) begin // branches + // if (funct3 == 3'b000) + // assign operation = 4'b1101; // beq + // else if (funct3 == 3'b001) + // assign operation = 4'b1110; // bne + // else if (funct3 == 3'b100) + // assign operation = 4'b1000; // blt + // else if (funct3 == 3'b101) + // assign operation = 4'b1011; // bge + // else if (funct3 == 3'b110) + // assign operation = 4'b0101; // bltu + // else if (funct3 == 3'b111) + // assign operation = 4'b1100; // bgeu + // else + // assign operation = 4'b1111; // invalid + // end + // else + // assign operation = 4'b1111; // invalid + // end // always @ * + +endmodule // aluctrl + + diff --git a/core/ctrl.v b/core/ctrl.v new file mode 100644 index 0000000..3fbee1f --- /dev/null +++ b/core/ctrl.v @@ -0,0 +1,201 @@ + +/** + * Main control logic for our simple processor. + * + * Input: opcode: Opcode from instruction + * + * Output: validinst True if the instruction we're decoding is valid + * Output: _branch true if branch or (jal. update PC with immediate + * Output: _jump True if we want update the PC with pc+imm regardless of the ALU result + * Output: _imm True if we're working on an itype instruction + * Output: pc_from_alu Use the pc from the ALU, not pc+4 or pc+imm + * Output: mem_read true if we should read from memory + * Output: mem_write true if writing to the data memory + * Output: reg_write true if writing to the register file + * Output: to_reg 0 for result from execute, 1 for data from memory + * Output: result_select 00 for result from alu, 01 for immediate, 10 for pc+4 + * Output: alu_src source for the second ALU input (0 is readdata2 and 1 is immediate) + * Output: pc_add Use PC as the input to the ALU + * Output: alu_op 00 for ld/st, 10 for R-type, 01 for branch + **/ + +module op( + input wire [6:0] opcode, + + output reg valid_instr, + output reg _branch, + output reg _jump, + output reg _imm, + output reg pc_from_alu, + output reg mem_read, + output reg mem_write, + output reg reg_write, + output reg to_reg, + output reg [1:0] result_select, + output reg alu_src, + output reg pc_add, + output reg [1:0] alu_op + ); + + // opcodes for all types and formats + assign rtype = 7'b0110011; + assign itype = 7'b0010011; + assign btype = 7'b1100011; + + assign load = 7'b0000011; + assign store = 7'b0100011; + assign lui = 7'b0110111; + assign auipc = 7'b0010111; + assign jal = 7'b1101111; + assign jalr = 7'b1100111; + + always @* begin + case (opcode) + rtype: begin + assign valid_instr = 1; + assign reg_write = 1; + assign alu_op = 2; + + assign _branch = 0; + assign _jump = 0; + assign _imm = 0; + assign pc_from_alu = 0; + assign mem_read = 0; + assign mem_write = 0; + assign to_reg = 0; + assign result_select = 0; + assign alu_src = 0; + assign pc_add = 0; + end + itype: begin + assign valid_instr = 1; + assign reg_write = 1; + assign alu_op = 2; + assign alu_src = 1; + assign _imm = 1; + + assign _branch = 0; + assign _jump = 0; + assign pc_from_alu = 0; + assign mem_read = 0; + assign mem_write = 0; + assign to_reg = 0; + assign result_select = 0; + assign pc_add = 0; + end + load: begin + assign valid_instr = 1; + assign mem_read = 1; + assign reg_write = 1; + assign to_reg = 1; + assign alu_src = 1; + + assign _branch = 0; + assign _jump = 0; + assign _imm = 0; + assign pc_from_alu = 0; + assign mem_write = 0; + assign to_reg = 0; + assign result_select = 0; + assign pc_add = 0; + assign alu_op = 0; + end + store: begin + assign valid_instr = 1; + assign mem_write = 1; + assign alu_src = 1; + + assign _branch = 0; + assign _jump = 0; + assign _imm = 0; + assign pc_from_alu = 0; + assign mem_read = 0; + assign to_reg = 0; + assign result_select = 0; + assign pc_add = 0; + assign alu_op = 0; + end + btype: begin + assign valid_instr = 1; + assign _branch = 1; + assign alu_op = 1; + + assign _jump = 0; + assign _imm = 0; + assign pc_from_alu = 0; + assign mem_read = 0; + assign mem_write = 0; + assign reg_write = 0; + assign to_reg = 0; + assign result_select = 0; + assign alu_src = 0; + assign pc_add = 0; + end + lui: begin + assign valid_instr = 1; + assign reg_write = 1; + assign result_select = 1; + + assign _branch = 0; + assign _jump = 0; + assign _imm = 0; + assign pc_from_alu = 0; + assign mem_read = 0; + assign mem_write = 0; + assign to_reg = 0; + assign alu_src = 0; + assign pc_add = 0; + assign alu_op = 0; + end + auipc: begin + assign valid_instr = 1; + assign reg_write = 1; + assign alu_src = 1; + assign pc_add = 1; + + assign _branch = 0; + assign _jump = 0; + assign _imm = 0; + assign pc_from_alu = 0; + assign mem_read = 0; + assign mem_write = 0; + assign to_reg = 0; + assign result_select = 0; + assign alu_op = 0; + end + jal: begin + assign valid_instr = 1; + assign _jump = 1; + assign reg_write = 1; + assign result_select = 2; + + assign _branch = 0; + assign _imm = 0; + assign pc_from_alu = 0; + assign mem_read = 0; + assign mem_write = 0; + assign to_reg = 0; + assign alu_src = 0; + assign pc_add = 0; + assign alu_op = 0; + end + jalr: begin + assign valid_instr = 1; + assign pc_from_alu = 1; + assign _jump = 1; + assign reg_write = 1; + assign result_select = 2; + assign alu_src = 1; + + assign _branch = 0; + assign _imm = 0; + assign mem_read = 0; + assign mem_write = 0; + assign to_reg = 0; + assign pc_add = 0; + assign alu_op = 0; + end + endcase + end // always + +endmodule // op diff --git a/core/obj_dir/Vtb.cpp b/core/obj_dir/Vtb.cpp new file mode 100644 index 0000000..f84c787 --- /dev/null +++ b/core/obj_dir/Vtb.cpp @@ -0,0 +1,99 @@ +// Verilated -*- C++ -*- +// DESCRIPTION: Verilator output: Design implementation internals +// See Vtb.h for the primary calling header + +#include "Vtb.h" +#include "Vtb__Syms.h" + +//========== + +void Vtb::eval_step() { + VL_DEBUG_IF(VL_DBG_MSGF("+++++TOP Evaluate Vtb::eval\n"); ); + Vtb__Syms* __restrict vlSymsp = this->__VlSymsp; // Setup global symbol table + Vtb* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp; +#ifdef VL_DEBUG + // Debug assertions + _eval_debug_assertions(); +#endif // VL_DEBUG + // Initialize + if (VL_UNLIKELY(!vlSymsp->__Vm_didInit)) _eval_initial_loop(vlSymsp); + // Evaluate till stable + int __VclockLoop = 0; + QData __Vchange = 1; + do { + VL_DEBUG_IF(VL_DBG_MSGF("+ Clock loop\n");); + _eval(vlSymsp); + if (VL_UNLIKELY(++__VclockLoop > 100)) { + // About to fail, so enable debug to see what's not settling. + // Note you must run make with OPT=-DVL_DEBUG for debug prints. + int __Vsaved_debug = Verilated::debug(); + Verilated::debug(1); + __Vchange = _change_request(vlSymsp); + Verilated::debug(__Vsaved_debug); + VL_FATAL_MT("tb.v", 6, "", + "Verilated model didn't converge\n" + "- See DIDNOTCONVERGE in the Verilator manual"); + } else { + __Vchange = _change_request(vlSymsp); + } + } while (VL_UNLIKELY(__Vchange)); +} + +void Vtb::_eval_initial_loop(Vtb__Syms* __restrict vlSymsp) { + vlSymsp->__Vm_didInit = true; + _eval_initial(vlSymsp); + // Evaluate till stable + int __VclockLoop = 0; + QData __Vchange = 1; + do { + _eval_settle(vlSymsp); + _eval(vlSymsp); + if (VL_UNLIKELY(++__VclockLoop > 100)) { + // About to fail, so enable debug to see what's not settling. + // Note you must run make with OPT=-DVL_DEBUG for debug prints. + int __Vsaved_debug = Verilated::debug(); + Verilated::debug(1); + __Vchange = _change_request(vlSymsp); + Verilated::debug(__Vsaved_debug); + VL_FATAL_MT("tb.v", 6, "", + "Verilated model didn't DC converge\n" + "- See DIDNOTCONVERGE in the Verilator manual"); + } else { + __Vchange = _change_request(vlSymsp); + } + } while (VL_UNLIKELY(__Vchange)); +} + +void Vtb::_eval(Vtb__Syms* __restrict vlSymsp) { + VL_DEBUG_IF(VL_DBG_MSGF("+ Vtb::_eval\n"); ); + Vtb* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp; +} + +VL_INLINE_OPT QData Vtb::_change_request(Vtb__Syms* __restrict vlSymsp) { + VL_DEBUG_IF(VL_DBG_MSGF("+ Vtb::_change_request\n"); ); + Vtb* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp; + // Body + return (vlTOPp->_change_request_1(vlSymsp)); +} + +VL_INLINE_OPT QData Vtb::_change_request_1(Vtb__Syms* __restrict vlSymsp) { + VL_DEBUG_IF(VL_DBG_MSGF("+ Vtb::_change_request_1\n"); ); + Vtb* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp; + // Body + // Change detection + QData __req = false; // Logically a bool + __req |= ((vlTOPp->tb__DOT__val1 ^ vlTOPp->__Vchglast__TOP__tb__DOT__val1) + | (vlTOPp->tb__DOT__val2 ^ vlTOPp->__Vchglast__TOP__tb__DOT__val2)); + VL_DEBUG_IF( if(__req && ((vlTOPp->tb__DOT__val1 ^ vlTOPp->__Vchglast__TOP__tb__DOT__val1))) VL_DBG_MSGF(" CHANGE: tb.v:10: tb.val1\n"); ); + VL_DEBUG_IF( if(__req && ((vlTOPp->tb__DOT__val2 ^ vlTOPp->__Vchglast__TOP__tb__DOT__val2))) VL_DBG_MSGF(" CHANGE: tb.v:11: tb.val2\n"); ); + // Final + vlTOPp->__Vchglast__TOP__tb__DOT__val1 = vlTOPp->tb__DOT__val1; + vlTOPp->__Vchglast__TOP__tb__DOT__val2 = vlTOPp->tb__DOT__val2; + return __req; +} + +#ifdef VL_DEBUG +void Vtb::_eval_debug_assertions() { + VL_DEBUG_IF(VL_DBG_MSGF("+ Vtb::_eval_debug_assertions\n"); ); +} +#endif // VL_DEBUG diff --git a/core/obj_dir/Vtb.d b/core/obj_dir/Vtb.d new file mode 100644 index 0000000..65e0d9a --- /dev/null +++ b/core/obj_dir/Vtb.d @@ -0,0 +1,3 @@ +Vtb.o: Vtb.cpp Vtb.h /usr/share/verilator/include/verilated_heavy.h \ + /usr/share/verilator/include/verilated.h \ + /usr/share/verilator/include/verilatedos.h Vtb__Syms.h diff --git a/core/obj_dir/Vtb.h b/core/obj_dir/Vtb.h new file mode 100644 index 0000000..e1386e3 --- /dev/null +++ b/core/obj_dir/Vtb.h @@ -0,0 +1,88 @@ +// Verilated -*- C++ -*- +// DESCRIPTION: Verilator output: Primary design header +// +// This header should be included by all source files instantiating the design. +// The class here is then constructed to instantiate the design. +// See the Verilator manual for examples. + +#ifndef _VTB_H_ +#define _VTB_H_ // guard + +#include "verilated_heavy.h" + +//========== + +class Vtb__Syms; + +//---------- + +VL_MODULE(Vtb) { + public: + + // LOCAL SIGNALS + // Internals; generally not touched by application code + CData/*4:0*/ tb__DOT__read1; + CData/*4:0*/ tb__DOT__read2; + CData/*4:0*/ tb__DOT__write; + QData/*63:0*/ tb__DOT__val1; + QData/*63:0*/ tb__DOT__val2; + QData/*63:0*/ tb__DOT__write_data; + QData/*63:0*/ tb__DOT__r__DOT__reg_array[32]; + + // LOCAL VARIABLES + // Internals; generally not touched by application code + CData/*4:0*/ __Vtask_tb__DOT__r__DOT__write_reg__0__regid; + QData/*63:0*/ __Vtask_tb__DOT__r__DOT__write_reg__0__data; + QData/*63:0*/ __Vchglast__TOP__tb__DOT__val1; + QData/*63:0*/ __Vchglast__TOP__tb__DOT__val2; + + // INTERNAL VARIABLES + // Internals; generally not touched by application code + Vtb__Syms* __VlSymsp; // Symbol table + + // CONSTRUCTORS + private: + VL_UNCOPYABLE(Vtb); ///< Copying not allowed + public: + /// Construct the model; called by application code + /// The special name may be used to make a wrapper with a + /// single model invisible with respect to DPI scope names. + Vtb(const char* name = "TOP"); + /// Destroy the model; called (often implicitly) by application code + ~Vtb(); + + // API METHODS + /// Evaluate the model. Application must call when inputs change. + void eval() { eval_step(); } + /// Evaluate when calling multiple units/models per time step. + void eval_step(); + /// Evaluate at end of a timestep for tracing, when using eval_step(). + /// Application must call after all eval() and before time changes. + void eval_end_step() {} + /// Simulation complete, run final blocks. Application must call on completion. + void final(); + + // INTERNAL METHODS + static void _eval_initial_loop(Vtb__Syms* __restrict vlSymsp); + void __Vconfigure(Vtb__Syms* symsp, bool first); + private: + static QData _change_request(Vtb__Syms* __restrict vlSymsp); + static QData _change_request_1(Vtb__Syms* __restrict vlSymsp); + void _ctor_var_reset() VL_ATTR_COLD; + public: + static void _eval(Vtb__Syms* __restrict vlSymsp); + private: +#ifdef VL_DEBUG + void _eval_debug_assertions(); +#endif // VL_DEBUG + public: + static void _eval_initial(Vtb__Syms* __restrict vlSymsp) VL_ATTR_COLD; + static void _eval_settle(Vtb__Syms* __restrict vlSymsp) VL_ATTR_COLD; + static void _initial__TOP__1(Vtb__Syms* __restrict vlSymsp) VL_ATTR_COLD; + static void _settle__TOP__2(Vtb__Syms* __restrict vlSymsp) VL_ATTR_COLD; +} VL_ATTR_ALIGNED(VL_CACHE_LINE_BYTES); + +//---------- + + +#endif // guard diff --git a/core/obj_dir/Vtb.mk b/core/obj_dir/Vtb.mk new file mode 100644 index 0000000..39f8e31 --- /dev/null +++ b/core/obj_dir/Vtb.mk @@ -0,0 +1,66 @@ +# Verilated -*- Makefile -*- +# DESCRIPTION: Verilator output: Makefile for building Verilated archive or executable +# +# Execute this makefile from the object directory: +# make -f Vtb.mk + +default: Vtb + +### Constants... +# Perl executable (from $PERL) +PERL = perl +# Path to Verilator kit (from $VERILATOR_ROOT) +VERILATOR_ROOT = /usr/share/verilator +# SystemC include directory with systemc.h (from $SYSTEMC_INCLUDE) +SYSTEMC_INCLUDE ?= +# SystemC library directory with libsystemc.a (from $SYSTEMC_LIBDIR) +SYSTEMC_LIBDIR ?= + +### Switches... +# SystemC output mode? 0/1 (from --sc) +VM_SC = 0 +# Legacy or SystemC output mode? 0/1 (from --sc) +VM_SP_OR_SC = $(VM_SC) +# Deprecated +VM_PCLI = 1 +# Deprecated: SystemC architecture to find link library path (from $SYSTEMC_ARCH) +VM_SC_TARGET_ARCH = linux + +### Vars... +# Design prefix (from --prefix) +VM_PREFIX = Vtb +# Module prefix (from --prefix) +VM_MODPREFIX = Vtb +# User CFLAGS (from -CFLAGS on Verilator command line) +VM_USER_CFLAGS = \ + +# User LDLIBS (from -LDFLAGS on Verilator command line) +VM_USER_LDLIBS = \ + +# User .cpp files (from .cpp's on Verilator command line) +VM_USER_CLASSES = \ + Vtb \ + +# User .cpp directories (from .cpp's on Verilator command line) +VM_USER_DIR = \ + . \ + + +### Default rules... +# Include list of all generated classes +include Vtb_classes.mk +# Include global rules +include $(VERILATOR_ROOT)/include/verilated.mk + +### Executable rules... (from --exe) +VPATH += $(VM_USER_DIR) + +Vtb.o: Vtb.cpp + $(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $< + +### Link rules... (from --exe) +Vtb: $(VK_USER_OBJS) $(VK_GLOBAL_OBJS) $(VM_PREFIX)__ALL.a $(VM_HIER_LIBS) + $(LINK) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) $(LIBS) $(SC_LIBS) -o $@ + + +# Verilated -*- Makefile -*- diff --git a/core/obj_dir/Vtb__ALL.cpp b/core/obj_dir/Vtb__ALL.cpp new file mode 100644 index 0000000..aa3c816 --- /dev/null +++ b/core/obj_dir/Vtb__ALL.cpp @@ -0,0 +1,5 @@ +// DESCRIPTION: Generated by verilator_includer via makefile +#define VL_INCLUDE_OPT include +#include "Vtb.cpp" +#include "Vtb__Slow.cpp" +#include "Vtb__Syms.cpp" diff --git a/core/obj_dir/Vtb__ALL.d b/core/obj_dir/Vtb__ALL.d new file mode 100644 index 0000000..e790eff --- /dev/null +++ b/core/obj_dir/Vtb__ALL.d @@ -0,0 +1,5 @@ +Vtb__ALL.o: Vtb__ALL.cpp Vtb.cpp Vtb.h \ + /usr/share/verilator/include/verilated_heavy.h \ + /usr/share/verilator/include/verilated.h \ + /usr/share/verilator/include/verilatedos.h Vtb__Syms.h Vtb__Slow.cpp \ + Vtb__Syms.cpp diff --git a/core/obj_dir/Vtb__Slow.cpp b/core/obj_dir/Vtb__Slow.cpp new file mode 100644 index 0000000..2423d7b --- /dev/null +++ b/core/obj_dir/Vtb__Slow.cpp @@ -0,0 +1,117 @@ +// Verilated -*- C++ -*- +// DESCRIPTION: Verilator output: Design implementation internals +// See Vtb.h for the primary calling header + +#include "Vtb.h" +#include "Vtb__Syms.h" + +//========== + +VL_CTOR_IMP(Vtb) { + Vtb__Syms* __restrict vlSymsp = __VlSymsp = new Vtb__Syms(this, name()); + Vtb* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp; + // Reset internal values + + // Reset structure values + _ctor_var_reset(); +} + +void Vtb::__Vconfigure(Vtb__Syms* vlSymsp, bool first) { + if (false && first) {} // Prevent unused + this->__VlSymsp = vlSymsp; + if (false && this->__VlSymsp) {} // Prevent unused + Verilated::timeunit(-3); + Verilated::timeprecision(-3); +} + +Vtb::~Vtb() { + VL_DO_CLEAR(delete __VlSymsp, __VlSymsp = nullptr); +} + +void Vtb::_initial__TOP__1(Vtb__Syms* __restrict vlSymsp) { + VL_DEBUG_IF(VL_DBG_MSGF("+ Vtb::_initial__TOP__1\n"); ); + Vtb* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp; + // Body + VL_WRITEF("%10# %10#\n",32,(IData)(vlTOPp->tb__DOT__val1), + 32,(IData)(vlTOPp->tb__DOT__val2)); + vlTOPp->tb__DOT__write = 2U; + vlTOPp->tb__DOT__write_data = 0x14ULL; + vlTOPp->tb__DOT__read1 = 1U; + vlTOPp->tb__DOT__read2 = 2U; + VL_WRITEF("%10# %10#\n",32,(IData)(vlTOPp->tb__DOT__val1), + 32,(IData)(vlTOPp->tb__DOT__val2)); + VL_STOP_MT("tb.v", 48, ""); + vlTOPp->__Vtask_tb__DOT__r__DOT__write_reg__0__data = 0x14ULL; + vlTOPp->__Vtask_tb__DOT__r__DOT__write_reg__0__regid = 2U; + vlTOPp->tb__DOT__r__DOT__reg_array[2U] = 0x14ULL; +} + +void Vtb::_settle__TOP__2(Vtb__Syms* __restrict vlSymsp) { + VL_DEBUG_IF(VL_DBG_MSGF("+ Vtb::_settle__TOP__2\n"); ); + Vtb* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp; + // Variables + CData/*4:0*/ __Vfunc_tb__DOT__r__DOT__read_reg__1__regid; + CData/*4:0*/ __Vfunc_tb__DOT__r__DOT__read_reg__2__regid; + QData/*63:0*/ __Vfunc_tb__DOT__r__DOT__read_reg__1__Vfuncout; + QData/*63:0*/ __Vfunc_tb__DOT__r__DOT__read_reg__2__Vfuncout; + // Body + vlTOPp->__Vtask_tb__DOT__r__DOT__write_reg__0__data + = vlTOPp->tb__DOT__write_data; + vlTOPp->__Vtask_tb__DOT__r__DOT__write_reg__0__regid + = vlTOPp->tb__DOT__write; + vlTOPp->tb__DOT__r__DOT__reg_array[vlTOPp->__Vtask_tb__DOT__r__DOT__write_reg__0__regid] + = vlTOPp->__Vtask_tb__DOT__r__DOT__write_reg__0__data; + __Vfunc_tb__DOT__r__DOT__read_reg__1__regid = vlTOPp->tb__DOT__read1; + __Vfunc_tb__DOT__r__DOT__read_reg__1__Vfuncout + = vlTOPp->tb__DOT__r__DOT__reg_array[__Vfunc_tb__DOT__r__DOT__read_reg__1__regid]; + __Vfunc_tb__DOT__r__DOT__read_reg__2__regid = vlTOPp->tb__DOT__read2; + __Vfunc_tb__DOT__r__DOT__read_reg__2__Vfuncout + = vlTOPp->tb__DOT__r__DOT__reg_array[__Vfunc_tb__DOT__r__DOT__read_reg__2__regid]; + __Vfunc_tb__DOT__r__DOT__read_reg__1__regid = vlTOPp->tb__DOT__read1; + __Vfunc_tb__DOT__r__DOT__read_reg__1__Vfuncout + = vlTOPp->tb__DOT__r__DOT__reg_array[__Vfunc_tb__DOT__r__DOT__read_reg__1__regid]; + vlTOPp->tb__DOT__val1 = __Vfunc_tb__DOT__r__DOT__read_reg__1__Vfuncout; + __Vfunc_tb__DOT__r__DOT__read_reg__2__regid = vlTOPp->tb__DOT__read2; + __Vfunc_tb__DOT__r__DOT__read_reg__2__Vfuncout + = vlTOPp->tb__DOT__r__DOT__reg_array[__Vfunc_tb__DOT__r__DOT__read_reg__2__regid]; + vlTOPp->tb__DOT__val2 = __Vfunc_tb__DOT__r__DOT__read_reg__2__Vfuncout; +} + +void Vtb::_eval_initial(Vtb__Syms* __restrict vlSymsp) { + VL_DEBUG_IF(VL_DBG_MSGF("+ Vtb::_eval_initial\n"); ); + Vtb* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp; + // Body + vlTOPp->_initial__TOP__1(vlSymsp); +} + +void Vtb::final() { + VL_DEBUG_IF(VL_DBG_MSGF("+ Vtb::final\n"); ); + // Variables + Vtb__Syms* __restrict vlSymsp = this->__VlSymsp; + Vtb* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp; +} + +void Vtb::_eval_settle(Vtb__Syms* __restrict vlSymsp) { + VL_DEBUG_IF(VL_DBG_MSGF("+ Vtb::_eval_settle\n"); ); + Vtb* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp; + // Body + vlTOPp->_settle__TOP__2(vlSymsp); +} + +void Vtb::_ctor_var_reset() { + VL_DEBUG_IF(VL_DBG_MSGF("+ Vtb::_ctor_var_reset\n"); ); + // Body + tb__DOT__read1 = VL_RAND_RESET_I(5); + tb__DOT__read2 = VL_RAND_RESET_I(5); + tb__DOT__val1 = VL_RAND_RESET_Q(64); + tb__DOT__val2 = VL_RAND_RESET_Q(64); + tb__DOT__write = VL_RAND_RESET_I(5); + tb__DOT__write_data = VL_RAND_RESET_Q(64); + for (int __Vi0=0; __Vi0<32; ++__Vi0) { + tb__DOT__r__DOT__reg_array[__Vi0] = VL_RAND_RESET_Q(64); + } + __Vtask_tb__DOT__r__DOT__write_reg__0__regid = VL_RAND_RESET_I(5); + __Vtask_tb__DOT__r__DOT__write_reg__0__data = VL_RAND_RESET_Q(64); + __Vchglast__TOP__tb__DOT__val1 = VL_RAND_RESET_Q(64); + __Vchglast__TOP__tb__DOT__val2 = VL_RAND_RESET_Q(64); +} diff --git a/core/obj_dir/Vtb__Syms.cpp b/core/obj_dir/Vtb__Syms.cpp new file mode 100644 index 0000000..5f8019a --- /dev/null +++ b/core/obj_dir/Vtb__Syms.cpp @@ -0,0 +1,21 @@ +// Verilated -*- C++ -*- +// DESCRIPTION: Verilator output: Symbol table implementation internals + +#include "Vtb__Syms.h" +#include "Vtb.h" + + + +// FUNCTIONS +Vtb__Syms::Vtb__Syms(Vtb* topp, const char* namep) + // Setup locals + : __Vm_namep(namep) + , __Vm_didInit(false) + // Setup submodule names +{ + // Pointer to top level + TOPp = topp; + // Setup each module's pointers to their submodules + // Setup each module's pointer back to symbol table (for public functions) + TOPp->__Vconfigure(this, true); +} diff --git a/core/obj_dir/Vtb__Syms.h b/core/obj_dir/Vtb__Syms.h new file mode 100644 index 0000000..3d4db64 --- /dev/null +++ b/core/obj_dir/Vtb__Syms.h @@ -0,0 +1,35 @@ +// Verilated -*- C++ -*- +// DESCRIPTION: Verilator output: Symbol table internal header +// +// Internal details; most calling programs do not need this header, +// unless using verilator public meta comments. + +#ifndef _VTB__SYMS_H_ +#define _VTB__SYMS_H_ // guard + +#include "verilated_heavy.h" + +// INCLUDE MODULE CLASSES +#include "Vtb.h" + +// SYMS CLASS +class Vtb__Syms : public VerilatedSyms { + public: + + // LOCAL STATE + const char* __Vm_namep; + bool __Vm_didInit; + + // SUBCELL STATE + Vtb* TOPp; + + // CREATORS + Vtb__Syms(Vtb* topp, const char* namep); + ~Vtb__Syms() = default; + + // METHODS + inline const char* name() { return __Vm_namep; } + +} VL_ATTR_ALIGNED(VL_CACHE_LINE_BYTES); + +#endif // guard diff --git a/core/obj_dir/Vtb__ver.d b/core/obj_dir/Vtb__ver.d new file mode 100644 index 0000000..3e2c57e --- /dev/null +++ b/core/obj_dir/Vtb__ver.d @@ -0,0 +1 @@ +obj_dir/Vtb.cpp obj_dir/Vtb.h obj_dir/Vtb.mk obj_dir/Vtb__Slow.cpp obj_dir/Vtb__Syms.cpp obj_dir/Vtb__Syms.h obj_dir/Vtb__ver.d obj_dir/Vtb_classes.mk : /usr/bin/verilator_bin /usr/bin/verilator_bin regs.v tb.v diff --git a/core/obj_dir/Vtb__verFiles.dat b/core/obj_dir/Vtb__verFiles.dat new file mode 100644 index 0000000..5cfe1ca --- /dev/null +++ b/core/obj_dir/Vtb__verFiles.dat @@ -0,0 +1,14 @@ +# DESCRIPTION: Verilator output: Timestamp data for --skip-identical. Delete at will. +C "-cc -Wall -Wno-UNOPTFLAT -Wno-STMTDLY -Wno-UNDRIVEN -Wno-UNUSED -Wno-IGNOREDRETURN tb.v --exe --build Vtb.cpp" +S 8158392 13113442 1608512454 749492301 1607455047 0 "/usr/bin/verilator_bin" +T 3853 9588217 1612668578 766783891 1612668578 766783891 "obj_dir/Vtb.cpp" +T 2966 9588210 1612668578 766783891 1612668578 766783891 "obj_dir/Vtb.h" +T 1742 9588708 1612668578 766783891 1612668578 766783891 "obj_dir/Vtb.mk" +T 4812 9588212 1612668578 766783891 1612668578 766783891 "obj_dir/Vtb__Slow.cpp" +T 524 9587930 1612668578 766783891 1612668578 766783891 "obj_dir/Vtb__Syms.cpp" +T 774 9587948 1612668578 766783891 1612668578 766783891 "obj_dir/Vtb__Syms.h" +T 213 9588712 1612668578 766783891 1612668578 766783891 "obj_dir/Vtb__ver.d" +T 0 0 1612668578 766783891 1612668578 766783891 "obj_dir/Vtb__verFiles.dat" +T 1576 9588704 1612668578 766783891 1612668578 766783891 "obj_dir/Vtb_classes.mk" +S 1031 9587412 1612667707 796752074 1612667707 796752074 "regs.v" +S 1009 9587945 1612667697 96751683 1612667697 96751683 "tb.v" diff --git a/core/obj_dir/Vtb_classes.mk b/core/obj_dir/Vtb_classes.mk new file mode 100644 index 0000000..f3651f2 --- /dev/null +++ b/core/obj_dir/Vtb_classes.mk @@ -0,0 +1,49 @@ +# Verilated -*- Makefile -*- +# DESCRIPTION: Verilator output: Make include file with class lists +# +# This file lists generated Verilated files, for including in higher level makefiles. +# See Vtb.mk for the caller. + +### Switches... +# C11 constructs required? 0/1 (always on now) +VM_C11 = 1 +# Coverage output mode? 0/1 (from --coverage) +VM_COVERAGE = 0 +# Parallel builds? 0/1 (from --output-split) +VM_PARALLEL_BUILDS = 0 +# Threaded output mode? 0/1/N threads (from --threads) +VM_THREADS = 0 +# Tracing output mode? 0/1 (from --trace/--trace-fst) +VM_TRACE = 0 +# Tracing output mode in FST format? 0/1 (from --trace-fst) +VM_TRACE_FST = 0 +# Tracing threaded output mode? 0/1/N threads (from --trace-thread) +VM_TRACE_THREADS = 0 +# Separate FST writer thread? 0/1 (from --trace-fst with --trace-thread > 0) +VM_TRACE_FST_WRITER_THREAD = 0 + +### Object file lists... +# Generated module classes, fast-path, compile with highest optimization +VM_CLASSES_FAST += \ + Vtb \ + +# Generated module classes, non-fast-path, compile with low/medium optimization +VM_CLASSES_SLOW += \ + Vtb__Slow \ + +# Generated support classes, fast-path, compile with highest optimization +VM_SUPPORT_FAST += \ + +# Generated support classes, non-fast-path, compile with low/medium optimization +VM_SUPPORT_SLOW += \ + Vtb__Syms \ + +# Global classes, need linked once per executable, fast-path, compile with highest optimization +VM_GLOBAL_FAST += \ + verilated \ + +# Global classes, need linked once per executable, non-fast-path, compile with low/medium optimization +VM_GLOBAL_SLOW += \ + + +# Verilated -*- Makefile -*- diff --git a/core/obj_dir/verilated.d b/core/obj_dir/verilated.d new file mode 100644 index 0000000..8efb1e5 --- /dev/null +++ b/core/obj_dir/verilated.d @@ -0,0 +1,8 @@ +verilated.o: /usr/share/verilator/include/verilated.cpp \ + /usr/share/verilator/include/verilatedos.h \ + /usr/share/verilator/include/verilated_imp.h \ + /usr/share/verilator/include/verilated.h \ + /usr/share/verilator/include/verilated_heavy.h \ + /usr/share/verilator/include/verilated_syms.h \ + /usr/share/verilator/include/verilated_sym_props.h \ + /usr/share/verilator/include/verilated_config.h diff --git a/core/regs.v b/core/regs.v new file mode 100644 index 0000000..7d2025c --- /dev/null +++ b/core/regs.v @@ -0,0 +1,42 @@ +`timescale 1ms/1ms + +module regs( + input wire clk, reset, + input wire [4:0] reg_read1, [4:0] reg_read2, + input wire [4:0] reg_write, + input wire [63:0] write_data, + input wire write_en, + output reg [63:0] reg_read1_out, + output reg [63:0] reg_read2_out + ); + + reg [63:0] reg_array [31:0]; // 2D array of all regs, including pc + + function write_reg; + input reg [4:0] regid; + input reg [63:0] data; + begin + // if (regid > 0 || regid <= 32) // Must not write + reg_array[regid] = data; + write_reg = 1; + end + endfunction // write_reg + + function [63:0] read_reg; + input reg [4:0] regid; + begin + read_reg = reg_array[regid]; + end + endfunction // read_reg + + always @(write_en) begin + write_reg(reg_write, write_data); + end + + always @* begin + assign reg_read1_out = read_reg(reg_read1); + assign reg_read2_out = read_reg(reg_read2); + end + + +endmodule // regs diff --git a/core/tb.v b/core/tb.v new file mode 100644 index 0000000..b6f4645 --- /dev/null +++ b/core/tb.v @@ -0,0 +1,54 @@ +// Testbench for CPU components + +`timescale 1ms/1ms + + +module tb; + wire clk, reset; + reg [4:0] read1; + reg [4:0] read2; + wire [63:0] val1; + wire [63:0] val2; + reg [4:0] write; + reg [63:0] write_data; + reg write_en; + + regs r + (.clk(clk), .reset(reset), + .reg_read1(read1), .reg_read2(read2), + .reg_write(write), .write_data(write_data), .write_en(write_en), + .reg_read1_out(val1), .reg_read2_out(val2) + ); + + initial begin; + #100; + read1 = 1; + read2 = 2; + $display("%d %d", val1[31:0], val2[31:0]); + #200; + write = 1; + write_data = 10; + write_en = 1; + #250; + write_en = 0; + #300; + write = 2; + write_data = 20; + write_en = 1; + #350; + write_en = 0; + #400; + read1 = 3; + read2 = 4; + #450 + read1 = 1; + read2 = 2; + $display("%d %d", val1[31:0], val2[31:0]); + #500; + $stop; + end + + +endmodule // regs_tb + + -- cgit v1.2.3