Refactor soc and core

[?]
8Cqo1QjSCQ3F66Vh3nan9N8dv1MjQSAEz8RNwt2cTacK
May 18, 2024, 1:33 AM
LLHICJMHRWCZVTXZOJ3MO3LX6RCYUN6HTRMMJMGVOEBUXW6YMDWQC

Dependencies

  • [2] 3YRZ62OF Implemented register file and created skeleton for basic core
  • [3] MOJRQVF4 Factored out memory interface
  • [4] MTNLHQLQ Focus on the hardware design by dropping alternative HDLS for Verilog

Change contents

  • file deletion: regfile.sv (----------)
    [3.1][2.841:875](),[2.875][2.1:1]()
    // SPDX-License-Identifier: CERN-OHL-S-2.0
    // A simple dual-read, single-write register file
    `default_nettype none
    `timescale 1ps/1ps
    module regfile
    (
    input bit clk, rst,
    // Write port
    input wire wen,
    input wire [5:0] waddr,
    input wire [31:0] wdata,
    // Read ports
    input wire [5:0] raddrA,
    output wire [31:0] rdataA,
    input wire [5:0] raddrB,
    output wire [31:0] rdataB
    );
    // r0 is always 0, so we can not implement it
    reg [31:0] registers [0:30];
    always_ff @(posedge clk, rst)
    if (rst)
    for (integer i = 0; i < 32; i++) begin
    registers[i] <= 0;
    end
    else if (wen)
    registers[~waddr[4:0]] <= wdata;
    assign rdataA = registers[~raddrA[4:0]];
    assign rdataB = registers[~raddrB[4:0]];
    endmodule
  • file deletion: soc.sv (----------)
    [3.1][3.1423:1453](),[3.1453][3.18:18]()
    // SPDX-License-Identifier: CERN-OHL-S-2.0
    // A basic SOC with the core, ram, and uart
    // Default 16KB ram
    `default_nettype none
    `timescale 1ps/1ps
    module soc
    #(
    parameter integer MEM_WORDS = 4096
    )
    (
    input bit clk,
    input bit rst,
    );
    // TODO: impl uart
    assign uart_tx = 0 & uart_rx & rst;
    mem memory();
    mem_impl memory_impl(clk, memory.impl);
    // synthesis translate off
    logic [1000:0] mem_file;
    initial begin
    if ($test$plusargs("trace") != 0) begin
    $display("[%0t] Tracing to logs/vlt_dump.vcd...\n", $time);
    $dumpfile("logs/vlt_dump.vcd");
    $dumpvars();
    end
    end
    // synthesis translate on
    endmodule
    input wire uart_rx,
    output wire uart_tx
  • file deletion: basic_rv32i.sv (----------)
    [3.1][2.2137:2175](),[2.2175][2.877:877]()
    // SPDX-License-Identifier: CERN-OHL-S-2.0
    // A maxmimally simple core
    `default_nettype none
    `timescale 1ps/1ps
    module basic_rv32i
    (
    mem.core mem,
    `ifdef RISCV_FORMAL
    output reg rvfi_valid,
    output reg [63:0] rvfi_order,
    output reg [31:0] rvfi_insn,
    output reg rvfi_trap,
    output reg rvfi_halt,
    output reg rvfi_intr,
    output reg [ 1:0] rvfi_mode,
    output reg [ 1:0] rvfi_ixl,
    output reg [ 4:0] rvfi_rs1_addr,
    output reg [ 4:0] rvfi_rs2_addr,
    output reg [31:0] rvfi_rs1_rdata,
    output reg [31:0] rvfi_rs2_rdata,
    output reg [ 4:0] rvfi_rd_addr,
    output reg [31:0] rvfi_rd_wdata,
    output reg [31:0] rvfi_pc_rdata,
    output reg [31:0] rvfi_pc_wdata,
    output reg [31:0] rvfi_mem_addr,
    output reg [ 3:0] rvfi_mem_rmask,
    output reg [ 3:0] rvfi_mem_wmask,
    output reg [31:0] rvfi_mem_rdata,
    output reg [31:0] rvfi_mem_wdata,
    output reg [63:0] rvfi_csr_mcycle_rmask,
    output reg [63:0] rvfi_csr_mcycle_wmask,
    output reg [63:0] rvfi_csr_mcycle_rdata,
    output reg [63:0] rvfi_csr_mcycle_wdata,
    output reg [63:0] rvfi_csr_minstret_rmask,
    output reg [63:0] rvfi_csr_minstret_wmask,
    output reg [63:0] rvfi_csr_minstret_rdata,
    output reg [63:0] rvfi_csr_minstret_wdata,
    `endif
    input bit clk, rst
    );
    endmodule
  • file deletion: mem.sv (----------)
    [3.1][3.2244:2274](),[3.2274][3.1:1]()
    // SPDX-License-Identifier: CERN-OHL-S-2.0
    // A simple valid-ready memory interface that can handle a single memory transfer at a time
    `default_nettype none
    `timescale 1ps/1ps
    // The core initiates a transfer by asserting valid, which stays high until the
    // peer asserts ready. All core outputs are stable over the valid period.
    // If the transfer is an instruction fetch, the core asserts instr.
    interface mem;
    bit valid;
    bit ready;
    bit instr;
    enum bit[3:0] {
    READ = 'b0000,
    WRITE_BYTE0 = 'b0001,
    WRITE_BYTE1 = 'b0010,
    WRITE_BYTE2 = 'b0100,
    WRITE_BYTE3 = 'b1000,
    WRITE_HWORD0 = 'b0011,
    WRITE_HWORD1 = 'b1100,
    WRITE_WORD = 'b1111
    } mode;
    wire [31:0] addr;
    wire [31:0] rdata;
    wire [31:0] wdata;
    modport core (
    output valid,
    input ready,
    output instr,
    output mode,
    output addr,
    input rdata,
    output wdata
    );
    modport impl (
    input valid,
    output ready,
    input instr,
    input mode,
    input addr,
    output rdata,
    input wdata
    );
    endinterface
    /* verilator lint_off DECLFILENAME */
    module mem_impl
    #(
    parameter integer MEM_WORDS = 4096
    )
    (
    input bit clk,
    mem.impl mem
    );
    always_ff @(posedge clk) begin
    mem.ready <= '0;
    if (mem.valid) begin
    mem.rdata <= memory[mem.addr];
    if (wen[0]) memory[mem.addr][ 7: 0] <= mem.wdata[ 7: 0];
    if (wen[1]) memory[mem.addr][15: 8] <= mem.wdata[15: 8];
    if (wen[2]) memory[mem.addr][23:16] <= mem.wdata[23:16];
    if (wen[3]) memory[mem.addr][31:24] <= mem.wdata[31:24];
    end
    end
    // synthesis translate off
    logic [200:0] mem_file;
    initial begin
    if ($value$plusargs("mem", mem_file)) begin
    $display("[%0t] Initializing memory\n", $time);
    $readmemh(mem_file, memory);
    end
    end
    phys_mem_addr: assert property(@(posedge clk) mem.addr < (4*MEM_WORDS));
    // synthesis translate on
    endmodule
    reg [31:0] memory [0:MEM_WORDS-1];
    reg [3:0] wen = mem.mode;
  • file addition: soc (d--r------)
    [3.1]
  • file addition: uart.sv (----------)
    [0.1]
    // SPDX-License-Identifier: CERN-OHL-S-2.0
    // A basic valid-ready ram, default 16KiB
    `default_nettype none
    `timescale 1ps/1ps
    module uart
    (
    input logic clk_i,
    input logic rst_ni,
    input logic uart_i,
    output logic uart_o
    );
    // TODO: implement
    endmodule
  • file addition: soc_pkg.sv (----------)
    [0.1]
    // SPDX-License-Identifier: CERN-OHL-S-2.0
    `default_nettype none
    `timescale 1ps/1ps
    package soc_pkg;
    parameter int unsigned MEM_WORDS = 4096;
    typedef struct packed {
    logic valid;
    logic [ 7:0] wen;
    logic [63:0] addr;
    logic [63:0] wdata;
    } mem_in_t;
    typedef struct packed {
    logic ready;
    logic [63:0] rdata;
    } mem_out_t;
    endpackage
  • file addition: soc.sv (----------)
    [0.1]
    // SPDX-License-Identifier: CERN-OHL-S-2.0
    // A basic SOC with the core, ram, and uart
    // Default 32KiB ram
    `default_nettype none
    `timescale 1ps/1ps
    module soc
    (
    input logic clk_i,
    input logic rst_ni,
    input logic uart_i,
    output logic uart_o
    );
    uart uart_impl(.clk_i, .rst_ni, .uart_i, .uart_o);
    soc_pkg::mem_in_t mem_in;
    soc_pkg::mem_out_t mem_out;
    mem ram(.clk_i, .core_i(mem_in), .core_o(mem_out));
    `ifndef SYNTHESIS
    initial begin
    if ($test$plusargs("trace") != 0) begin
    $display("[%0t] Tracing to logs/vlt_dump.vcd...\n", $time);
    $dumpfile("logs/vlt_dump.vcd");
    $dumpvars();
    end
    end
    `endif
    endmodule
  • file addition: mem.sv (----------)
    [0.1]
    // SPDX-License-Identifier: CERN-OHL-S-2.0
    // A basic valid-ready ram, default 32KiB
    `default_nettype none
    `timescale 1ps/1ps
    // The core initiates a transfer by asserting valid, which stays high until the
    // peer asserts ready. All core outputs are stable over the valid period.
    module mem
    (
    input logic clk_i,
    input soc_pkg::mem_in_t core_i,
    output soc_pkg::mem_out_t core_o
    );
    logic [63:0] memory [0:soc_pkg::MEM_WORDS-1];
    always_ff @(posedge clk_i) begin
    core_o.ready <= '0;
    if (core_i.valid) begin
    MemAddrFitsIntoPhys: assert(core_i.addr < (8*soc_pkg::MEM_WORDS));
    core_o.rdata <= memory[core_i.addr];
    core_o.ready <= 1'b1;
    if (core_i.wen[0]) memory[core_i.addr][ 7: 0] <= core_i.wdata[ 7: 0];
    if (core_i.wen[1]) memory[core_i.addr][15: 8] <= core_i.wdata[15: 8];
    if (core_i.wen[2]) memory[core_i.addr][23:16] <= core_i.wdata[23:16];
    if (core_i.wen[3]) memory[core_i.addr][31:24] <= core_i.wdata[31:24];
    end
    end
    `ifndef SYNTHESIS
    logic [200:0] mem_file;
    initial begin
    if ($value$plusargs("mem", mem_file)) begin
    $display("[%0t] Initializing memory\n", $time);
    $readmemh(mem_file, memory);
    end
    end
    `endif
    endmodule
  • file addition: core (d--r------)
    [3.1]
  • file addition: core_pkg.sv (----------)
    [0.2949]
    // SPDX-License-Identifier: CERN-OHL-S-2.0
    `default_nettype none
    `timescale 1ps/1ps
    package core_pkg;
    // The core initiates a transfer by asserting valid, which stays high until the
    // peer asserts ready. All core outputs are stable over the valid period.
    typedef struct packed {
    logic valid;
    logic [ 3:0] wen;
    logic [31:0] addr;
    logic [31:0] wdata;
    } core_out_t;
    typedef struct packed {
    logic ready;
    logic [31:0] rdata;
    } core_in_t;
    endpackage
  • replacement in README.md at line 2
    [3.1526][3.1526:1624]()
    The core targets RV32IAMS to fit on reasonably priced FPGAs while still being able to boot Linux.
    [3.1526]
    [3.1624]
    The core targets RV64IAMS to reduce complexity while still being able to boot Linux.
  • replacement in README.md at line 4
    [3.1625][3.1625:1797]()
    A toolchain will need to be compiled from source, as the default extensions for RISC-V toolchains are GC, and the `ilp32` ABI used is not compatible with the ABI they use.
    [3.1625]
    [3.1797]
    A toolchain will need to be compiled from source, as the default extensions for RISC-V toolchains are GC, and the `lp64` ABI used is not compatible with the ABI they use.
  • replacement in Makefile at line 6
    [3.2042][3.2042:2065]()
    SMTBMC ?= yosys-smtbmc
    [3.2042]
    [3.2065]
    SLANG ?= slang
    JOBS ?= 16
    LINKER ?= mold
  • replacement in Makefile at line 17
    [3.2378][3.2378:2460]()
    # Use the mold linker to massively improve linking speed
    LDFLAGS += -fuse-ld=mold
    [3.2378]
    [3.2460]
    LDFLAGS += -fuse-ld=$(LINKER)
  • replacement in Makefile at line 21
    [3.2495][3.2495:2526]()
    VERILATOR_FLAGS += -j $(nproc)
    [3.2495]
    [3.2526]
    VERILATOR_COMMON_FLAGS += -j $(JOBS)
    # Check assertions
    VERILATOR_COMMON_FLAGS += --assert
    # Generate coverage analysis
    VERILATOR_COMMON_FLAGS += --coverage
    # Look in the rtl directory
    VERILATOR_COMMON_FLAGS += -Irtl/soc -Irtl/core
  • replacement in Makefile at line 29
    [3.2541][3.2541:2565]()
    VERILATOR_FLAGS += --cc
    [3.2541]
    [3.2342]
    VERILATOR_GENERATION_FLAGS += --cc
  • replacement in Makefile at line 31
    [3.2362][3.2581:2605](),[3.2581][3.2581:2605]()
    VERILATOR_FLAGS += -MMD
    [3.2362]
    [3.2605]
    VERILATOR_GENERATION_FLAGS += -MMD
  • replacement in Makefile at line 33
    [3.2693][3.2693:2731]()
    VERILATOR_FLAGS += --output-split 500
    [3.2693]
    [3.2731]
    VERILATOR_GENERATION_FLAGS += --output-split 500
  • replacement in Makefile at line 35
    [3.2788][3.2788:3015]()
    VERILATOR_FLAGS += --output-split-cfuncs 50 --output-split-ctrace 50
    # Warn about lint issues
    VERILATOR_FLAGS += -Wall
    # Check assertions
    VERILATOR_FLAGS += --assert
    # Generate coverage analysis
    VERILATOR_FLAGS += --coverage
    [3.2788]
    [3.3015]
    VERILATOR_GENERATION_FLAGS += --output-split-cfuncs 50 --output-split-ctrace 50
  • replacement in Makefile at line 38
    [3.3052][3.3052:3092]()
    # VERILATOR_FLAGS += --threads $(nproc)
    [3.3052]
    [3.3092]
    # VERILATOR_GENERATION_FLAGS += --threads $(JOBS)
  • edit in Makefile at line 41
    [3.3138]
    [3.3138]
    # Pkgs must come first to prevent compile errors
    SOC_RTLS = rtl/soc/soc_pkg.sv rtl/soc/soc.sv rtl/soc/mem.sv rtl/soc/uart.sv
  • edit in Makefile at line 47
    [3.3190]
    [3.3190]
    lint: soc-lint-slang soc-lint-yosys_parse soc-lint-verilator
  • replacement in Makefile at line 50
    [3.3209][3.2363:2413]()
    $(VERILATOR) $(VERILATOR_FLAGS) rtl/soc.sv -Irtl
    [3.3209]
    [3.3253]
    $(VERILATOR) $(VERILATOR_COMMON_FLAGS) $(VERILATOR_GENERATION_FLAGS) $(SOC_RTLS)
  • replacement in Makefile at line 53
    [3.3271][3.3271:3305]()
    $(MAKE) -j -C obj_dir -f Vsoc.mk
    [3.3271]
    [3.3305]
    $(MAKE) -j $(JOBS) -C obj_dir -f Vsoc.mk
    soc-lint-verilator:
    $(VERILATOR) $(VERILATOR_COMMON_FLAGS) --lint-only -Wall -Wpedantic $(SOC_RTLS)
    soc-lint-slang:
    $(SLANG) -j $(JOBS) -Irtl/soc -Irtl/core --allow-dup-initial-drivers $(SOC_RTLS)
  • edit in Makefile at line 61
    [3.3306]
    [3.3306]
    soc-lint-yosys_parse:
    $(YOSYS) -q -p 'read_verilog -sv -Irtl/soc -Irtl/core $(SOC_RTLS)'