Integrate PLIC

This commit is contained in:
Florian Zaruba 2018-09-24 18:03:25 +02:00
parent ab5b5dd670
commit b686a406a8
No known key found for this signature in database
GPG key ID: E742FFE8EC38A792
15 changed files with 540 additions and 192 deletions

3
.gitmodules vendored
View file

@ -13,3 +13,6 @@
[submodule "src/axi"]
path = src/axi
url = https://github.com/pulp-platform/axi.git
[submodule "src/register_interface"]
path = src/register_interface
url = https://github.com/pulp-platform/register_interface.git

View file

@ -24,12 +24,14 @@ target-options ?=
defines ?=
# Sources
# Package files -> compile first
ariane_pkg := include/riscv_pkg.sv \
src/debug/dm_pkg.sv \
include/ariane_pkg.sv \
include/std_cache_pkg.sv \
src/axi/src/axi_pkg.sv \
include/axi_intf.sv
ariane_pkg := include/riscv_pkg.sv \
src/debug/dm_pkg.sv \
include/ariane_pkg.sv \
include/std_cache_pkg.sv \
src/axi/src/axi_pkg.sv \
include/axi_intf.sv \
tb/ariane_soc_pkg.sv \
src/register_interface/src/reg_intf.sv
# utility modules
util := $(wildcard src/util/*.svh) \
@ -50,10 +52,13 @@ src := $(filter-out src/ariane_regfile.sv, $(wildcard src/*.sv)) \
$(wildcard src/cache_subsystem/*.sv) \
$(wildcard bootrom/*.sv) \
$(wildcard src/clint/*.sv) \
$(wildcard src/plic/*.sv) \
$(wildcard src/register_interface/*.sv) \
$(wildcard src/axi_node/src/*.sv) \
$(wildcard src/axi_mem_if/src/*.sv) \
$(filter-out src/debug/dm_pkg.sv, $(wildcard src/debug/*.sv)) \
$(wildcard src/debug/debug_rom/*.sv) \
src/axi/src/axi_multicut.sv \
src/axi/src/axi_cut.sv \
src/axi/src/axi_join.sv \
src/fpga-support/rtl/SyncSpRamBeNx64.sv \
@ -135,16 +140,16 @@ $(dpi-library)/ariane_dpi.so: $(dpi)
sim: build
vsim${questa_version} +permissive -64 -lib ${library} +max-cycles=$(max_cycles) +UVM_TESTNAME=${test_case} \
+BASEDIR=$(riscv-test-dir) $(uvm-flags) "+UVM_VERBOSITY=LOW" -coverage -classdebug +jtag_rbb_enable=0 \
+BASEDIR=$(riscv-test-dir) $(uvm-flags) "+UVM_VERBOSITY=LOW" -coverage -classdebug +jtag_rbb_enable=1 \
$(QUESTASIM_FLAGS) \
-gblso $(RISCV)/lib/libfesvr.so -sv_lib $(dpi-library)/ariane_dpi -do " do tb/wave/wave_core.do; run -all; exit" \
-gblso $(RISCV)/lib/libfesvr.so -sv_lib $(dpi-library)/ariane_dpi -do "log -r /*; run -all; exit" \
${top_level}_optimized +permissive-off ++$(riscv-test-dir)/$(riscv-test) ++$(target-options)
simc: build
vsim${questa_version} +permissive -64 -c -lib ${library} +max-cycles=$(max_cycles) +UVM_TESTNAME=${test_case} \
+BASEDIR=$(riscv-test-dir) $(uvm-flags) "+UVM_VERBOSITY=LOW" -coverage -classdebug +jtag_rbb_enable=0 \
$(QUESTASIM_FLAGS) \
-gblso $(RISCV)/lib/libfesvr.so -sv_lib $(dpi-library)/ariane_dpi -do " run -all; exit" \
-gblso $(RISCV)/lib/libfesvr.so -sv_lib $(dpi-library)/ariane_dpi -do "run -all; exit" \
${top_level}_optimized +permissive-off ++$(riscv-test-dir)/$(riscv-test) ++$(target-options)
$(riscv-asm-tests): build

View file

@ -77,6 +77,8 @@ Coming.
### Debugging
[OpenOCD](http://openocd.org/doc/html/Architecture-and-Core-Commands.html)
```
(gdb) b putchar
(gdb) c
@ -148,3 +150,6 @@ This runs the randomized program on Spike and on the RTL target, and checks whet
Check out the [contribution guide](CONTRIBUTING.md)
# Acknowledgements
Thanks to Gian Marti, Thomas Kramer and Thomas E. Benz for implementing the PLIC.

View file

@ -38,6 +38,29 @@
interrupts-extended = <&CPU0_intc 3 &CPU0_intc 7 >;
reg = <0x0 0x2000000 0x0 0xc0000>;
};
PLIC0: interrupt-controller@c000000 {
#interrupt-cells = <1>;
compatible = "riscv,plic0";
interrupt-controller;
interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>;
reg = <0x0 0xc000000 0x0 0x4000000>;
reg-names = "control";
riscv,max-priority = <7>;
riscv,ndev = <53>;
};
debug-controller@0 {
compatible = "riscv,debug-013";
interrupts-extended = <&CPU0_intc 65535>;
reg = <0x0 0x0 0x0 0x1000>;
reg-names = "control";
};
uartlite_0@42C00000 {
compatible = "xlnx,axi-uartlite-1.02.a";
reg = <0x10000000 0x10000>;
interrupt-parent = <&PLIC0>;
interrupts = <0 1 2>;
clock = <100000000>;
};
};
htif {
compatible = "ucb,htif0";

View file

@ -31,14 +31,13 @@ module ariane_xilinx (
input logic tms,
input logic trst_n,
input logic tdi,
output logic tdo
output logic tdo,
input logic rx,
output logic tx
);
localparam logic [63:0] RomBase = 64'h10000;
localparam NBSlave = 4; // debug, Instruction fetch, data bypass, data
localparam NBMaster = 3; // debug, ROM, RAM
localparam logic [63:0] CacheStartAddr = 64'h8000_0000;
localparam AxiAddrWidth = 64;
localparam AxiDataWidth = 64;
localparam AxiIdWidthMaster = 2;
@ -64,7 +63,7 @@ AXI_BUS #(
.AXI_DATA_WIDTH ( AxiDataWidth ),
.AXI_ID_WIDTH ( AxiIdWidthSlaves ),
.AXI_USER_WIDTH ( AxiUserWidth )
) master[NBMaster-1:0]();
) master[ariane_soc::NB_PERIPHERALS-1:0]();
// disable test-enable
logic test_en;
@ -201,13 +200,27 @@ axi_node_intf_wrap #(
.AXI_USER_WIDTH ( AxiUserWidth ),
.AXI_ID_WIDTH ( AxiIdWidthMaster )
) i_axi_xbar (
.clk ( clk ),
.rst_n ( ndmreset_n ),
.test_en_i ( test_en ),
.slave ( slave ),
.master ( master ),
.start_addr_i ( {64'h0, RomBase, 64'h2000000, CacheStartAddr} ),
.end_addr_i ( {64'hFFF, RomBase + 64'hFFFF, 64'h2FFFFFF, CacheStartAddr + 2**24} )
.clk ( clk ),
.rst_n ( ndmreset_n ),
.test_en_i ( test_en ),
.slave ( slave ),
.master ( master ),
.start_addr_i ({
ariane_soc::DebugBase,
ariane_soc::ROMBase,
ariane_soc::CLINTBase,
ariane_soc::PLICBase,
ariane_soc::UARTBase,
ariane_soc::DRAMBase
}),
.end_addr_i ({
ariane_soc::DebugBase + ariane_soc::DebugLength,
ariane_soc::ROMBase + ariane_soc::ROMLength,
ariane_soc::CLINTBase + ariane_soc::CLINTLength,
ariane_soc::PLICBase + ariane_soc::PLICLength,
ariane_soc::UARTBase + ariane_soc::UARTLength,
ariane_soc::DRAMBase + ariane_soc::DRAMLength
})
);
dm::dmi_req_t debug_req;;
@ -243,22 +256,22 @@ dm_top #(
.AxiDataWidth ( AxiDataWidth ),
.AxiUserWidth ( AxiUserWidth )
) i_dm_top (
.clk_i ( clk ),
.rst_ni ( rst_n ), // PoR
.testmode_i ( test_en ),
.ndmreset_o ( ndmreset ),
.dmactive_o ( ), // active debug session
.debug_req_o ( debug_req_irq ),
.unavailable_i ( '0 ),
.axi_master ( slave_slice[3] ),
.axi_slave ( master[3] ),
.dmi_rst_ni ( rst_n ),
.dmi_req_valid_i ( debug_req_valid ),
.dmi_req_ready_o ( debug_req_ready ),
.dmi_req_i ( debug_req ),
.dmi_resp_valid_o ( debug_resp_valid ),
.dmi_resp_ready_i ( debug_resp_ready ),
.dmi_resp_o ( debug_resp )
.clk_i ( clk ),
.rst_ni ( rst_n ), // PoR
.testmode_i ( test_en ),
.ndmreset_o ( ndmreset ),
.dmactive_o ( ), // active debug session
.debug_req_o ( debug_req_irq ),
.unavailable_i ( '0 ),
.axi_master ( slave_slice[3] ),
.axi_slave ( master[ariane_soc::Debug] ),
.dmi_rst_ni ( rst_n ),
.dmi_req_valid_i ( debug_req_valid ),
.dmi_req_ready_o ( debug_req_ready ),
.dmi_req_i ( debug_req ),
.dmi_resp_valid_o ( debug_resp_valid ),
.dmi_resp_ready_i ( debug_resp_ready ),
.dmi_resp_o ( debug_resp )
);
// ---------------
@ -288,18 +301,91 @@ ariane #(
// CLINT
// ---------------
clint #(
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( AXI_ID_WIDTH_SLAVES ),
.NR_CORES ( 1 )
.AXI_ADDR_WIDTH ( AxiAddrWidth ),
.AXI_DATA_WIDTH ( AxiDataWidth ),
.AXI_ID_WIDTH ( AxiIdWidthSlaves ),
.NR_CORES ( 1 )
) i_clint (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.slave ( master[1] ),
.clk_i ( clk ),
.rst_ni ( ndmreset_n ),
.slave ( master[ariane_soc::CLINT] ),
// TODO(zarubaf): Fix RTC
.rtc_i ( 1'b0 ),
.timer_irq_o ( timer_irq ),
.ipi_o ( ipi )
.rtc_i ( 1'b0 ),
.timer_irq_o ( timer_irq ),
.ipi_o ( ipi )
);
// ---------------
// PLIC
// ---------------
logic [ariane_soc::NumTargets-1:0] irqs;
logic [ariane_soc::NumSources-1:0] irq_sources;
REG_BUS #(
.ADDR_WIDTH ( AxiAddrWidth ),
.DATA_WIDTH ( AxiDataWidth )
) reg_bus (clk_i);
plic #(
.ADDR_WIDTH ( AxiAddrWidth ),
.DATA_WIDTH ( AxiDataWidth ),
.ID_BITWIDTH ( 2 ), // TODO (zarubaf): Find propper width
.PARAMETER_BITWIDTH ( 2 ), // TODO (zarubaf): Find propper width
.NUM_TARGETS ( ariane_soc::NumTargets ),
.NUM_SOURCES ( ariane_soc::NumSources )
) i_plic (
.clk_i ( clk ),
.rst_ni ( ndmreset_n ),
.irq_sources_i ( irq_sources ),
.eip_targets_o ( irqs ),
.external_bus_io ( reg_bus )
);
// ---------------
// Peripheral
// ---------------
logic [3:0] uart_axi_lite_awaddr;
logic uart_axi_lite_awvalid;
logic uart_axi_lite_awready;
logic [31:0] uart_axi_lite_wdata;
logic [3:0] uart_axi_lite_wstrb;
logic uart_axi_lite_wvalid;
logic uart_axi_lite_wready;
logic [1:0] uart_axi_lite_bresp;
logic uart_axi_lite_bvalid;
logic uart_axi_lite_bready;
logic [3:0] uart_axi_lite_araddr;
logic uart_axi_lite_arvalid;
logic uart_axi_lite_arready;
logic [31:0] uart_axi_lite_rdata;
logic [1:0] uart_axi_lite_rresp;
logic uart_axi_lite_rvalid;
logic uart_axi_lite_rready;
axi_uartlite_0 i_axi_uart_lite (
.s_axi_aclk ( clk ),
.s_axi_aresetn ( ndmreset_n ),
.interrupt ( irq_sources[0] ),
.s_axi_awaddr ( uart_axi_lite_awaddr ),
.s_axi_awvalid ( uart_axi_lite_awvalid ),
.s_axi_awready ( uart_axi_lite_awready ),
.s_axi_wdata ( uart_axi_lite_wdata ),
.s_axi_wstrb ( uart_axi_lite_wstrb ),
.s_axi_wvalid ( uart_axi_lite_wvalid ),
.s_axi_wready ( uart_axi_lite_wready ),
.s_axi_bresp ( uart_axi_lite_bresp ),
.s_axi_bvalid ( uart_axi_lite_bvalid ),
.s_axi_bready ( uart_axi_lite_bready ),
.s_axi_araddr ( uart_axi_lite_araddr ),
.s_axi_arvalid ( uart_axi_lite_arvalid ),
.s_axi_arready ( uart_axi_lite_arready ),
.s_axi_rdata ( uart_axi_lite_rdata ),
.s_axi_rresp ( uart_axi_lite_rresp ),
.s_axi_rvalid ( uart_axi_lite_rvalid ),
.s_axi_rready ( uart_axi_lite_rready ),
.rx,
.tx
);
// ---------------
@ -315,15 +401,15 @@ axi2mem #(
.AXI_DATA_WIDTH ( AxiDataWidth ),
.AXI_USER_WIDTH ( AxiUserWidth )
) i_axi2rom (
.clk_i ( clk ),
.rst_ni ( ndmreset_n ),
.slave ( master[2] ),
.req_o ( rom_req ),
.we_o ( ),
.addr_o ( rom_addr ),
.be_o ( ),
.data_o ( ),
.data_i ( rom_rdata )
.clk_i ( clk ),
.rst_ni ( ndmreset_n ),
.slave ( master[ariane_soc::ROM] ),
.req_o ( rom_req ),
.we_o ( ),
.addr_o ( rom_addr ),
.be_o ( ),
.data_o ( ),
.data_i ( rom_rdata )
);
bootrom i_bootrom (
@ -333,50 +419,49 @@ bootrom i_bootrom (
.rdata_o ( rom_rdata )
);
// DDR 4 Subsystem
axi_clock_converter_0 axi_clock_converter (
.s_axi_aclk(clk),
.s_axi_aresetn(ndmreset_n),
.s_axi_awid(master[0].aw_id),
.s_axi_awaddr(master[0].aw_addr),
.s_axi_awlen(master[0].aw_len),
.s_axi_awsize(master[0].aw_size),
.s_axi_awburst(master[0].aw_burst),
.s_axi_awlock(master[0].aw_lock),
.s_axi_awcache(master[0].aw_cache),
.s_axi_awprot(master[0].aw_prot),
.s_axi_awregion(master[0].aw_region),
.s_axi_awqos(master[0].aw_qos),
.s_axi_awvalid(master[0].aw_valid),
.s_axi_awready(master[0].aw_ready),
.s_axi_wdata(master[0].w_data),
.s_axi_wstrb(master[0].w_strb),
.s_axi_wlast(master[0].w_last),
.s_axi_wvalid(master[0].w_valid),
.s_axi_wready(master[0].w_ready),
.s_axi_bid(master[0].b_id),
.s_axi_bresp(master[0].b_resp),
.s_axi_bvalid(master[0].b_valid),
.s_axi_bready(master[0].b_ready),
.s_axi_arid(master[0].ar_id),
.s_axi_araddr(master[0].ar_addr[31:0]),
.s_axi_arlen(master[0].ar_len),
.s_axi_arsize(master[0].ar_size),
.s_axi_arburst(master[0].ar_burst),
.s_axi_arlock(master[0].ar_lock),
.s_axi_arcache(master[0].ar_cache),
.s_axi_arprot(master[0].ar_prot),
.s_axi_arregion(master[0].ar_region),
.s_axi_arqos(master[0].ar_qos),
.s_axi_arvalid(master[0].ar_valid),
.s_axi_arready(master[0].ar_ready),
.s_axi_rid(master[0].r_id),
.s_axi_rdata(master[0].r_data),
.s_axi_rresp(master[0].r_resp),
.s_axi_rlast(master[0].r_last),
.s_axi_rvalid(master[0].r_valid),
.s_axi_rready(master[0].r_ready),
.s_axi_awid(master[ariane_soc::DRAM].aw_id),
.s_axi_awaddr(master[ariane_soc::DRAM].aw_addr),
.s_axi_awlen(master[ariane_soc::DRAM].aw_len),
.s_axi_awsize(master[ariane_soc::DRAM].aw_size),
.s_axi_awburst(master[ariane_soc::DRAM].aw_burst),
.s_axi_awlock(master[ariane_soc::DRAM].aw_lock),
.s_axi_awcache(master[ariane_soc::DRAM].aw_cache),
.s_axi_awprot(master[ariane_soc::DRAM].aw_prot),
.s_axi_awregion(master[ariane_soc::DRAM].aw_region),
.s_axi_awqos(master[ariane_soc::DRAM].aw_qos),
.s_axi_awvalid(master[ariane_soc::DRAM].aw_valid),
.s_axi_awready(master[ariane_soc::DRAM].aw_ready),
.s_axi_wdata(master[ariane_soc::DRAM].w_data),
.s_axi_wstrb(master[ariane_soc::DRAM].w_strb),
.s_axi_wlast(master[ariane_soc::DRAM].w_last),
.s_axi_wvalid(master[ariane_soc::DRAM].w_valid),
.s_axi_wready(master[ariane_soc::DRAM].w_ready),
.s_axi_bid(master[ariane_soc::DRAM].b_id),
.s_axi_bresp(master[ariane_soc::DRAM].b_resp),
.s_axi_bvalid(master[ariane_soc::DRAM].b_valid),
.s_axi_bready(master[ariane_soc::DRAM].b_ready),
.s_axi_arid(master[ariane_soc::DRAM].ar_id),
.s_axi_araddr(master[ariane_soc::DRAM].ar_addr[31:0]),
.s_axi_arlen(master[ariane_soc::DRAM].ar_len),
.s_axi_arsize(master[ariane_soc::DRAM].ar_size),
.s_axi_arburst(master[ariane_soc::DRAM].ar_burst),
.s_axi_arlock(master[ariane_soc::DRAM].ar_lock),
.s_axi_arcache(master[ariane_soc::DRAM].ar_cache),
.s_axi_arprot(master[ariane_soc::DRAM].ar_prot),
.s_axi_arregion(master[ariane_soc::DRAM].ar_region),
.s_axi_arqos(master[ariane_soc::DRAM].ar_qos),
.s_axi_arvalid(master[ariane_soc::DRAM].ar_valid),
.s_axi_arready(master[ariane_soc::DRAM].ar_ready),
.s_axi_rid(master[ariane_soc::DRAM].r_id),
.s_axi_rdata(master[ariane_soc::DRAM].r_data),
.s_axi_rresp(master[ariane_soc::DRAM].r_resp),
.s_axi_rlast(master[ariane_soc::DRAM].r_last),
.s_axi_rvalid(master[ariane_soc::DRAM].r_valid),
.s_axi_rready(master[ariane_soc::DRAM].r_ready),
// to size converter
.m_axi_aclk(c0_ddr4_ui_clk),
.m_axi_aresetn(ndmreset_n),

@ -1 +1 @@
Subproject commit 328cbe05a42a31aae6f57f780351a2ba22954fef
Subproject commit a2cd661d01a03b6556da04baf682701aeeccdbf9

View file

@ -15,7 +15,7 @@ riscv set_reset_timeout_sec 120
riscv set_command_timeout_sec 120
# prefer to use sba for system bus access
riscv set_prefer_sba off
riscv set_prefer_sba on
init
halt

View file

@ -27,7 +27,7 @@
//-- 2018-03-31 2.0 tbenz Created header
//-------------------------------------------------------------------------------
module plic_core #(
module plic #(
parameter int ADDR_WIDTH = -1, //width of external address bus
parameter int DATA_WIDTH = -1, //width of external data bus
parameter int ID_BITWIDTH = -1, //width of the gateway identifiers

View file

@ -0,0 +1,135 @@
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
//
//-------------------------------------------------------------------------------
//-- Title : Claim - Complete - Tracker
//-------------------------------------------------------------------------------
//-- File : plic_claim_complete_tracker.sv
//-- Author : Gian Marti <gimarti.student.ethz.ch>
//-- Author : Thomas Kramer <tkramer.student.ethz.ch>
//-- Author : Thomas E. Benz <tbenz.student.ethz.ch>
//-- Company : Integrated Systems Laboratory, ETH Zurich
//-- Created : 2018-03-31
//-- Last update: 2018-03-31
//-- Platform : ModelSim (simulation), Synopsys (synthesis)
//-- Standard : SystemVerilog IEEE 1800-2012
//-------------------------------------------------------------------------------
//-- Description: Implements the control logic of the plic
//-------------------------------------------------------------------------------
//-- Revisions :
//-- Date Version Author Description
//-- 2018-03-31 2.0 tbenz Created header
//-------------------------------------------------------------------------------
//FSM that receives interrupt claims and interrupt completes from targets
//and generates the fitting inerrupt claims and interrupt completes for sources
module plic_claim_complete_tracker #(
parameter int NUM_TARGETS = 1,
parameter int NUM_GATEWAYS = 1,
parameter int ID_BITWIDTH = 4
)(
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input logic [ID_BITWIDTH-1:0] identifier_of_largest_priority_per_target[NUM_TARGETS],
input logic target_irq_claims_i [NUM_TARGETS],
input logic target_irq_completes_i[NUM_TARGETS],
input logic [ID_BITWIDTH-1:0] target_irq_completes_identifier_i[NUM_TARGETS],
output logic gateway_irq_claims_o [NUM_GATEWAYS],
output logic gateway_irq_completes_o[NUM_GATEWAYS]
);
// claimed_gateways_q[target] is 0 if the target has not claimed the irq of any gateway
// and the is the identifier of the claimed gateway otherwise
logic [ID_BITWIDTH-1:0] claimed_gateways_q[NUM_TARGETS];
// the +1 is because counting starts from 1 and goes to NUM_GATEWAYS+1
logic claim_array [NUM_GATEWAYS+1][NUM_TARGETS];
logic save_claims_array_q [NUM_GATEWAYS+1][NUM_TARGETS];
logic complete_array [NUM_GATEWAYS+1][NUM_TARGETS];
logic [ID_BITWIDTH-1:0] complete_id;
// for handling claims
for (genvar counter = 0; counter < NUM_TARGETS; counter++) begin
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_target
integer id;
if (~rst_ni) begin
claimed_gateways_q[counter] <= '0;
for (integer i = 0; i <= NUM_GATEWAYS; i++) begin
claim_array[i][counter] <= '0;
save_claims_array_q[i][counter] <= '0;
end
end else begin
// per default, all claims and completes are zero
for (integer i = 0; i <= NUM_GATEWAYS; i++) begin
claim_array[i][counter] <= 0;
complete_array[i][counter] <= 0;
end
// if a claim is issued, forward it to gateway with highest priority for the claiming target
if (target_irq_claims_i[counter]) begin
id = identifier_of_largest_priority_per_target[counter];
claim_array[id][counter] <= 1;
// save claim for later when the complete-notification arrives
save_claims_array_q[id][counter] <= 1;
end else begin
//if a complete is issued, check if that gateway has previously been claimed by
//this target and forward the
//complete message to that gateway. if no claim has previously been issued, the
//complete message is ignored
//integer complete_id = target_irq_completes_identifier_i[counter];
complete_id = target_irq_completes_identifier_i[counter];
if (target_irq_completes_i[counter] && (save_claims_array_q[complete_id][counter] > 0)) begin
complete_array[complete_id][counter] <= 1;
save_claims_array_q[complete_id][counter] <= 0;
end
end
end
end
end
// the outputs for an id are the ORs of all targets for that id
always_comb begin : proc_result_computation
for (integer gateway = 1; gateway <= NUM_GATEWAYS; gateway++) begin
automatic logic is_claimed = '0;
automatic logic is_completed = '0;
for (integer target = 0; target < NUM_TARGETS; target++) begin
is_claimed = is_claimed | claim_array [gateway][target];
is_completed = is_completed | complete_array[gateway][target];
end
if (is_claimed) begin
gateway_irq_claims_o [gateway-1] = 1;
end else begin
gateway_irq_claims_o [gateway-1] = 0;
end
if (is_completed) begin
gateway_irq_completes_o[gateway-1] = 1;
end else begin
gateway_irq_completes_o[gateway-1] = 0;
end
end
end
endmodule //plic_claim_complete_tracker

View file

@ -56,8 +56,8 @@ module plic_interface #(
// CCP: claim/clear pulses
//calculate some parameter needed later
localparam int num_gateway_bundles = (NUM_GATEWAYS-1) / DATA_WIDTH + 1; // how many bundles we have to consider
localparam int bpw = DATA_WIDTH / 8; // how many bytes a data word consist of
localparam int num_gateway_bundles = (NUM_GATEWAYS-1) / DATA_WIDTH + 1; // how many bundles we have to consider
localparam int bpw = DATA_WIDTH / 8; // how many bytes a data word consist of
//internal signals
logic [ADDR_WIDTH-12-1:0 ] page_address; // the upper part of the address
logic [11:0 ] page_offset; // the lowest 12 bit describes the page offset
@ -157,7 +157,7 @@ module plic_interface #(
//the bottom part page_word_offset now tells us which gateway bundle we have to consider
//part of the page_address and the upper part of the page_word_offset give us the target nr.
if(page_offset[6:$clog2(bpw)]<num_gateway_bundles) begin
if(page_offset[6:$clog2(bpw)] < num_gateway_bundles) begin
if(({page_address[8:0], page_offset[11:7]} - 64) < NUM_TARGETS) begin
funct = IEB;
// debug:
@ -218,7 +218,7 @@ module plic_interface #(
external_bus_io.rdata = irq_pending_bundle[page_word_offset];
external_bus_io.ready = 1;
//write case
end else if(write_active != 0) begin
end else if (write_active != 0) begin
external_bus_io.error = 1; //not allowed
end
end

View file

@ -46,17 +46,6 @@ module plic_target_slice #(
logic[PRIORITY_BITWIDTH:0] interrupt_priority_masked[NUM_GATEWAYS];
always_comb begin : proc_mask_gateway_outputs
for (int i = 0; i < NUM_GATEWAYS; i++) begin
if(interrupt_enable_i[i] && interrupt_pending_i[i]) begin
interrupt_priority_masked[i] <= interrupt_priority_i[i] + 1; //priority shift +1
end else begin
interrupt_priority_masked[i] <= '0;
end
end
end
// Signals that represent the selected interrupt source.
logic[PRIORITY_BITWIDTH:0] best_priority;
@ -64,22 +53,22 @@ module plic_target_slice #(
// Create a tree to find the best interrupt source.
plic_find_max #(
.NUM_OPERANDS (NUM_GATEWAYS ),
.ID_BITWIDTH (ID_BITWIDTH ),
.PRIORITY_BITWIDTH (PRIORITY_BITWIDTH+1 )
.NUM_OPERANDS ( NUM_GATEWAYS ),
.ID_BITWIDTH ( ID_BITWIDTH ),
.PRIORITY_BITWIDTH ( PRIORITY_BITWIDTH + 1 )
) find_max_instance (
.priorities_i (interrupt_priority_masked ),
.identifiers_i (interrupt_id_i ),
.priorities_i ( interrupt_priority_masked ),
.identifiers_i ( interrupt_id_i ),
// Outputs
.largest_priority_o (best_priority ),
.identifier_of_largest_o (best_id )
.largest_priority_o ( best_priority ),
.identifier_of_largest_o ( best_id )
);
// Compare the priority of the best interrupt source to the threshold.
always_comb begin : proc_compare_threshold
if ((best_priority - 1 > threshold_i) && (best_priority != '0)) begin
ext_interrupt_present_o = 1;
identifier_of_largest_o = best_id;
ext_interrupt_present_o = 1;
identifier_of_largest_o = best_id;
end else begin
if ((best_priority - 1 <= threshold_i) && (best_priority != '0)) begin
ext_interrupt_present_o = 0;
@ -91,4 +80,13 @@ module plic_target_slice #(
end
end
always_comb begin : proc_mask_gateway_outputs
for (int i = 0; i < NUM_GATEWAYS; i++) begin
if (interrupt_enable_i[i] && interrupt_pending_i[i]) begin
interrupt_priority_masked[i] = interrupt_priority_i[i] + 1; //priority shift +1
end else begin
interrupt_priority_masked[i] = '0;
end
end
end
endmodule

@ -0,0 +1 @@
Subproject commit 2680950466dfe915c6a51037526c5d4329bd34db

View file

@ -18,8 +18,7 @@ module scoreboard #(
parameter int unsigned NR_ENTRIES = 8,
parameter int unsigned NR_WB_PORTS = 1,
parameter int unsigned NR_COMMIT_PORTS = 2
)
(
)(
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input logic flush_unissued_instr_i, // flush only un-issued instructions

44
tb/ariane_soc_pkg.sv Normal file
View file

@ -0,0 +1,44 @@
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
//
// Author: Florian Zaruba, ETH Zurich
// Description: Contains SoC information as constants
package ariane_soc;
localparam NB_PERIPHERALS = 6;
localparam NumTargets = 2;
localparam NumSources = 1;
typedef enum int unsigned {
DRAM = 0,
UART = 1,
PLIC = 2,
CLINT = 3,
ROM = 4,
Debug = 5
} axi_slaves_t;
typedef enum logic [63:0] {
DebugBase = 64'h0000_0000,
ROMBase = 64'h0001_0000,
CLINTBase = 64'h0200_0000,
PLICBase = 64'h0C00_0000,
UARTBase = 64'h1000_0000,
DRAMBase = 64'h8000_0000
} soc_bus_start_t;
localparam DebugLength = 64'h1000;
localparam ROMLength = 64'h1000;
localparam CLINTLength = 64'hC0000;
localparam PLICLength = 64'h4000000;
localparam UARTLength = 64'h10000;
localparam DRAMLength = 2**24;
endpackage

View file

@ -69,7 +69,6 @@ module ariane_testharness #(
assign ndmreset_n = ~ndmreset ;
localparam NB_SLAVE = 4;
localparam NB_MASTER = 4;
localparam AXI_ID_WIDTH_SLAVES = AXI_ID_WIDTH + $clog2(NB_SLAVE);
@ -85,7 +84,7 @@ module ariane_testharness #(
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( AXI_ID_WIDTH_SLAVES ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
) master[NB_MASTER-1:0]();
) master[ariane_soc::NB_PERIPHERALS-1:0]();
// ---------------
// Debug
@ -172,22 +171,22 @@ module ariane_testharness #(
.AxiDataWidth ( AXI_DATA_WIDTH ),
.AxiUserWidth ( AXI_USER_WIDTH )
) i_dm_top (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ), // PoR
.testmode_i ( test_en ),
.ndmreset_o ( ndmreset ),
.dmactive_o ( ), // active debug session
.debug_req_o ( debug_req_core ),
.unavailable_i ( '0 ),
.axi_master ( slave[3] ),
.axi_slave ( master[3] ),
.dmi_rst_ni ( rst_ni ),
.dmi_req_valid_i ( debug_req_valid ),
.dmi_req_ready_o ( debug_req_ready ),
.dmi_req_i ( debug_req ),
.dmi_resp_valid_o ( debug_resp_valid ),
.dmi_resp_ready_i ( debug_resp_ready ),
.dmi_resp_o ( debug_resp )
.clk_i ( clk_i ),
.rst_ni ( rst_ni ), // PoR
.testmode_i ( test_en ),
.ndmreset_o ( ndmreset ),
.dmactive_o ( ), // active debug session
.debug_req_o ( debug_req_core ),
.unavailable_i ( '0 ),
.axi_master ( slave[3] ),
.axi_slave ( master[ariane_soc::Debug] ),
.dmi_rst_ni ( rst_ni ),
.dmi_req_valid_i ( debug_req_valid ),
.dmi_req_ready_o ( debug_req_ready ),
.dmi_req_i ( debug_req ),
.dmi_resp_valid_o ( debug_resp_valid ),
.dmi_resp_ready_i ( debug_resp_ready ),
.dmi_resp_o ( debug_resp )
);
// ---------------
@ -203,15 +202,15 @@ module ariane_testharness #(
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
) i_axi2rom (
.clk_i ( clk_i ),
.rst_ni ( ndmreset_n ),
.slave ( master[2] ),
.req_o ( rom_req ),
.we_o ( ),
.addr_o ( rom_addr ),
.be_o ( ),
.data_o ( ),
.data_i ( rom_rdata )
.clk_i ( clk_i ),
.rst_ni ( ndmreset_n ),
.slave ( master[ariane_soc::ROM] ),
.req_o ( rom_req ),
.we_o ( ),
.addr_o ( rom_addr ),
.be_o ( ),
.data_o ( ),
.data_i ( rom_rdata )
);
bootrom i_bootrom (
@ -231,22 +230,21 @@ module ariane_testharness #(
logic [AXI_DATA_WIDTH-1:0] wdata;
logic [AXI_DATA_WIDTH-1:0] rdata;
axi2mem #(
.AXI_ID_WIDTH ( AXI_ID_WIDTH_SLAVES ),
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
) i_axi2mem (
.clk_i ( clk_i ),
.rst_ni ( ndmreset_n ),
.slave ( master[0] ),
.req_o ( req ),
.we_o ( we ),
.addr_o ( addr ),
.be_o ( be ),
.data_o ( wdata ),
.data_i ( rdata )
.clk_i ( clk_i ),
.rst_ni ( ndmreset_n ),
.slave ( master[ariane_soc::DRAM] ),
.req_o ( req ),
.we_o ( we ),
.addr_o ( addr ),
.be_o ( be ),
.data_o ( wdata ),
.data_i ( rdata )
);
sram #(
@ -268,20 +266,34 @@ module ariane_testharness #(
// ---------------
axi_node_intf_wrap #(
// three ports from Ariane (instruction, data and bypass)
.NB_SLAVE ( NB_SLAVE ),
.NB_MASTER ( NB_MASTER ), // debug unit, memory unit
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH ),
.AXI_ID_WIDTH ( AXI_ID_WIDTH )
.NB_SLAVE ( NB_SLAVE ),
.NB_MASTER ( ariane_soc::NB_PERIPHERALS ),
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH ),
.AXI_ID_WIDTH ( AXI_ID_WIDTH )
) i_axi_xbar (
.clk ( clk_i ),
.rst_n ( ndmreset_n ),
.test_en_i ( test_en ),
.slave ( slave ),
.master ( master ),
.start_addr_i ( {64'h0, 64'h10000, 64'h2000000, CACHE_START_ADDR} ),
.end_addr_i ( {64'hFFF, 64'h1FFFF, 64'h2FFFFFF, CACHE_START_ADDR + 2**24} )
.clk ( clk_i ),
.rst_n ( ndmreset_n ),
.test_en_i ( test_en ),
.slave ( slave ),
.master ( master ),
.start_addr_i ({
ariane_soc::DebugBase,
ariane_soc::ROMBase,
ariane_soc::CLINTBase,
ariane_soc::PLICBase,
ariane_soc::UARTBase,
ariane_soc::DRAMBase
}),
.end_addr_i ({
ariane_soc::DebugBase + ariane_soc::DebugLength,
ariane_soc::ROMBase + ariane_soc::ROMLength,
ariane_soc::CLINTBase + ariane_soc::CLINTLength,
ariane_soc::PLICBase + ariane_soc::PLICLength,
ariane_soc::UARTBase + ariane_soc::UARTLength,
ariane_soc::DRAMBase + ariane_soc::DRAMLength
})
);
// ---------------
@ -296,14 +308,52 @@ module ariane_testharness #(
.AXI_ID_WIDTH ( AXI_ID_WIDTH_SLAVES ),
.NR_CORES ( 1 )
) i_clint (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.slave ( master[1] ),
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.slave ( master[ariane_soc::CLINT] ),
.rtc_i,
.timer_irq_o ( timer_irq ),
.ipi_o ( ipi )
.timer_irq_o ( timer_irq ),
.ipi_o ( ipi )
);
// ---------------
// PLIC
// ---------------
logic [ariane_soc::NumTargets-1:0] irqs;
logic [ariane_soc::NumSources-1:0] irq_sources;
REG_BUS #(
.ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.DATA_WIDTH ( AXI_DATA_WIDTH )
) reg_bus (clk_i);
plic #(
.ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.DATA_WIDTH ( AXI_DATA_WIDTH ),
.ID_BITWIDTH ( 2 ), // TODO (zarubaf): Find propper width
.PARAMETER_BITWIDTH ( 2 ), // TODO (zarubaf): Find propper width
.NUM_TARGETS ( ariane_soc::NumTargets ),
.NUM_SOURCES ( ariane_soc::NumSources )
) i_plic (
.clk_i,
.rst_ni ( ndmreset_n ),
.irq_sources_i ( irq_sources ),
.eip_targets_o ( irqs ),
.external_bus_io ( reg_bus )
);
// ---------------
// Peripheral
// ---------------
// tie-off uart here
assign irq_sources = '0;
assign master[ariane_soc::UART].aw_ready = 1'b1;
assign master[ariane_soc::UART].ar_ready = 1'b1;
assign master[ariane_soc::UART].w_ready = 1'b1;
assign master[ariane_soc::UART].b_valid = 1'b0;
assign master[ariane_soc::UART].r_valid = 1'b0;
// ---------------
// Core
// ---------------
@ -312,18 +362,18 @@ module ariane_testharness #(
.AXI_ID_WIDTH ( AXI_ID_WIDTH ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
) i_ariane (
.clk_i ( clk_i ),
.rst_ni ( ndmreset_n ),
.boot_addr_i ( 64'h10000 ), // start fetching from ROM
.core_id_i ( '0 ),
.cluster_id_i ( '0 ),
.irq_i ( '0 ), // we do not specify other interrupts in this TB
.ipi_i ( ipi ),
.time_irq_i ( timer_irq ),
.debug_req_i ( debug_req_core ),
.data_if ( slave[2] ),
.bypass_if ( slave[1] ),
.instr_if ( slave[0] )
.clk_i ( clk_i ),
.rst_ni ( ndmreset_n ),
.boot_addr_i ( 64'h10000 ), // start fetching from ROM
.core_id_i ( '0 ),
.cluster_id_i ( '0 ),
.irq_i ( irqs ),
.ipi_i ( ipi ),
.time_irq_i ( timer_irq ),
.debug_req_i ( debug_req_core ),
.data_if ( slave[2] ),
.bypass_if ( slave[1] ),
.instr_if ( slave[0] )
);
endmodule