diff --git a/ci/ibex-rtl-ci-steps.yml b/ci/ibex-rtl-ci-steps.yml index 5fc32a7b..5b1a853f 100644 --- a/ci/ibex-rtl-ci-steps.yml +++ b/ci/ibex-rtl-ci-steps.yml @@ -14,19 +14,19 @@ steps: displayName: Test and display fusesoc config for ${{ config }} - bash: | - fusesoc --cores-root . run --target=lint --tool=verilator lowrisc:ibex:ibex_core_tracing $IBEX_CONFIG_OPTS + fusesoc --cores-root . run --target=lint --tool=verilator lowrisc:ibex:ibex_top_tracing $IBEX_CONFIG_OPTS if [ $? != 0 ]; then echo -n "##vso[task.logissue type=error]" - echo "Verilog lint failed. Run 'fusesoc --cores-root . run --target=lint --tool=verilator lowrisc:ibex:ibex_core_tracing $IBEX_CONFIG_OPTS' to check and fix all errors." + echo "Verilog lint failed. Run 'fusesoc --cores-root . run --target=lint --tool=verilator lowrisc:ibex:ibex_top_tracing $IBEX_CONFIG_OPTS' to check and fix all errors." exit 1 fi displayName: Lint Verilog source files with Verilator for ${{ config }} - bash: | - fusesoc --cores-root . run --target=lint --tool=veriblelint lowrisc:ibex:ibex_core_tracing $IBEX_CONFIG_OPTS + fusesoc --cores-root . run --target=lint --tool=veriblelint lowrisc:ibex:ibex_top_tracing $IBEX_CONFIG_OPTS if [ $? != 0 ]; then echo -n "##vso[task.logissue type=error]" - echo "Verilog lint failed. Run 'fusesoc --cores-root . run --target=lint --tool=veriblelint lowrisc:ibex:ibex_core_tracing $IBEX_CONFIG_OPTS' to check and fix all errors." + echo "Verilog lint failed. Run 'fusesoc --cores-root . run --target=lint --tool=veriblelint lowrisc:ibex:ibex_top_tracing $IBEX_CONFIG_OPTS' to check and fix all errors." exit 1 fi displayName: Lint Verilog source files with Verible Verilog Lint for ${{ config }} diff --git a/doc/02_user/integration.rst b/doc/02_user/integration.rst index d165fdb0..e6a8ff05 100644 --- a/doc/02_user/integration.rst +++ b/doc/02_user/integration.rst @@ -3,7 +3,7 @@ Core Integration ================ -The main module is named ``ibex_core`` and can be found in ``ibex_core.sv``. +The main module is named ``ibex_top`` and can be found in ``ibex_top.sv``. Below, the instantiation template is given and the parameters and interfaces are described. Instantiation Template @@ -11,7 +11,7 @@ Instantiation Template .. code-block:: verilog - ibex_core #( + ibex_top #( .PMPEnable ( 0 ), .PMPGranularity ( 0 ), .PMPNumRegions ( 4 ), @@ -28,7 +28,7 @@ Instantiation Template .DbgTriggerEn ( 0 ), .DmHaltAddr ( 32'h1A110800 ), .DmExceptionAddr ( 32'h1A110808 ) - ) u_core ( + ) u_top ( // Clock and reset .clk_i (), .rst_ni (), diff --git a/doc/03_reference/icache.rst b/doc/03_reference/icache.rst index c96273e3..1e55de98 100644 --- a/doc/03_reference/icache.rst +++ b/doc/03_reference/icache.rst @@ -204,7 +204,7 @@ This isn't an attempt to describe the cache's performance characteristics. The I$ has a single clock (``clk_i``) and asynchronous reset (``rst_ni``). Data is requested from the instruction memory with the ports prefixed by ``instr_``. These work as described in :ref:`instruction-fetch`. -Note that there's one extra port on the I$, which doesn't appear at the ``ibex_core`` top-level. +Note that there's one extra port on the I$, which doesn't appear at the ``ibex_top`` top-level. This is ``instr_pmp_err_i``. If the PMP block disallows a fetch for a certain address, it will squash the outgoing memory request entirely and set ``instr_pmp_err_i``. If that happens, the cache drops ``instr_req_o`` and stops making any further requests for that cache line. diff --git a/doc/03_reference/tracer.rst b/doc/03_reference/tracer.rst index 6a1fedab..38242063 100644 --- a/doc/03_reference/tracer.rst +++ b/doc/03_reference/tracer.rst @@ -4,7 +4,7 @@ Tracer ====== The module ``ibex_tracer`` can be used to create a log of the executed instructions. -It is used by ``ibex_core_tracing`` which forwards the `RVFI signals `_ to the tracer (see also :ref:`rvfi`). +It is used by ``ibex_top_tracing`` which forwards the `RVFI signals `_ to the tracer (see also :ref:`rvfi`). Output file ----------- diff --git a/dv/riscv_compliance/ibex_riscv_compliance.core b/dv/riscv_compliance/ibex_riscv_compliance.core index 0e5f56e7..54db4509 100644 --- a/dv/riscv_compliance/ibex_riscv_compliance.core +++ b/dv/riscv_compliance/ibex_riscv_compliance.core @@ -9,7 +9,7 @@ filesets: depend: - lowrisc:dv_verilator:memutil_verilator - lowrisc:dv_verilator:simutil_verilator - - lowrisc:ibex:ibex_core_tracing + - lowrisc:ibex:ibex_top_tracing - lowrisc:ibex:sim_shared files: diff --git a/dv/riscv_compliance/rtl/ibex_riscv_compliance.sv b/dv/riscv_compliance/rtl/ibex_riscv_compliance.sv index db625783..7cfea96c 100644 --- a/dv/riscv_compliance/rtl/ibex_riscv_compliance.sv +++ b/dv/riscv_compliance/rtl/ibex_riscv_compliance.sv @@ -112,7 +112,7 @@ module ibex_riscv_compliance ( .cfg_device_addr_mask ); - ibex_core_tracing #( + ibex_top_tracing #( .PMPEnable (PMPEnable ), .PMPGranularity (PMPGranularity ), .PMPNumRegions (PMPNumRegions ), @@ -127,7 +127,7 @@ module ibex_riscv_compliance ( .BranchPredictor (BranchPredictor ), .DmHaltAddr (32'h00000000 ), .DmExceptionAddr (32'h00000000 ) - ) u_core ( + ) u_top ( .clk_i (clk_sys ), .rst_ni (rst_sys_n ), diff --git a/dv/uvm/core_ibex/ibex_dv.f b/dv/uvm/core_ibex/ibex_dv.f index 60531b4e..5493126e 100644 --- a/dv/uvm/core_ibex/ibex_dv.f +++ b/dv/uvm/core_ibex/ibex_dv.f @@ -63,7 +63,8 @@ ${PRJ_DIR}/rtl/ibex_register_file_fpga.sv ${PRJ_DIR}/rtl/ibex_register_file_latch.sv ${PRJ_DIR}/rtl/ibex_pmp.sv ${PRJ_DIR}/rtl/ibex_core.sv -${PRJ_DIR}/rtl/ibex_core_tracing.sv +${PRJ_DIR}/rtl/ibex_top.sv +${PRJ_DIR}/rtl/ibex_top_tracing.sv // Core DV files ${PRJ_DIR}/vendor/google_riscv-dv/src/riscv_signature_pkg.sv diff --git a/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv b/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv index 955496b3..ac3464f2 100644 --- a/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv +++ b/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv @@ -58,7 +58,7 @@ module core_ibex_tb_top; parameter bit ICacheECC = 1'b0; parameter bit BranchPredictor = 1'b0; - ibex_core_tracing #( + ibex_top_tracing #( .DmHaltAddr (32'h`BOOT_ADDR + 'h0 ), .DmExceptionAddr (32'h`BOOT_ADDR + 'h4 ), .PMPEnable (PMPEnable ), @@ -78,7 +78,7 @@ module core_ibex_tb_top; .rst_ni (rst_n ), .test_en_i (1'b0 ), - .ram_cfg_i (1'b0 ), + .ram_cfg_i ('b0 ), .hart_id_i (32'b0 ), .boot_addr_i (32'h`BOOT_ADDR ), // align with spike boot address @@ -145,31 +145,31 @@ module core_ibex_tb_top; // Irq interface connections assign irq_vif.reset = ~rst_n; // Dut_if interface connections - assign dut_if.ecall = dut.u_ibex_core.id_stage_i.controller_i.ecall_insn; - assign dut_if.wfi = dut.u_ibex_core.id_stage_i.controller_i.wfi_insn; - assign dut_if.ebreak = dut.u_ibex_core.id_stage_i.controller_i.ebrk_insn; - assign dut_if.illegal_instr = dut.u_ibex_core.id_stage_i.controller_i.illegal_insn_d; - assign dut_if.dret = dut.u_ibex_core.id_stage_i.controller_i.dret_insn; - assign dut_if.mret = dut.u_ibex_core.id_stage_i.controller_i.mret_insn; + assign dut_if.ecall = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.ecall_insn; + assign dut_if.wfi = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.wfi_insn; + assign dut_if.ebreak = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.ebrk_insn; + assign dut_if.illegal_instr = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.illegal_insn_d; + assign dut_if.dret = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.dret_insn; + assign dut_if.mret = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.mret_insn; assign dut_if.reset = ~rst_n; - assign dut_if.priv_mode = dut.u_ibex_core.priv_mode_id; + assign dut_if.priv_mode = dut.u_ibex_top.u_ibex_core.priv_mode_id; // Instruction monitor connections - assign instr_monitor_if.valid_id = dut.u_ibex_core.id_stage_i.instr_valid_i; - assign instr_monitor_if.err_id = dut.u_ibex_core.id_stage_i.controller_i.instr_fetch_err; - assign instr_monitor_if.is_compressed_id = dut.u_ibex_core.id_stage_i.instr_is_compressed_i; - assign instr_monitor_if.instr_compressed_id = dut.u_ibex_core.id_stage_i.instr_rdata_c_i; - assign instr_monitor_if.instr_id = dut.u_ibex_core.id_stage_i.instr_rdata_i; - assign instr_monitor_if.pc_id = dut.u_ibex_core.pc_id; - assign instr_monitor_if.branch_taken_id = dut.u_ibex_core.id_stage_i.controller_i.branch_set_i; - assign instr_monitor_if.branch_target_id = dut.u_ibex_core.branch_target_ex; - assign instr_monitor_if.stall_id = dut.u_ibex_core.id_stage_i.stall_id; - assign instr_monitor_if.jump_set_id = dut.u_ibex_core.id_stage_i.jump_set; + assign instr_monitor_if.valid_id = dut.u_ibex_top.u_ibex_core.id_stage_i.instr_valid_i; + assign instr_monitor_if.err_id = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.instr_fetch_err; + assign instr_monitor_if.is_compressed_id = dut.u_ibex_top.u_ibex_core.id_stage_i.instr_is_compressed_i; + assign instr_monitor_if.instr_compressed_id = dut.u_ibex_top.u_ibex_core.id_stage_i.instr_rdata_c_i; + assign instr_monitor_if.instr_id = dut.u_ibex_top.u_ibex_core.id_stage_i.instr_rdata_i; + assign instr_monitor_if.pc_id = dut.u_ibex_top.u_ibex_core.pc_id; + assign instr_monitor_if.branch_taken_id = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.branch_set_i; + assign instr_monitor_if.branch_target_id = dut.u_ibex_top.u_ibex_core.branch_target_ex; + assign instr_monitor_if.stall_id = dut.u_ibex_top.u_ibex_core.id_stage_i.stall_id; + assign instr_monitor_if.jump_set_id = dut.u_ibex_top.u_ibex_core.id_stage_i.jump_set; // CSR interface connections - assign csr_if.csr_access = dut.u_ibex_core.csr_access; - assign csr_if.csr_addr = dut.u_ibex_core.csr_addr; - assign csr_if.csr_wdata = dut.u_ibex_core.csr_wdata; - assign csr_if.csr_rdata = dut.u_ibex_core.csr_rdata; - assign csr_if.csr_op = dut.u_ibex_core.csr_op; + assign csr_if.csr_access = dut.u_ibex_top.u_ibex_core.csr_access; + assign csr_if.csr_addr = dut.u_ibex_top.u_ibex_core.csr_addr; + assign csr_if.csr_wdata = dut.u_ibex_top.u_ibex_core.csr_wdata; + assign csr_if.csr_rdata = dut.u_ibex_top.u_ibex_core.csr_rdata; + assign csr_if.csr_op = dut.u_ibex_top.u_ibex_core.csr_op; initial begin // Drive the clock and reset lines. Reset everything and start the clock at the beginning of diff --git a/dv/uvm/icache/dv/ibex_icache_sim.core b/dv/uvm/icache/dv/ibex_icache_sim.core index 403f8d17..56268f62 100644 --- a/dv/uvm/icache/dv/ibex_icache_sim.core +++ b/dv/uvm/icache/dv/ibex_icache_sim.core @@ -8,6 +8,9 @@ filesets: files_rtl: depend: - lowrisc:ibex:ibex_icache:0.1 + files: + - tb/ic_top.sv + file_type: systemVerilogSource files_dv: depend: diff --git a/dv/uvm/icache/dv/tb/ic_top.sv b/dv/uvm/icache/dv/tb/ic_top.sv new file mode 100644 index 00000000..b366594f --- /dev/null +++ b/dv/uvm/icache/dv/tb/ic_top.sv @@ -0,0 +1,131 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +module ic_top import ibex_pkg::*; #(parameter bit ICacheECC = 1'b0) ( + input logic clk_i, + input logic rst_ni, + input logic req_i, + input logic branch_i, + input logic branch_spec_i, + input logic predicted_branch_i, + input logic branch_mispredict_i, + input logic [31:0] addr_i, + input logic ready_i, + output logic valid_o, + output logic [31:0] rdata_o, + output logic [31:0] addr_o, + output logic err_o, + output logic err_plus2_o, + output logic instr_req_o, + input logic instr_gnt_i, + output logic [31:0] instr_addr_o, + input logic [BUS_SIZE-1:0] instr_rdata_i, + input logic instr_err_i, + input logic instr_pmp_err_i, + input logic instr_rvalid_i, + + input logic icache_enable_i, + input logic icache_inval_i, + output logic busy_o +); + + localparam int unsigned BusSizeECC = ICacheECC ? (BUS_SIZE + 7) : BUS_SIZE; + localparam int unsigned LineSizeECC = BusSizeECC * IC_LINE_BEATS; + localparam int unsigned TagSizeECC = ICacheECC ? (IC_TAG_SIZE + 6) : IC_TAG_SIZE; + + // RAM IO + logic [IC_NUM_WAYS-1:0] ic_tag_req; + logic ic_tag_write; + logic [IC_INDEX_W-1:0] ic_tag_addr; + logic [TagSizeECC-1:0] ic_tag_wdata; + logic [TagSizeECC-1:0] ic_tag_rdata [IC_NUM_WAYS]; + logic [IC_NUM_WAYS-1:0] ic_data_req; + logic ic_data_write; + logic [IC_INDEX_W-1:0] ic_data_addr; + logic [LineSizeECC-1:0] ic_data_wdata; + logic [LineSizeECC-1:0] ic_data_rdata [IC_NUM_WAYS]; + + // DUT + ibex_icache #( + .ICacheECC (ICacheECC), + .BusSizeECC (BusSizeECC), + .TagSizeECC (TagSizeECC), + .LineSizeECC (LineSizeECC) + ) icache_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .req_i ( req_i ), + + .branch_i ( branch_i ), + .branch_spec_i ( branch_spec_i ), + .predicted_branch_i ( predicted_branch_i ), + .branch_mispredict_i ( branch_mispredict_i ), + .addr_i ( addr_i ), + + .ready_i ( ready_i ), + .valid_o ( valid_o ), + .rdata_o ( rdata_o ), + .addr_o ( addr_o ), + .err_o ( err_o ), + .err_plus2_o ( err_plus2_o ), + + .instr_req_o ( instr_req_o ), + .instr_addr_o ( instr_addr_o ), + .instr_gnt_i ( instr_gnt_i ), + .instr_rvalid_i ( instr_rvalid_i ), + .instr_rdata_i ( instr_rdata_i ), + .instr_err_i ( instr_err_i ), + .instr_pmp_err_i ( instr_pmp_err_i ), + + .ic_tag_req_o ( ic_tag_req ), + .ic_tag_write_o ( ic_tag_write ), + .ic_tag_addr_o ( ic_tag_addr ), + .ic_tag_wdata_o ( ic_tag_wdata ), + .ic_tag_rdata_i ( ic_tag_rdata ), + .ic_data_req_o ( ic_data_req ), + .ic_data_write_o ( ic_data_write ), + .ic_data_addr_o ( ic_data_addr ), + .ic_data_wdata_o ( ic_data_wdata ), + .ic_data_rdata_i ( ic_data_rdata ), + + .icache_enable_i ( icache_enable_i ), + .icache_inval_i ( icache_inval_i ), + .busy_o ( busy_o ) + ); + // RAMs + for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_rams + // Tag RAM instantiation + prim_ram_1p #( + .Width (TagSizeECC), + .Depth (IC_NUM_LINES), + .DataBitsPerMask (TagSizeECC) + ) tag_bank ( + .clk_i (clk_i), + .req_i (ic_tag_req[way]), + .cfg_i ('0), + .write_i (ic_tag_write), + .wmask_i ({TagSizeECC{1'b1}}), + .addr_i (ic_tag_addr), + .wdata_i (ic_tag_wdata), + .rdata_o (ic_tag_rdata[way]) + ); + // Data RAM instantiation + prim_ram_1p #( + .Width (LineSizeECC), + .Depth (IC_NUM_LINES), + .DataBitsPerMask (LineSizeECC) + ) data_bank ( + .clk_i (clk_i), + .req_i (ic_data_req[way]), + .cfg_i ('0), + .write_i (ic_data_write), + .wmask_i ({LineSizeECC{1'b1}}), + .addr_i (ic_data_addr), + .wdata_i (ic_data_wdata), + .rdata_o (ic_data_rdata[way]) + ); + end + +endmodule diff --git a/dv/uvm/icache/dv/tb/tb.sv b/dv/uvm/icache/dv/tb/tb.sv index f9ad694c..94df9bde 100644 --- a/dv/uvm/icache/dv/tb/tb.sv +++ b/dv/uvm/icache/dv/tb/tb.sv @@ -22,7 +22,7 @@ module tb #(parameter bit ICacheECC = 1'b0); ibex_icache_mem_if mem_if (.clk(clk), .rst_n(rst_n)); // dut - ibex_icache #( + ic_top #( .ICacheECC (ICacheECC) ) dut ( .clk_i (clk), @@ -41,7 +41,6 @@ module tb #(parameter bit ICacheECC = 1'b0); .addr_o (core_if.addr), .err_o (core_if.err), .err_plus2_o (core_if.err_plus2), - .ram_cfg_i ('0), .icache_enable_i (core_if.enable), .icache_inval_i (core_if.invalidate), .busy_o (core_if.busy), diff --git a/examples/fpga/artya7/rtl/top_artya7.sv b/examples/fpga/artya7/rtl/top_artya7.sv index db4e4611..62c9fea1 100644 --- a/examples/fpga/artya7/rtl/top_artya7.sv +++ b/examples/fpga/artya7/rtl/top_artya7.sv @@ -42,11 +42,11 @@ module top_artya7 ( logic [31:0] mem_rdata; - ibex_core #( + ibex_top #( .RegFile(ibex_pkg::RegFileFPGA), .DmHaltAddr(32'h00000000), .DmExceptionAddr(32'h00000000) - ) u_core ( + ) u_top ( .clk_i (clk_sys), .rst_ni (rst_sys_n), diff --git a/examples/fpga/artya7/top_artya7.core b/examples/fpga/artya7/top_artya7.core index 811fb93c..5b7fab20 100644 --- a/examples/fpga/artya7/top_artya7.core +++ b/examples/fpga/artya7/top_artya7.core @@ -7,7 +7,7 @@ description: "Ibex example toplevel for Arty A7 boards (both, -35 and -100)" filesets: files_rtl_artya7: depend: - - lowrisc:ibex:ibex_core + - lowrisc:ibex:ibex_top - lowrisc:ibex:fpga_xilinx_shared files: - rtl/top_artya7.sv diff --git a/examples/simple_system/ibex_simple_system.core b/examples/simple_system/ibex_simple_system.core index a153ea25..c585a099 100644 --- a/examples/simple_system/ibex_simple_system.core +++ b/examples/simple_system/ibex_simple_system.core @@ -7,7 +7,7 @@ description: "Generic simple system for running binaries on ibex using verilator filesets: files_sim: depend: - - lowrisc:ibex:ibex_core_tracing + - lowrisc:ibex:ibex_top_tracing - lowrisc:ibex:sim_shared files: - rtl/ibex_simple_system.sv diff --git a/examples/simple_system/rtl/ibex_simple_system.sv b/examples/simple_system/rtl/ibex_simple_system.sv index 3de2c17e..68c7bf7f 100644 --- a/examples/simple_system/rtl/ibex_simple_system.sv +++ b/examples/simple_system/rtl/ibex_simple_system.sv @@ -161,7 +161,7 @@ module ibex_simple_system ( .cfg_device_addr_mask ); - ibex_core_tracing #( + ibex_top_tracing #( .SecureIbex ( SecureIbex ), .PMPEnable ( PMPEnable ), .PMPGranularity ( PMPGranularity ), @@ -178,7 +178,7 @@ module ibex_simple_system ( .BranchPredictor ( BranchPredictor ), .DmHaltAddr ( 32'h00100000 ), .DmExceptionAddr ( 32'h00100000 ) - ) u_core ( + ) u_top ( .clk_i (clk_sys), .rst_ni (rst_sys_n), @@ -282,7 +282,7 @@ module ibex_simple_system ( export "DPI-C" function mhpmcounter_get; function automatic longint unsigned mhpmcounter_get(int index); - return u_core.u_ibex_core.cs_registers_i.mhpmcounter[index]; + return u_top.u_ibex_top.u_ibex_core.cs_registers_i.mhpmcounter[index]; endfunction endmodule diff --git a/ibex_core.core b/ibex_core.core index 4a6333dd..a77ba599 100644 --- a/ibex_core.core +++ b/ibex_core.core @@ -3,7 +3,7 @@ CAPI=2: # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 name: "lowrisc:ibex:ibex_core:0.1" -description: "Ibex, a small RV32 CPU core" +description: "Ibex CPU Core Components" filesets: files_rtl: @@ -34,9 +34,6 @@ filesets: - rtl/ibex_pmp.sv - rtl/ibex_wb_stage.sv - rtl/ibex_dummy_instr.sv - - rtl/ibex_register_file_ff.sv # generic FF-based - - rtl/ibex_register_file_fpga.sv # FPGA - - rtl/ibex_register_file_latch.sv # ASIC - rtl/ibex_core.sv file_type: systemVerilogSource diff --git a/ibex_top.core b/ibex_top.core new file mode 100644 index 00000000..12bec71c --- /dev/null +++ b/ibex_top.core @@ -0,0 +1,160 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:ibex:ibex_top:0.1" +description: "Ibex, a small RV32 CPU core" + +filesets: + files_rtl: + depend: + - lowrisc:ibex:ibex_pkg + - lowrisc:ibex:ibex_core + files: + - rtl/ibex_register_file_ff.sv # generic FF-based + - rtl/ibex_register_file_fpga.sv # FPGA + - rtl/ibex_register_file_latch.sv # ASIC + - rtl/ibex_top.sv + file_type: systemVerilogSource + + files_lint_verilator: + files: + - lint/verilator_waiver.vlt: {file_type: vlt} + + files_lint_verible: + files: + - lint/verible_waiver.vbw: {file_type: veribleLintWaiver} + + files_check_tool_requirements: + depend: + - lowrisc:tool:check_tool_requirements + +parameters: + RVFI: + datatype: bool + paramtype: vlogdefine + + SYNTHESIS: + datatype: bool + paramtype: vlogdefine + + FPGA_XILINX: + datatype: bool + description: Identifies Xilinx FPGA targets to set DSP pragmas for performance counters. + default: false + paramtype: vlogdefine + + RV32E: + datatype: int + default: 0 + paramtype: vlogparam + + RV32M: + datatype: str + default: ibex_pkg::RV32MFast + paramtype: vlogdefine + description: "RV32M implementation parameter enum. See the ibex_pkg::rv32m_e enum in ibex_pkg.sv for permitted values." + + RV32B: + datatype: str + default: ibex_pkg::RV32BNone + paramtype: vlogdefine + description: "Bitmanip implementation parameter enum. See the ibex_pkg::rv32b_e enum in ibex_pkg.sv for permitted values." + + RegFile: + datatype: str + default: ibex_pkg::RegFileFF + paramtype: vlogdefine + description: "Register file implementation parameter enum. See the ibex_pkg::regfile_e enum in ibex_pkg.sv for permitted values." + + ICache: + datatype: int + default: 0 + paramtype: vlogparam + description: "Enable instruction cache" + + ICacheECC: + datatype: int + default: 0 + paramtype: vlogparam + description: "Enable ECC protection in instruction cache" + + BranchTargetALU: + datatype: int + default: 0 + paramtype: vlogparam + description: "Enables separate branch target ALU (increasing branch performance EXPERIMENTAL) [0/1]" + + WritebackStage: + datatype: int + default: 0 + paramtype: vlogparam + description: "Enables third pipeline stage (EXPERIMENTAL) [0/1]" + + BranchPredictor: + datatype: int + paramtype: vlogparam + default: 0 + description: "Enables static branch prediction (EXPERIMENTAL)" + + SecureIbex: + datatype: int + default: 0 + paramtype: vlogparam + description: "Enables security hardening features (EXPERIMENTAL) [0/1]" + + PMPEnable: + datatype: int + default: 0 + paramtype: vlogparam + description: "Enable PMP" + + PMPGranularity: + datatype: int + default: 0 + paramtype: vlogparam + description: "Granularity of NAPOT range, 0 = 4 byte, 1 = byte, 2 = 16 byte, 3 = 32 byte etc" + + PMPNumRegions: + datatype: int + default: 4 + paramtype: vlogparam + description: "Number of PMP regions" + +targets: + default: &default_target + filesets: + - tool_verilator ? (files_lint_verilator) + - tool_veriblelint ? (files_lint_verible) + - files_rtl + - files_check_tool_requirements + toplevel: ibex_top + parameters: + - tool_vivado ? (FPGA_XILINX=true) + lint: + <<: *default_target + parameters: + - SYNTHESIS=true + - RVFI=true + default_tool: verilator + tools: + verilator: + mode: lint-only + verilator_options: + - "-Wall" + # RAM primitives wider than 64bit (required for ECC) fail to build in + # Verilator without increasing the unroll count (see Verilator#1266) + - "--unroll-count 72" + format: + filesets: + - files_rtl + parameters: + - SYNTHESIS=true + - RVFI=true + default_tool: veribleformat + toplevel: ibex_top + tools: + veribleformat: + verible_format_args: + - "--inplace" + diff --git a/ibex_core_tracing.core b/ibex_top_tracing.core similarity index 95% rename from ibex_core_tracing.core rename to ibex_top_tracing.core index 8832f0df..a586d9e1 100644 --- a/ibex_core_tracing.core +++ b/ibex_top_tracing.core @@ -2,15 +2,15 @@ CAPI=2: # Copyright lowRISC contributors. # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -name: "lowrisc:ibex:ibex_core_tracing:0.1" +name: "lowrisc:ibex:ibex_top_tracing:0.1" description: "Ibex, a small RV32 CPU core with tracing enabled" filesets: files_rtl: depend: - - lowrisc:ibex:ibex_core + - lowrisc:ibex:ibex_top - lowrisc:ibex:ibex_tracer files: - - rtl/ibex_core_tracing.sv + - rtl/ibex_top_tracing.sv file_type: systemVerilogSource parameters: @@ -107,7 +107,7 @@ targets: - files_rtl parameters: - RVFI=true - toplevel: ibex_core_tracing + toplevel: ibex_top_tracing lint: <<: *default_target @@ -143,7 +143,7 @@ targets: - SYNTHESIS=true - RVFI=true default_tool: veribleformat - toplevel: ibex_core + toplevel: ibex_top_tracing tools: veribleformat: verible_format_args: diff --git a/lint/verilator_waiver.vlt b/lint/verilator_waiver.vlt index 929a9c80..c1a1092e 100644 --- a/lint/verilator_waiver.vlt +++ b/lint/verilator_waiver.vlt @@ -23,13 +23,13 @@ lint_off -rule PINCONNECTEMPTY // matches when you set a 1-bit value to a literal 1, so it won't hide // silly mistakes like setting it to 2. // -lint_off -rule WIDTH -file "*/rtl/ibex_core_tracing.sv" +lint_off -rule WIDTH -file "*/rtl/ibex_top_tracing.sv" -match "*expects 1 bits*Initial value's CONST '32'h1'*" // Operator expects 1 bit on initial value but initial value's CONST generates // 32 bits, need a specific RV32B waiver as it uses enums so the above catch-all // waiver doesn't work. -lint_off -rule WIDTH -file "*/rtl/ibex_core_tracing.sv" -match "*'RV32B'*" +lint_off -rule WIDTH -file "*/rtl/ibex_top_tracing.sv" -match "*'RV32B'*" // Bits of signal are not used: be_i[3:1] // Bits of signal are not used: addr_i[31:10,1:0] diff --git a/rtl/ibex_core.sv b/rtl/ibex_core.sv index a74448be..88d4745a 100644 --- a/rtl/ibex_core.sv +++ b/rtl/ibex_core.sv @@ -12,34 +12,36 @@ /** * Top level module of the ibex RISC-V core */ -module ibex_core #( - parameter bit PMPEnable = 1'b0, - parameter int unsigned PMPGranularity = 0, - parameter int unsigned PMPNumRegions = 4, - parameter int unsigned MHPMCounterNum = 0, - parameter int unsigned MHPMCounterWidth = 40, - parameter bit RV32E = 1'b0, - parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast, - parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone, - parameter ibex_pkg::regfile_e RegFile = ibex_pkg::RegFileFF, - parameter bit BranchTargetALU = 1'b0, - parameter bit WritebackStage = 1'b0, - parameter bit ICache = 1'b0, - parameter bit ICacheECC = 1'b0, - parameter bit BranchPredictor = 1'b0, - parameter bit DbgTriggerEn = 1'b0, - parameter int unsigned DbgHwBreakNum = 1, - parameter bit SecureIbex = 1'b0, - parameter int unsigned DmHaltAddr = 32'h1A110800, - parameter int unsigned DmExceptionAddr = 32'h1A110808 +module ibex_core import ibex_pkg::*; #( + parameter bit PMPEnable = 1'b0, + parameter int unsigned PMPGranularity = 0, + parameter int unsigned PMPNumRegions = 4, + parameter int unsigned MHPMCounterNum = 0, + parameter int unsigned MHPMCounterWidth = 40, + parameter bit RV32E = 1'b0, + parameter rv32m_e RV32M = RV32MFast, + parameter rv32b_e RV32B = RV32BNone, + parameter bit BranchTargetALU = 1'b0, + parameter bit WritebackStage = 1'b0, + parameter bit ICache = 1'b0, + parameter bit ICacheECC = 1'b0, + parameter int unsigned BusSizeECC = BUS_SIZE, + parameter int unsigned TagSizeECC = IC_TAG_SIZE, + parameter int unsigned LineSizeECC = IC_LINE_SIZE, + parameter bit BranchPredictor = 1'b0, + parameter bit DbgTriggerEn = 1'b0, + parameter int unsigned DbgHwBreakNum = 1, + parameter bit SecureIbex = 1'b0, + parameter bit DummyInstructions = 1'b0, + parameter bit RegFileECC = 1'b0, + parameter int unsigned RegFileDataWidth = 32, + parameter int unsigned DmHaltAddr = 32'h1A110800, + parameter int unsigned DmExceptionAddr = 32'h1A110808 ) ( // Clock and Reset input logic clk_i, input logic rst_ni, - input logic test_en_i, // enable all clock gates for testing - input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i, - input logic [31:0] hart_id_i, input logic [31:0] boot_addr_i, @@ -62,16 +64,39 @@ module ibex_core #( input logic [31:0] data_rdata_i, input logic data_err_i, + // Register file interface + output logic dummy_instr_id_o, + output logic [4:0] rf_raddr_a_o, + output logic [4:0] rf_raddr_b_o, + output logic [4:0] rf_waddr_wb_o, + output logic rf_we_wb_o, + output logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_o, + input logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_i, + input logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_i, + + // RAMs interface + output logic [IC_NUM_WAYS-1:0] ic_tag_req_o, + output logic ic_tag_write_o, + output logic [IC_INDEX_W-1:0] ic_tag_addr_o, + output logic [TagSizeECC-1:0] ic_tag_wdata_o, + input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS], + output logic [IC_NUM_WAYS-1:0] ic_data_req_o, + output logic ic_data_write_o, + output logic [IC_INDEX_W-1:0] ic_data_addr_o, + output logic [LineSizeECC-1:0] ic_data_wdata_o, + input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS], + // Interrupt inputs input logic irq_software_i, input logic irq_timer_i, input logic irq_external_i, input logic [14:0] irq_fast_i, input logic irq_nm_i, // non-maskeable interrupt + output logic irq_pending_o, // Debug Interface input logic debug_req_i, - output ibex_pkg::crash_dump_t crash_dump_o, + output crash_dump_t crash_dump_o, // RISC-V Formal Interface // Does not comply with the coding standards of _i/_o suffixes, but follows @@ -103,17 +128,13 @@ module ibex_core #( `endif // CPU Control Signals - input logic fetch_enable_i, output logic alert_minor_o, output logic alert_major_o, - output logic core_sleep_o + output logic core_busy_o ); - import ibex_pkg::*; - localparam int unsigned PMP_NUM_CHAN = 2; localparam bit DataIndTiming = SecureIbex; - localparam bit DummyInstructions = SecureIbex; localparam bit PCIncrCheck = SecureIbex; localparam bit ShadowCSR = SecureIbex; // Speculative branch option, trades-off performance against timing. @@ -121,8 +142,6 @@ module ibex_core #( // by ~3% (based on CoreMark/MHz score). // Set by default in the max PMP config which has the tightest budget for branch target timing. localparam bit SpecBranch = PMPEnable & (PMPNumRegions == 16); - localparam bit RegFileECC = SecureIbex; - localparam int unsigned RegFileDataWidth = RegFileECC ? 32 + 7 : 32; // IF/ID signals logic dummy_instr_id; @@ -179,7 +198,6 @@ module ibex_core #( logic ctrl_busy; logic if_busy; logic lsu_busy; - logic core_busy_d, core_busy_q; // Register File logic [4:0] rf_raddr_a; @@ -196,6 +214,7 @@ module ibex_core #( logic [31:0] rf_wdata_lsu; logic rf_we_wb; logic rf_we_lsu; + logic rf_ecc_err_comb; logic [4:0] rf_waddr_id; logic [31:0] rf_wdata_id; @@ -263,7 +282,6 @@ module ibex_core #( logic outstanding_store_wb; // Interrupts - logic irq_pending; logic nmi_mode; irqs_t irqs; logic csr_mstatus_mie; @@ -358,43 +376,9 @@ module ibex_core #( // Clock management // ////////////////////// - logic clk; - - logic clock_en; - // Before going to sleep, wait for I- and D-side // interfaces to finish ongoing operations. - assign core_busy_d = ctrl_busy | if_busy | lsu_busy; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - core_busy_q <= 1'b0; - end else begin - core_busy_q <= core_busy_d; - end - end - // capture fetch_enable_i in fetch_enable_q, once for ever - logic fetch_enable_q; - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fetch_enable_q <= 1'b0; - end else if (fetch_enable_i) begin - fetch_enable_q <= 1'b1; - end - end - - assign clock_en = fetch_enable_q & (core_busy_q | debug_req_i | irq_pending | irq_nm_i); - assign core_sleep_o = ~clock_en; - - // main clock gate of the core - // generates all clocks except the one for the debug unit which is - // independent - prim_clock_gating core_clock_gate_i ( - .clk_i ( clk_i ), - .en_i ( clock_en ), - .test_en_i ( test_en_i ), - .clk_o ( clk ) - ); + assign core_busy_o = ctrl_busy | if_busy | lsu_busy; ////////////// // IF stage // @@ -406,13 +390,15 @@ module ibex_core #( .DummyInstructions ( DummyInstructions ), .ICache ( ICache ), .ICacheECC ( ICacheECC ), + .BusSizeECC ( BusSizeECC ), + .TagSizeECC ( TagSizeECC ), + .LineSizeECC ( LineSizeECC ), .PCIncrCheck ( PCIncrCheck ), .BranchPredictor ( BranchPredictor ) ) if_stage_i ( - .clk_i ( clk ), + .clk_i ( clk_i ), .rst_ni ( rst_ni ), - .ram_cfg_i ( ram_cfg_i ), .boot_addr_i ( boot_addr_i ), .req_i ( instr_req_int ), // instruction request control @@ -425,6 +411,17 @@ module ibex_core #( .instr_err_i ( instr_err_i ), .instr_pmp_err_i ( pmp_req_err[PMP_I] ), + .ic_tag_req_o ( ic_tag_req_o ), + .ic_tag_write_o ( ic_tag_write_o ), + .ic_tag_addr_o ( ic_tag_addr_o ), + .ic_tag_wdata_o ( ic_tag_wdata_o ), + .ic_tag_rdata_i ( ic_tag_rdata_i ), + .ic_data_req_o ( ic_data_req_o ), + .ic_data_write_o ( ic_data_write_o ), + .ic_data_addr_o ( ic_data_addr_o ), + .ic_data_wdata_o ( ic_data_wdata_o ), + .ic_data_rdata_i ( ic_data_rdata_i ), + // outputs to ID stage .instr_valid_id_o ( instr_valid_id ), .instr_new_id_o ( instr_new_id ), @@ -492,7 +489,7 @@ module ibex_core #( .WritebackStage ( WritebackStage ), .BranchPredictor ( BranchPredictor ) ) id_stage_i ( - .clk_i ( clk ), + .clk_i ( clk_i ), .rst_ni ( rst_ni ), // Processor Enable @@ -586,7 +583,7 @@ module ibex_core #( // Interrupt Signals .csr_mstatus_mie_i ( csr_mstatus_mie ), - .irq_pending_i ( irq_pending ), + .irq_pending_i ( irq_pending_o ), .irqs_i ( irqs ), .irq_nm_i ( irq_nm_i ), .nmi_mode_o ( nmi_mode ), @@ -646,7 +643,7 @@ module ibex_core #( .RV32B ( RV32B ), .BranchTargetALU ( BranchTargetALU ) ) ex_block_i ( - .clk_i ( clk ), + .clk_i ( clk_i ), .rst_ni ( rst_ni ), // ALU signal from ID stage @@ -694,7 +691,7 @@ module ibex_core #( assign lsu_resp_err = lsu_load_err | lsu_store_err; ibex_load_store_unit load_store_unit_i ( - .clk_i ( clk ), + .clk_i ( clk_i ), .rst_ni ( rst_ni ), // data interface @@ -742,7 +739,7 @@ module ibex_core #( ibex_wb_stage #( .WritebackStage ( WritebackStage ) ) wb_stage_i ( - .clk_i ( clk ), + .clk_i ( clk_i ), .rst_ni ( rst_ni ), .en_wb_i ( en_wb ), .instr_type_wb_i ( instr_type_wb ), @@ -777,14 +774,15 @@ module ibex_core #( .instr_done_wb_o ( instr_done_wb ) ); - /////////////////////// - // Register file ECC // - /////////////////////// + ///////////////////////////// + // Register file interface // + ///////////////////////////// - logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc; - logic [RegFileDataWidth-1:0] rf_rdata_a_ecc; - logic [RegFileDataWidth-1:0] rf_rdata_b_ecc; - logic rf_ecc_err_comb; + assign dummy_instr_id_o = dummy_instr_id; + assign rf_raddr_a_o = rf_raddr_a; + assign rf_waddr_wb_o = rf_waddr_wb; + assign rf_we_wb_o = rf_we_wb; + assign rf_raddr_b_o = rf_raddr_b; if (RegFileECC) begin : gen_regfile_ecc @@ -794,26 +792,26 @@ module ibex_core #( // ECC checkbit generation for regiter file wdata prim_secded_39_32_enc regfile_ecc_enc ( .in (rf_wdata_wb), - .out (rf_wdata_wb_ecc) + .out (rf_wdata_wb_ecc_o) ); // ECC checking on register file rdata prim_secded_39_32_dec regfile_ecc_dec_a ( - .in (rf_rdata_a_ecc), + .in (rf_rdata_a_ecc_i), .d_o (), .syndrome_o (), .err_o (rf_ecc_err_a) ); prim_secded_39_32_dec regfile_ecc_dec_b ( - .in (rf_rdata_b_ecc), + .in (rf_rdata_b_ecc_i), .d_o (), .syndrome_o (), .err_o (rf_ecc_err_b) ); // Assign read outputs - no error correction, just trigger an alert - assign rf_rdata_a = rf_rdata_a_ecc[31:0]; - assign rf_rdata_b = rf_rdata_b_ecc[31:0]; + assign rf_rdata_a = rf_rdata_a_ecc_i[31:0]; + assign rf_rdata_b = rf_rdata_b_ecc_i[31:0]; // Calculate errors - qualify with WB forwarding to avoid xprop into the alert signal assign rf_ecc_err_a_id = |rf_ecc_err_a & rf_ren_a & ~rf_rd_a_wb_match; @@ -830,73 +828,12 @@ module ibex_core #( assign unused_rf_ren_b = rf_ren_b; assign unused_rf_rd_a_wb_match = rf_rd_a_wb_match; assign unused_rf_rd_b_wb_match = rf_rd_b_wb_match; - assign rf_wdata_wb_ecc = rf_wdata_wb; - assign rf_rdata_a = rf_rdata_a_ecc; - assign rf_rdata_b = rf_rdata_b_ecc; + assign rf_wdata_wb_ecc_o = rf_wdata_wb; + assign rf_rdata_a = rf_rdata_a_ecc_i; + assign rf_rdata_b = rf_rdata_b_ecc_i; assign rf_ecc_err_comb = 1'b0; end - if (RegFile == RegFileFF) begin : gen_regfile_ff - ibex_register_file_ff #( - .RV32E ( RV32E ), - .DataWidth ( RegFileDataWidth ), - .DummyInstructions ( DummyInstructions ) - ) register_file_i ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - - .test_en_i ( test_en_i ), - .dummy_instr_id_i ( dummy_instr_id ), - - .raddr_a_i ( rf_raddr_a ), - .rdata_a_o ( rf_rdata_a_ecc ), - .raddr_b_i ( rf_raddr_b ), - .rdata_b_o ( rf_rdata_b_ecc ), - .waddr_a_i ( rf_waddr_wb ), - .wdata_a_i ( rf_wdata_wb_ecc ), - .we_a_i ( rf_we_wb ) - ); - end else if (RegFile == RegFileFPGA) begin : gen_regfile_fpga - ibex_register_file_fpga #( - .RV32E ( RV32E ), - .DataWidth ( RegFileDataWidth ), - .DummyInstructions ( DummyInstructions ) - ) register_file_i ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - - .test_en_i ( test_en_i ), - .dummy_instr_id_i ( dummy_instr_id ), - - .raddr_a_i ( rf_raddr_a ), - .rdata_a_o ( rf_rdata_a_ecc ), - .raddr_b_i ( rf_raddr_b ), - .rdata_b_o ( rf_rdata_b_ecc ), - .waddr_a_i ( rf_waddr_wb ), - .wdata_a_i ( rf_wdata_wb_ecc ), - .we_a_i ( rf_we_wb ) - ); - end else if (RegFile == RegFileLatch) begin : gen_regfile_latch - ibex_register_file_latch #( - .RV32E ( RV32E ), - .DataWidth ( RegFileDataWidth ), - .DummyInstructions ( DummyInstructions ) - ) register_file_i ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - - .test_en_i ( test_en_i ), - .dummy_instr_id_i ( dummy_instr_id ), - - .raddr_a_i ( rf_raddr_a ), - .rdata_a_o ( rf_rdata_a_ecc ), - .raddr_b_i ( rf_raddr_b ), - .rdata_b_o ( rf_rdata_b_ecc ), - .waddr_a_i ( rf_waddr_wb ), - .wdata_a_i ( rf_wdata_wb_ecc ), - .we_a_i ( rf_we_wb ) - ); - end /////////////////////// // Crash dump output // @@ -993,7 +930,7 @@ module ibex_core #( .RV32M ( RV32M ), .RV32B ( RV32B ) ) cs_registers_i ( - .clk_i ( clk ), + .clk_i ( clk_i ), .rst_ni ( rst_ni ), // Hart ID from outside @@ -1021,7 +958,7 @@ module ibex_core #( .irq_external_i ( irq_external_i ), .irq_fast_i ( irq_fast_i ), .nmi_mode_i ( nmi_mode ), - .irq_pending_o ( irq_pending ), + .irq_pending_o ( irq_pending_o ), .irqs_o ( irqs ), .csr_mstatus_mie_o ( csr_mstatus_mie ), .csr_mstatus_tw_o ( csr_mstatus_tw ), @@ -1104,7 +1041,7 @@ module ibex_core #( .PMPNumChan ( PMP_NUM_CHAN ), .PMPNumRegions ( PMPNumRegions ) ) pmp_i ( - .clk_i ( clk ), + .clk_i ( clk_i ), .rst_ni ( rst_ni ), // Interface to CSRs .csr_pmp_cfg_i ( csr_pmp_cfg ), @@ -1212,7 +1149,7 @@ module ibex_core #( assign rvfi_instr_new_wb = rvfi_instr_new_wb_q; - always_ff @(posedge clk or negedge rst_ni) begin + always_ff @(posedge clk_i or negedge rst_ni) begin if (~rst_ni) begin rvfi_instr_new_wb_q <= 0; end else begin @@ -1229,7 +1166,7 @@ module ibex_core #( end for (genvar i = 0;i < RVFI_STAGES; i = i + 1) begin : g_rvfi_stages - always_ff @(posedge clk or negedge rst_ni) begin + always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin rvfi_stage_halt[i] <= '0; rvfi_stage_trap[i] <= '0; @@ -1338,7 +1275,7 @@ module ibex_core #( end end - always_ff @(posedge clk or negedge rst_ni) begin + always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin rvfi_mem_addr_q <= '0; rvfi_mem_rdata_q <= '0; @@ -1386,7 +1323,7 @@ module ibex_core #( rvfi_rs3_addr_d = rf_raddr_a; end end - always_ff @(posedge clk or negedge rst_ni) begin + always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin rvfi_rs1_data_q <= '0; rvfi_rs1_addr_q <= '0; @@ -1425,7 +1362,7 @@ module ibex_core #( // RD write register is refreshed only once per cycle and // then it is kept stable for the cycle. - always_ff @(posedge clk or negedge rst_ni) begin + always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin rvfi_rd_addr_q <= '0; rvfi_rd_wdata_q <= '0; @@ -1453,7 +1390,7 @@ module ibex_core #( end end - always_ff @(posedge clk or negedge rst_ni) begin + always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin rvfi_set_trap_pc_q <= 1'b0; rvfi_intr_q <= 1'b0; diff --git a/rtl/ibex_icache.sv b/rtl/ibex_icache.sv index 15bc2df9..77f1de2c 100644 --- a/rtl/ibex_icache.sv +++ b/rtl/ibex_icache.sv @@ -10,9 +10,12 @@ `include "prim_assert.sv" -module ibex_icache #( +module ibex_icache import ibex_pkg::*; #( parameter bit BranchPredictor = 1'b0, parameter bit ICacheECC = 1'b0, + parameter int unsigned BusSizeECC = BUS_SIZE, + parameter int unsigned TagSizeECC = IC_TAG_SIZE, + parameter int unsigned LineSizeECC = IC_LINE_SIZE, // Only cache branch targets parameter bit BranchCache = 1'b0 ) ( @@ -42,28 +45,33 @@ module ibex_icache #( output logic instr_req_o, input logic instr_gnt_i, output logic [31:0] instr_addr_o, - input logic [ibex_pkg::BUS_WIDTH-1:0] instr_rdata_i, + input logic [BUS_SIZE-1:0] instr_rdata_i, input logic instr_err_i, input logic instr_pmp_err_i, input logic instr_rvalid_i, + // RAM IO + output logic [IC_NUM_WAYS-1:0] ic_tag_req_o, + output logic ic_tag_write_o, + output logic [IC_INDEX_W-1:0] ic_tag_addr_o, + output logic [TagSizeECC-1:0] ic_tag_wdata_o, + input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS], + output logic [IC_NUM_WAYS-1:0] ic_data_req_o, + output logic ic_data_write_o, + output logic [IC_INDEX_W-1:0] ic_data_addr_o, + output logic [LineSizeECC-1:0] ic_data_wdata_o, + input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS], + // Cache status - input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i, input logic icache_enable_i, input logic icache_inval_i, output logic busy_o ); - import ibex_pkg::*; - // Number of fill buffers (must be >= 2) localparam int unsigned NUM_FB = 4; // Request throttling threshold localparam int unsigned FB_THRESHOLD = NUM_FB - 2; - // Derived parameters - localparam int unsigned BUS_SIZE_ECC = ICacheECC ? (BUS_WIDTH + 7) : BUS_WIDTH; - localparam int unsigned LINE_SIZE_ECC = BUS_SIZE_ECC * IC_LINE_BEATS; - localparam int unsigned TAG_SIZE_ECC = ICacheECC ? (IC_TAG_SIZE + 6) : IC_TAG_SIZE; // Prefetch signals logic [ADDR_W-1:0] lookup_addr_aligned; @@ -88,16 +96,16 @@ module ibex_icache #( logic [IC_INDEX_W-1:0] tag_index_ic0; logic [IC_NUM_WAYS-1:0] tag_banks_ic0; logic tag_write_ic0; - logic [TAG_SIZE_ECC-1:0] tag_wdata_ic0; + logic [TagSizeECC-1:0] tag_wdata_ic0; logic data_req_ic0; logic [IC_INDEX_W-1:0] data_index_ic0; logic [IC_NUM_WAYS-1:0] data_banks_ic0; logic data_write_ic0; - logic [LINE_SIZE_ECC-1:0] data_wdata_ic0; + logic [LineSizeECC-1:0] data_wdata_ic0; // Cache pipelipe IC1 signals - logic [TAG_SIZE_ECC-1:0] tag_rdata_ic1 [IC_NUM_WAYS]; - logic [LINE_SIZE_ECC-1:0] data_rdata_ic1 [IC_NUM_WAYS]; - logic [LINE_SIZE_ECC-1:0] hit_data_ecc_ic1; + logic [TagSizeECC-1:0] tag_rdata_ic1 [IC_NUM_WAYS]; + logic [LineSizeECC-1:0] data_rdata_ic1 [IC_NUM_WAYS]; + logic [LineSizeECC-1:0] hit_data_ecc_ic1; logic [IC_LINE_SIZE-1:0] hit_data_ic1; logic lookup_valid_ic1; logic [ADDR_W-1:IC_INDEX_HI+1] lookup_addr_ic1; @@ -307,8 +315,8 @@ module ibex_icache #( // Dataram ECC for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks prim_secded_39_32_enc data_ecc_enc ( - .in (fill_wdata_ic0[bank*BUS_WIDTH+:BUS_WIDTH]), - .out (data_wdata_ic0[bank*BUS_SIZE_ECC+:BUS_SIZE_ECC]) + .in (fill_wdata_ic0[bank*BUS_SIZE+:BUS_SIZE]), + .out (data_wdata_ic0[bank*BusSizeECC+:BusSizeECC]) ); end @@ -321,38 +329,23 @@ module ibex_icache #( // IC0 -> IC1 // //////////////// - for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_rams - // Tag RAM instantiation - prim_ram_1p #( - .Width (TAG_SIZE_ECC), - .Depth (IC_NUM_LINES), - .DataBitsPerMask (TAG_SIZE_ECC) - ) tag_bank ( - .clk_i (clk_i), - .req_i (tag_req_ic0 & tag_banks_ic0[way]), - .cfg_i (ram_cfg_i), - .write_i (tag_write_ic0), - .wmask_i ({TAG_SIZE_ECC{1'b1}}), - .addr_i (tag_index_ic0), - .wdata_i (tag_wdata_ic0), - .rdata_o (tag_rdata_ic1[way]) - ); - // Data RAM instantiation - prim_ram_1p #( - .Width (LINE_SIZE_ECC), - .Depth (IC_NUM_LINES), - .DataBitsPerMask (LINE_SIZE_ECC) - ) data_bank ( - .clk_i (clk_i), - .req_i (data_req_ic0 & data_banks_ic0[way]), - .cfg_i (ram_cfg_i), - .write_i (data_write_ic0), - .wmask_i ({LINE_SIZE_ECC{1'b1}}), - .addr_i (data_index_ic0), - .wdata_i (data_wdata_ic0), - .rdata_o (data_rdata_ic1[way]) - ); - end + // Tag RAMs outputs + assign ic_tag_req_o = {IC_NUM_WAYS{tag_req_ic0}} & tag_banks_ic0; + assign ic_tag_write_o = tag_write_ic0; + assign ic_tag_addr_o = tag_index_ic0; + assign ic_tag_wdata_o = tag_wdata_ic0; + + // Tag RAMs inputs + assign tag_rdata_ic1 = ic_tag_rdata_i; + + // Data RAMs outputs + assign ic_data_req_o = {IC_NUM_WAYS{data_req_ic0}} & data_banks_ic0; + assign ic_data_write_o = data_write_ic0; + assign ic_data_addr_o = data_index_ic0; + assign ic_data_wdata_o = data_wdata_ic0; + + // Data RAMs inputs + assign data_rdata_ic1 = ic_data_rdata_i; always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin @@ -427,7 +420,7 @@ module ibex_icache #( logic [27:0] tag_rdata_padded_ic1; // Expand the tag rdata with extra padding if the tag size is less than the maximum - assign tag_rdata_padded_ic1 = {tag_rdata_ic1[way][TAG_SIZE_ECC-1-:6], + assign tag_rdata_padded_ic1 = {tag_rdata_ic1[way][TagSizeECC-1-:6], {22-IC_TAG_SIZE{1'b0}}, tag_rdata_ic1[way][IC_TAG_SIZE-1:0]}; @@ -444,14 +437,14 @@ module ibex_icache #( // Note - could generate for all ways and mux after for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks prim_secded_39_32_dec data_ecc_dec ( - .in (hit_data_ecc_ic1[bank*BUS_SIZE_ECC+:BUS_SIZE_ECC]), + .in (hit_data_ecc_ic1[bank*BusSizeECC+:BusSizeECC]), .d_o (), .syndrome_o (), .err_o (data_err_ic1[bank*2+:2]) ); - assign hit_data_ic1[bank*BUS_WIDTH+:BUS_WIDTH] = - hit_data_ecc_ic1[bank*BUS_SIZE_ECC+:BUS_WIDTH]; + assign hit_data_ic1[bank*BUS_SIZE+:BUS_SIZE] = + hit_data_ecc_ic1[bank*BusSizeECC+:BUS_SIZE]; end @@ -817,7 +810,7 @@ module ibex_icache #( always_ff @(posedge clk_i) begin if (fill_data_en[fb][b]) begin - fill_data_q[fb][b*BUS_WIDTH+:BUS_WIDTH] <= fill_data_d[fb][b*BUS_WIDTH+:BUS_WIDTH]; + fill_data_q[fb][b*BUS_SIZE+:BUS_SIZE] <= fill_data_d[fb][b*BUS_SIZE+:BUS_SIZE]; end end @@ -983,7 +976,7 @@ module ibex_icache #( end end - // Mux the data from BUS_WIDTH to halfword + // Mux the data from BUS_SIZE to halfword // This muxing realigns data when instruction words are split across BUS_W e.g. // word 1 |----|*h1*| // word 0 |*h0*|----| --> |*h1*|*h0*| @@ -1061,7 +1054,7 @@ module ibex_icache #( // ECC primitives will need to be changed for different sizes `ASSERT_INIT(ecc_tag_param_legal, (IC_TAG_SIZE <= 27)) - `ASSERT_INIT(ecc_data_param_legal, !ICacheECC || (BUS_WIDTH == 32)) + `ASSERT_INIT(ecc_data_param_legal, !ICacheECC || (BUS_SIZE == 32)) // Lookups in the tag ram should always give a known result `ASSERT_KNOWN(TagHitKnown, lookup_valid_ic1 & tag_hit_ic1) diff --git a/rtl/ibex_if_stage.sv b/rtl/ibex_if_stage.sv index 2c491750..8bd0efee 100644 --- a/rtl/ibex_if_stage.sv +++ b/rtl/ibex_if_stage.sv @@ -12,19 +12,21 @@ `include "prim_assert.sv" -module ibex_if_stage #( +module ibex_if_stage import ibex_pkg::*; #( parameter int unsigned DmHaltAddr = 32'h1A110800, parameter int unsigned DmExceptionAddr = 32'h1A110808, parameter bit DummyInstructions = 1'b0, parameter bit ICache = 1'b0, parameter bit ICacheECC = 1'b0, + parameter int unsigned BusSizeECC = BUS_SIZE, + parameter int unsigned TagSizeECC = IC_TAG_SIZE, + parameter int unsigned LineSizeECC = IC_LINE_SIZE, parameter bit PCIncrCheck = 1'b0, parameter bit BranchPredictor = 1'b0 ) ( input logic clk_i, input logic rst_ni, - input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i, input logic [31:0] boot_addr_i, // also used for mtvec input logic req_i, // instruction request control @@ -37,6 +39,18 @@ module ibex_if_stage #( input logic instr_err_i, input logic instr_pmp_err_i, + // ICache RAM IO + output logic [IC_NUM_WAYS-1:0] ic_tag_req_o, + output logic ic_tag_write_o, + output logic [IC_INDEX_W-1:0] ic_tag_addr_o, + output logic [TagSizeECC-1:0] ic_tag_wdata_o, + input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS], + output logic [IC_NUM_WAYS-1:0] ic_data_req_o, + output logic ic_data_write_o, + output logic [IC_INDEX_W-1:0] ic_data_addr_o, + output logic [LineSizeECC-1:0] ic_data_wdata_o, + input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS], + // output of ID stage output logic instr_valid_id_o, // instr in IF-ID is valid output logic instr_new_id_o, // instr in IF-ID is new @@ -45,7 +59,7 @@ module ibex_if_stage #( // to reduce fan-out output logic [15:0] instr_rdata_c_id_o, // compressed instr for ID stage // (mtval), meaningful only if - // instr_is_compressed_id_o = 1'b1 + // instr_is_compressed_id_o = 1'b1 output logic instr_is_compressed_id_o, // compressed decoder thinks this // is a compressed instr output logic instr_bp_taken_o, // instruction was predicted to be @@ -62,11 +76,11 @@ module ibex_if_stage #( input logic instr_valid_clear_i, // clear instr valid bit in IF-ID input logic pc_set_i, // set the PC to a new value input logic pc_set_spec_i, - input ibex_pkg::pc_sel_e pc_mux_i, // selector for PC multiplexer + input pc_sel_e pc_mux_i, // selector for PC multiplexer input logic nt_branch_mispredict_i, // Not-taken branch in ID/EX was // mispredicted (predicted taken) - input ibex_pkg::exc_pc_sel_e exc_pc_mux_i, // selects ISR address - input ibex_pkg::exc_cause_e exc_cause, // selects ISR address for + input exc_pc_sel_e exc_pc_mux_i, // selects ISR address + input exc_cause_e exc_cause, // selects ISR address for // vectorized interrupt lines input logic dummy_instr_en_i, input logic [2:0] dummy_instr_mask_i, @@ -94,8 +108,6 @@ module ibex_if_stage #( output logic if_busy_o // IF stage is busy fetching instr ); - import ibex_pkg::*; - logic instr_valid_id_d, instr_valid_id_q; logic instr_new_id_d, instr_new_id_q; @@ -186,7 +198,10 @@ module ibex_if_stage #( // Full I-Cache option ibex_icache #( .BranchPredictor (BranchPredictor), - .ICacheECC (ICacheECC) + .ICacheECC (ICacheECC), + .BusSizeECC (BusSizeECC), + .TagSizeECC (TagSizeECC), + .LineSizeECC (LineSizeECC) ) icache_i ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), @@ -214,7 +229,17 @@ module ibex_if_stage #( .instr_err_i ( instr_err_i ), .instr_pmp_err_i ( instr_pmp_err_i ), - .ram_cfg_i ( ram_cfg_i ), + .ic_tag_req_o ( ic_tag_req_o ), + .ic_tag_write_o ( ic_tag_write_o ), + .ic_tag_addr_o ( ic_tag_addr_o ), + .ic_tag_wdata_o ( ic_tag_wdata_o ), + .ic_tag_rdata_i ( ic_tag_rdata_i ), + .ic_data_req_o ( ic_data_req_o ), + .ic_data_write_o ( ic_data_write_o ), + .ic_data_addr_o ( ic_data_addr_o ), + .ic_data_wdata_o ( ic_data_wdata_o ), + .ic_data_rdata_i ( ic_data_rdata_i ), + .icache_enable_i ( icache_enable_i ), .icache_inval_i ( icache_inval_i ), .busy_o ( prefetch_busy ) @@ -253,11 +278,21 @@ module ibex_if_stage #( .busy_o ( prefetch_busy ) ); // ICache tieoffs - logic unused_icen, unused_icinv; - prim_ram_1p_pkg::ram_1p_cfg_t unused_ram_cfg; - assign unused_icen = icache_enable_i; - assign unused_icinv = icache_inval_i; - assign unused_ram_cfg = ram_cfg_i; + logic unused_icen, unused_icinv; + logic [TagSizeECC-1:0] unused_tag_ram_input [IC_NUM_WAYS]; + logic [LineSizeECC-1:0] unused_data_ram_input [IC_NUM_WAYS]; + assign unused_icen = icache_enable_i; + assign unused_icinv = icache_inval_i; + assign unused_tag_ram_input = ic_tag_rdata_i; + assign unused_data_ram_input = ic_data_rdata_i; + assign ic_tag_req_o = 'b0; + assign ic_tag_write_o = 'b0; + assign ic_tag_addr_o = 'b0; + assign ic_tag_wdata_o = 'b0; + assign ic_data_req_o = 'b0; + assign ic_data_write_o = 'b0; + assign ic_data_addr_o = 'b0; + assign ic_data_wdata_o = 'b0; end assign unused_fetch_addr_n0 = fetch_addr_n[0]; diff --git a/rtl/ibex_pkg.sv b/rtl/ibex_pkg.sv index 321a8923..bc4a8515 100644 --- a/rtl/ibex_pkg.sv +++ b/rtl/ibex_pkg.sv @@ -19,6 +19,14 @@ typedef struct packed { logic [31:0] exception_addr; } crash_dump_t; +typedef struct packed { + logic dummy_instr_id; + logic [4:0] raddr_a; + logic [4:0] waddr_a; + logic we_a; + logic [4:0] raddr_b; +} core2rf_t; + ///////////////////// // Parameter Enums // ///////////////////// diff --git a/rtl/ibex_top.sv b/rtl/ibex_top.sv new file mode 100644 index 00000000..75dae333 --- /dev/null +++ b/rtl/ibex_top.sv @@ -0,0 +1,411 @@ +// Copyright lowRISC contributors. +// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`ifdef RISCV_FORMAL + `define RVFI +`endif + +/** + * Top level module of the ibex RISC-V core + */ +module ibex_top #( + parameter bit PMPEnable = 1'b0, + parameter int unsigned PMPGranularity = 0, + parameter int unsigned PMPNumRegions = 4, + parameter int unsigned MHPMCounterNum = 0, + parameter int unsigned MHPMCounterWidth = 40, + parameter bit RV32E = 1'b0, + parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast, + parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone, + parameter ibex_pkg::regfile_e RegFile = ibex_pkg::RegFileFF, + parameter bit BranchTargetALU = 1'b0, + parameter bit WritebackStage = 1'b0, + parameter bit ICache = 1'b0, + parameter bit ICacheECC = 1'b0, + parameter bit BranchPredictor = 1'b0, + parameter bit DbgTriggerEn = 1'b0, + parameter int unsigned DbgHwBreakNum = 1, + parameter bit SecureIbex = 1'b0, + parameter int unsigned DmHaltAddr = 32'h1A110800, + parameter int unsigned DmExceptionAddr = 32'h1A110808 +) ( + // Clock and Reset + input logic clk_i, + input logic rst_ni, + + input logic test_en_i, // enable all clock gates for testing + input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i, + + input logic [31:0] hart_id_i, + input logic [31:0] boot_addr_i, + + // Instruction memory interface + output logic instr_req_o, + input logic instr_gnt_i, + input logic instr_rvalid_i, + output logic [31:0] instr_addr_o, + input logic [31:0] instr_rdata_i, + input logic instr_err_i, + + // Data memory interface + output logic data_req_o, + input logic data_gnt_i, + input logic data_rvalid_i, + output logic data_we_o, + output logic [3:0] data_be_o, + output logic [31:0] data_addr_o, + output logic [31:0] data_wdata_o, + input logic [31:0] data_rdata_i, + input logic data_err_i, + + // Interrupt inputs + input logic irq_software_i, + input logic irq_timer_i, + input logic irq_external_i, + input logic [14:0] irq_fast_i, + input logic irq_nm_i, // non-maskeable interrupt + + // Debug Interface + input logic debug_req_i, + output ibex_pkg::crash_dump_t crash_dump_o, + + // RISC-V Formal Interface + // Does not comply with the coding standards of _i/_o suffixes, but follows + // the convention of RISC-V Formal Interface Specification. +`ifdef RVFI + output logic rvfi_valid, + output logic [63:0] rvfi_order, + output logic [31:0] rvfi_insn, + output logic rvfi_trap, + output logic rvfi_halt, + output logic rvfi_intr, + output logic [ 1:0] rvfi_mode, + output logic [ 1:0] rvfi_ixl, + output logic [ 4:0] rvfi_rs1_addr, + output logic [ 4:0] rvfi_rs2_addr, + output logic [ 4:0] rvfi_rs3_addr, + output logic [31:0] rvfi_rs1_rdata, + output logic [31:0] rvfi_rs2_rdata, + output logic [31:0] rvfi_rs3_rdata, + output logic [ 4:0] rvfi_rd_addr, + output logic [31:0] rvfi_rd_wdata, + output logic [31:0] rvfi_pc_rdata, + output logic [31:0] rvfi_pc_wdata, + output logic [31:0] rvfi_mem_addr, + output logic [ 3:0] rvfi_mem_rmask, + output logic [ 3:0] rvfi_mem_wmask, + output logic [31:0] rvfi_mem_rdata, + output logic [31:0] rvfi_mem_wdata, +`endif + + // CPU Control Signals + input logic fetch_enable_i, + output logic alert_minor_o, + output logic alert_major_o, + output logic core_sleep_o +); + + import ibex_pkg::*; + + localparam bit DummyInstructions = SecureIbex; + localparam bit RegFileECC = SecureIbex; + localparam int unsigned RegFileDataWidth = RegFileECC ? 32 + 7 : 32; + // Icache parameters + localparam int unsigned BusSizeECC = ICacheECC ? (BUS_SIZE + 7) : BUS_SIZE; + localparam int unsigned LineSizeECC = BusSizeECC * IC_LINE_BEATS; + localparam int unsigned TagSizeECC = ICacheECC ? (IC_TAG_SIZE + 6) : IC_TAG_SIZE; + + // Clock signals + logic clk; + logic core_busy_d, core_busy_q; + logic fetch_enable_q; + logic clock_en; + logic irq_pending; + // Core <-> Register file signals + logic dummy_instr_id; + logic [4:0] rf_raddr_a; + logic [4:0] rf_raddr_b; + logic [4:0] rf_waddr_wb; + logic rf_we_wb; + logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc; + logic [RegFileDataWidth-1:0] rf_rdata_a_ecc; + logic [RegFileDataWidth-1:0] rf_rdata_b_ecc; + // Core <-> RAMs signals + logic [IC_NUM_WAYS-1:0] ic_tag_req; + logic ic_tag_write; + logic [IC_INDEX_W-1:0] ic_tag_addr; + logic [TagSizeECC-1:0] ic_tag_wdata; + logic [TagSizeECC-1:0] ic_tag_rdata [IC_NUM_WAYS]; + logic [IC_NUM_WAYS-1:0] ic_data_req; + logic ic_data_write; + logic [IC_INDEX_W-1:0] ic_data_addr; + logic [LineSizeECC-1:0] ic_data_wdata; + logic [LineSizeECC-1:0] ic_data_rdata [IC_NUM_WAYS]; + + ///////////////////// + // Main clock gate // + ///////////////////// + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + core_busy_q <= 1'b0; + end else begin + core_busy_q <= core_busy_d; + end + end + + // capture fetch_enable_i in fetch_enable_q, once for ever + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + fetch_enable_q <= 1'b0; + end else if (fetch_enable_i) begin + fetch_enable_q <= 1'b1; + end + end + + assign clock_en = fetch_enable_q & (core_busy_q | debug_req_i | irq_pending | irq_nm_i); + assign core_sleep_o = ~clock_en; + + prim_clock_gating core_clock_gate_i ( + .clk_i ( clk_i ), + .en_i ( clock_en ), + .test_en_i ( test_en_i ), + .clk_o ( clk ) + ); + + //////////////////////// + // Core instantiation // + //////////////////////// + + ibex_core #( + .PMPEnable ( PMPEnable ), + .PMPGranularity ( PMPGranularity ), + .PMPNumRegions ( PMPNumRegions ), + .MHPMCounterNum ( MHPMCounterNum ), + .MHPMCounterWidth ( MHPMCounterWidth ), + .RV32E ( RV32E ), + .RV32M ( RV32M ), + .RV32B ( RV32B ), + .BranchTargetALU ( BranchTargetALU ), + .ICache ( ICache ), + .ICacheECC ( ICacheECC ), + .BusSizeECC ( BusSizeECC ), + .TagSizeECC ( TagSizeECC ), + .LineSizeECC ( LineSizeECC ), + .BranchPredictor ( BranchPredictor ), + .DbgTriggerEn ( DbgTriggerEn ), + .DbgHwBreakNum ( DbgHwBreakNum ), + .WritebackStage ( WritebackStage ), + .SecureIbex ( SecureIbex ), + .DummyInstructions ( DummyInstructions ), + .RegFileECC ( RegFileECC ), + .RegFileDataWidth ( RegFileDataWidth ), + .DmHaltAddr ( DmHaltAddr ), + .DmExceptionAddr ( DmExceptionAddr ) + ) u_ibex_core ( + .clk_i (clk), + .rst_ni, + + .hart_id_i, + .boot_addr_i, + + .instr_req_o, + .instr_gnt_i, + .instr_rvalid_i, + .instr_addr_o, + .instr_rdata_i, + .instr_err_i, + + .data_req_o, + .data_gnt_i, + .data_rvalid_i, + .data_we_o, + .data_be_o, + .data_addr_o, + .data_wdata_o, + .data_rdata_i, + .data_err_i, + + .dummy_instr_id_o (dummy_instr_id), + .rf_raddr_a_o (rf_raddr_a), + .rf_raddr_b_o (rf_raddr_b), + .rf_waddr_wb_o (rf_waddr_wb), + .rf_we_wb_o (rf_we_wb), + .rf_wdata_wb_ecc_o (rf_wdata_wb_ecc), + .rf_rdata_a_ecc_i (rf_rdata_a_ecc), + .rf_rdata_b_ecc_i (rf_rdata_b_ecc), + + .ic_tag_req_o (ic_tag_req), + .ic_tag_write_o (ic_tag_write), + .ic_tag_addr_o (ic_tag_addr), + .ic_tag_wdata_o (ic_tag_wdata), + .ic_tag_rdata_i (ic_tag_rdata), + .ic_data_req_o (ic_data_req), + .ic_data_write_o (ic_data_write), + .ic_data_addr_o (ic_data_addr), + .ic_data_wdata_o (ic_data_wdata), + .ic_data_rdata_i (ic_data_rdata), + + .irq_software_i, + .irq_timer_i, + .irq_external_i, + .irq_fast_i, + .irq_nm_i, + .irq_pending_o (irq_pending), + + .debug_req_i, + .crash_dump_o, + +`ifdef RVFI + .rvfi_valid, + .rvfi_order, + .rvfi_insn, + .rvfi_trap, + .rvfi_halt, + .rvfi_intr, + .rvfi_mode, + .rvfi_ixl, + .rvfi_rs1_addr, + .rvfi_rs2_addr, + .rvfi_rs3_addr, + .rvfi_rs1_rdata, + .rvfi_rs2_rdata, + .rvfi_rs3_rdata, + .rvfi_rd_addr, + .rvfi_rd_wdata, + .rvfi_pc_rdata, + .rvfi_pc_wdata, + .rvfi_mem_addr, + .rvfi_mem_rmask, + .rvfi_mem_wmask, + .rvfi_mem_rdata, + .rvfi_mem_wdata, +`endif + + .alert_minor_o, + .alert_major_o, + .core_busy_o (core_busy_d) + ); + + ///////////////////////////////// + // Register file Instantiation // + ///////////////////////////////// + + if (RegFile == RegFileFF) begin : gen_regfile_ff + ibex_register_file_ff #( + .RV32E ( RV32E ), + .DataWidth ( RegFileDataWidth ), + .DummyInstructions ( DummyInstructions ) + ) register_file_i ( + .clk_i ( clk ), + .rst_ni ( rst_ni ), + + .test_en_i ( test_en_i ), + .dummy_instr_id_i ( dummy_instr_id ), + + .raddr_a_i ( rf_raddr_a ), + .rdata_a_o ( rf_rdata_a_ecc ), + .raddr_b_i ( rf_raddr_b ), + .rdata_b_o ( rf_rdata_b_ecc ), + .waddr_a_i ( rf_waddr_wb ), + .wdata_a_i ( rf_wdata_wb_ecc ), + .we_a_i ( rf_we_wb ) + ); + end else if (RegFile == RegFileFPGA) begin : gen_regfile_fpga + ibex_register_file_fpga #( + .RV32E ( RV32E ), + .DataWidth ( RegFileDataWidth ), + .DummyInstructions ( DummyInstructions ) + ) register_file_i ( + .clk_i ( clk ), + .rst_ni ( rst_ni ), + + .test_en_i ( test_en_i ), + .dummy_instr_id_i ( dummy_instr_id ), + + .raddr_a_i ( rf_raddr_a ), + .rdata_a_o ( rf_rdata_a_ecc ), + .raddr_b_i ( rf_raddr_b ), + .rdata_b_o ( rf_rdata_b_ecc ), + .waddr_a_i ( rf_waddr_wb ), + .wdata_a_i ( rf_wdata_wb_ecc ), + .we_a_i ( rf_we_wb ) + ); + end else if (RegFile == RegFileLatch) begin : gen_regfile_latch + ibex_register_file_latch #( + .RV32E ( RV32E ), + .DataWidth ( RegFileDataWidth ), + .DummyInstructions ( DummyInstructions ) + ) register_file_i ( + .clk_i ( clk ), + .rst_ni ( rst_ni ), + + .test_en_i ( test_en_i ), + .dummy_instr_id_i ( dummy_instr_id ), + + .raddr_a_i ( rf_raddr_a ), + .rdata_a_o ( rf_rdata_a_ecc ), + .raddr_b_i ( rf_raddr_b ), + .rdata_b_o ( rf_rdata_b_ecc ), + .waddr_a_i ( rf_waddr_wb ), + .wdata_a_i ( rf_wdata_wb_ecc ), + .we_a_i ( rf_we_wb ) + ); + end + + //////////////////////// + // Rams Instantiation // + //////////////////////// + + if (ICache) begin : gen_rams + + for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_rams + // Tag RAM instantiation + prim_ram_1p #( + .Width (TagSizeECC), + .Depth (IC_NUM_LINES), + .DataBitsPerMask (TagSizeECC) + ) tag_bank ( + .clk_i (clk_i), + .req_i (ic_tag_req[way]), + .cfg_i (ram_cfg_i), + .write_i (ic_tag_write), + .wmask_i ({TagSizeECC{1'b1}}), + .addr_i (ic_tag_addr), + .wdata_i (ic_tag_wdata), + .rdata_o (ic_tag_rdata[way]) + ); + // Data RAM instantiation + prim_ram_1p #( + .Width (LineSizeECC), + .Depth (IC_NUM_LINES), + .DataBitsPerMask (LineSizeECC) + ) data_bank ( + .clk_i (clk_i), + .req_i (ic_data_req[way]), + .cfg_i (ram_cfg_i), + .write_i (ic_data_write), + .wmask_i ({LineSizeECC{1'b1}}), + .addr_i (ic_data_addr), + .wdata_i (ic_data_wdata), + .rdata_o (ic_data_rdata[way]) + ); + end + + end else begin : gen_norams + + prim_ram_1p_pkg::ram_1p_cfg_t unused_ram_cfg; + logic unused_ram_inputs; + + assign unused_ram_cfg = ram_cfg_i; + assign unused_ram_inputs = 1'b0 & (|ic_tag_req) & ic_tag_write & (|ic_tag_addr) & + (|ic_tag_wdata) & (|ic_data_req) & ic_data_write & (|ic_data_addr) & + (|ic_data_wdata); + assign ic_tag_rdata = '{default:'b0}; + assign ic_data_rdata = '{default:'b0}; + + end + +endmodule diff --git a/rtl/ibex_core_tracing.sv b/rtl/ibex_top_tracing.sv similarity index 99% rename from rtl/ibex_core_tracing.sv rename to rtl/ibex_top_tracing.sv index d921ef71..b777ea96 100644 --- a/rtl/ibex_core_tracing.sv +++ b/rtl/ibex_top_tracing.sv @@ -6,7 +6,7 @@ * Top level module of the ibex RISC-V core with tracing enabled */ -module ibex_core_tracing #( +module ibex_top_tracing #( parameter bit PMPEnable = 1'b0, parameter int unsigned PMPGranularity = 0, parameter int unsigned PMPNumRegions = 4, @@ -107,7 +107,7 @@ module ibex_core_tracing #( logic [31:0] rvfi_mem_rdata; logic [31:0] rvfi_mem_wdata; - ibex_core #( + ibex_top #( .PMPEnable ( PMPEnable ), .PMPGranularity ( PMPGranularity ), .PMPNumRegions ( PMPNumRegions ), @@ -127,7 +127,7 @@ module ibex_core_tracing #( .SecureIbex ( SecureIbex ), .DmHaltAddr ( DmHaltAddr ), .DmExceptionAddr ( DmExceptionAddr ) - ) u_ibex_core ( + ) u_ibex_top ( .clk_i, .rst_ni, diff --git a/syn/README.md b/syn/README.md index cfb248c0..4f2a37b2 100644 --- a/syn/README.md +++ b/syn/README.md @@ -72,10 +72,10 @@ flow. All outputs are placed under the `syn/syn_out` directory with the prefix - sta.log - Log of the OpenSTA run - `generated` - *.v - Ibex RTL after sv2v processing - - ibex_core.pre_map.v - Pre-mapping synthesis netlists - - ibex_core_netlist.v - Post-synthesis netlist - - ibex_core_netlist.sta.v - Post-synthesis netlist usable by OpenSTA - - ibex_core.[library-name].out.sdc - Generated .sdc timing constraints + - ibex_top.pre_map.v - Pre-mapping synthesis netlists + - ibex_top_netlist.v - Post-synthesis netlist + - ibex_top_netlist.sta.v - Post-synthesis netlist usable by OpenSTA + - ibex_top.[library-name].out.sdc - Generated .sdc timing constraints file If you wish to change the results directory naming or location edit @@ -86,7 +86,7 @@ If you wish to change the results directory naming or location edit Two files specify the timing constraints and timing related settings for the flow. These are used to generate a single .sdc file -* `ibex_core_lr_synth_core.tcl` - This specifies the constraints on all inputs +* `ibex_top_lr_synth_core.tcl` - This specifies the constraints on all inputs and outputs as a fraction of a clock cycle, the names of the clock and reset inputs and the desired clock period in ps * `ibex.[library-name].sdc` - Header to include in generated .sdc file. Settings diff --git a/syn/ibex_core.nangate.sdc b/syn/ibex_top.nangate.sdc similarity index 100% rename from syn/ibex_core.nangate.sdc rename to syn/ibex_top.nangate.sdc diff --git a/syn/ibex_core_abc.nangate.sdc b/syn/ibex_top_abc.nangate.sdc similarity index 100% rename from syn/ibex_core_abc.nangate.sdc rename to syn/ibex_top_abc.nangate.sdc diff --git a/syn/ibex_core_lr_synth_conf.tcl b/syn/ibex_top_lr_synth_conf.tcl similarity index 100% rename from syn/ibex_core_lr_synth_conf.tcl rename to syn/ibex_top_lr_synth_conf.tcl diff --git a/syn/lec_sv2v.sh b/syn/lec_sv2v.sh index ba89dc39..df73b681 100755 --- a/syn/lec_sv2v.sh +++ b/syn/lec_sv2v.sh @@ -23,7 +23,7 @@ #------------------------------------------------------------------------- rm -Rf build lec_out fusesoc --cores-root .. run --tool=icarus --target=lint \ - --setup "lowrisc:ibex:ibex_core" > /dev/null 2>&1 + --setup "lowrisc:ibex:ibex_top" > /dev/null 2>&1 # copy all files to lec_out mkdir lec_out diff --git a/syn/syn_yosys.sh b/syn/syn_yosys.sh index 9156a486..bbfd24cb 100755 --- a/syn/syn_yosys.sh +++ b/syn/syn_yosys.sh @@ -47,8 +47,9 @@ for file in ../rtl/*.sv; do sv2v \ --define=SYNTHESIS \ ../rtl/*_pkg.sv \ + ../vendor/lowrisc_ip/ip/prim/rtl/prim_ram_1p_pkg.sv \ -I../vendor/lowrisc_ip/ip/prim/rtl \ - -I../dv/fcov \ + -I../vendor/lowrisc_ip/dv/sv/dv_utils \ $file \ > $LR_SYNTH_OUT_DIR/generated/${module}.v done diff --git a/syn/tcl/lr_synth_flow_var_setup.tcl b/syn/tcl/lr_synth_flow_var_setup.tcl index 8e2dd105..303852f8 100644 --- a/syn/tcl/lr_synth_flow_var_setup.tcl +++ b/syn/tcl/lr_synth_flow_var_setup.tcl @@ -5,7 +5,7 @@ puts "=================== Flow Vars ===================" set_flow_var cell_library_path "cmos_cells.lib" "Path to cell library" -set_flow_var top_module "ibex_core" "top module" +set_flow_var top_module "ibex_top" "top module" set_flow_var out_dir "syn_out" "Output directory for synthesis" set_flow_var pre_map_out "./${lr_synth_out_dir}/generated/${lr_synth_top_module}.pre_map.v" "Pre-mapping netlist out" set_flow_var netlist_out "./${lr_synth_out_dir}/generated/${lr_synth_top_module}_netlist.v" "netlist out" diff --git a/syn/tcl/yosys_run_synth.tcl b/syn/tcl/yosys_run_synth.tcl index 7986f327..898d6241 100644 --- a/syn/tcl/yosys_run_synth.tcl +++ b/syn/tcl/yosys_run_synth.tcl @@ -17,18 +17,18 @@ if { $lr_synth_timing_run } { yosys "read_verilog -sv ./rtl/prim_clock_gating.v $lr_synth_out_dir/generated/*.v" if { $lr_synth_ibex_branch_target_alu } { - yosys "chparam -set BranchTargetALU 1 ibex_core" + yosys "chparam -set BranchTargetALU 1 $lr_synth_top_module" } if { $lr_synth_ibex_writeback_stage } { - yosys "chparam -set WritebackStage 1 ibex_core" + yosys "chparam -set WritebackStage 1 $lr_synth_top_module" } -yosys "chparam -set RV32B $lr_synth_ibex_bitmanip ibex_core" +yosys "chparam -set RV32B $lr_synth_ibex_bitmanip $lr_synth_top_module" -yosys "chparam -set RV32M $lr_synth_ibex_multiplier ibex_core" +yosys "chparam -set RV32M $lr_synth_ibex_multiplier $lr_synth_top_module" -yosys "chparam -set RegFile $lr_synth_ibex_regfile ibex_core" +yosys "chparam -set RegFile $lr_synth_ibex_regfile $lr_synth_top_module" yosys "synth $flatten_opt -top $lr_synth_top_module" yosys "opt -purge" diff --git a/syn/translate_timing_rpts.sh b/syn/translate_timing_rpts.sh index 3396a413..10ffe808 100755 --- a/syn/translate_timing_rpts.sh +++ b/syn/translate_timing_rpts.sh @@ -4,7 +4,7 @@ # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -./python/build_translated_names.py ibex_core ./$LR_SYNTH_OUT_DIR/generated ./$LR_SYNTH_OUT_DIR/reports/timing/*.csv.rpt +./python/build_translated_names.py ibex_top ./$LR_SYNTH_OUT_DIR/generated ./$LR_SYNTH_OUT_DIR/reports/timing/*.csv.rpt for file in ./$LR_SYNTH_OUT_DIR/reports/timing/*.csv.rpt; do ./python/translate_timing_csv.py $file ./$LR_SYNTH_OUT_DIR/generated