Linux booting to first context switch

This commit is contained in:
Florian Zaruba 2018-09-29 13:46:03 +02:00
parent dcc8d73aa7
commit eab01511a3
No known key found for this signature in database
GPG key ID: E742FFE8EC38A792
25 changed files with 991 additions and 212 deletions

View file

@ -58,7 +58,7 @@ src := $(filter-out src/ariane_regfile.sv, $(wildcard src/*.sv)) \
$(wildcard bootrom/*.sv) \
$(wildcard src/clint/*.sv) \
$(wildcard src/plic/*.sv) \
$(wildcard src/register_interface/*.sv) \
$(wildcard src/register_interface/src/*.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)) \
@ -66,6 +66,7 @@ src := $(filter-out src/ariane_regfile.sv, $(wildcard src/*.sv)) \
src/axi/src/axi_multicut.sv \
src/axi/src/axi_cut.sv \
src/axi/src/axi_join.sv \
src/axi/src/axi_to_axi_lite.sv \
src/fpga-support/rtl/SyncSpRamBeNx64.sv \
src/common_cells/src/sync.sv \
src/common_cells/src/cdc_2phase.sv \
@ -76,8 +77,9 @@ src := $(filter-out src/ariane_regfile.sv, $(wildcard src/*.sv)) \
src/common_cells/src/lzc.sv \
src/common_cells/src/rrarbiter.sv \
src/common_cells/src/lfsr_8bit.sv \
src/common_cells/src/rstgen_bypass.sv \
src/common_cells/src/rstgen_bypass.sv \
tb/ariane_testharness.sv \
tb/common/mock_uartlite.sv \
tb/common/SimDTM.sv \
tb/common/SimJTAG.sv
@ -148,15 +150,15 @@ 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 \
$(QUESTASIM_FLAGS) \
-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)
-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" \
${top_level}_optimized +permissive-off ++$(riscv-test-dir)/$(riscv-test) ++$(target-options)
-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)
$(riscv-asm-tests): build
vsim${questa_version} +permissive -64 -c -lib ${library} +max-cycles=$(max_cycles) +UVM_TESTNAME=${test_case} \
@ -164,7 +166,7 @@ $(riscv-asm-tests): build
$(QUESTASIM_FLAGS) \
-gblso $(RISCV)/lib/libfesvr.so -sv_lib $(dpi-library)/ariane_dpi \
-do "coverage save -onexit tmp/$@.ucdb; run -a; quit -code [coverage attribute -name TESTSTATUS -concise]" \
${top_level}_optimized +permissive-off ++$(riscv-test-dir)/$@ ++$(target-options) | tee tmp/riscv-asm-tests-$@.log
${top_level}_optimized +permissive-off ++$(riscv-test-dir)$@ ++$(target-options) | tee tmp/riscv-asm-tests-$@.log
$(riscv-benchmarks): build
vsim${questa_version} +permissive -64 -c -lib ${library} +max-cycles=$(max_cycles) +UVM_TESTNAME=${test_case} \
@ -172,7 +174,7 @@ $(riscv-benchmarks): build
$(QUESTASIM_FLAGS) \
-gblso $(RISCV)/lib/libfesvr.so -sv_lib $(dpi-library)/ariane_dpi \
-do "coverage save -onexit tmp/$@.ucdb; run -a; quit -code [coverage attribute -name TESTSTATUS -concise]" \
${top_level}_optimized +permissive-off ++$(riscv-benchmarks-dir)/$@ ++$(target-options) | tee tmp/riscv-benchmarks-$@.log
${top_level}_optimized +permissive-off ++$(riscv-benchmarks-dir)$@ ++$(target-options) | tee tmp/riscv-benchmarks-$@.log
# can use -jX to run ci tests in parallel using X processes
run-asm-tests: $(riscv-asm-tests)

View file

@ -8,7 +8,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
timebase-frequency = <50000000>;
timebase-frequency = <25000000>;
CPU0: cpu@0 {
device_type = "cpu";
reg = <0>;
@ -26,7 +26,7 @@
};
memory@80000000 {
device_type = "memory";
reg = <0x0 0x80000000 0x0 0x1000000>;
reg = <0x0 0x80000000 0x0 0x2000000>;
};
soc {
#address-cells = <2>;

Binary file not shown.

View file

@ -153,7 +153,7 @@ module bootrom (
64'h02000000_00000000,
64'h04000000_03000000,
64'h00636f73_01000000,
64'h02000000_00000001,
64'h02000000_00000002,
64'h00000000_00000080,
64'h00000000_4b000000,
64'h10000000_03000000,
@ -196,7 +196,7 @@ module bootrom (
64'h3f000000_04000000,
64'h03000000_00000030,
64'h40757063_01000000,
64'h80f0fa02_2c000000,
64'h40787d01_2c000000,
64'h04000000_03000000,
64'h00000000_0f000000,
64'h04000000_03000000,

View file

@ -6,3 +6,6 @@ set_input_jitter tck 1.000
set_max_delay -datapath_only -from [get_pins i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_src/data_src_q_reg*/C] -to [get_pins i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_dst/data_dst_q_reg*/D] 10.000
set_max_delay -datapath_only -from [get_pins i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_src/req_src_q_reg/C] -to [get_pins i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_dst/req_dst_q_reg/D] 10.000
set_max_delay -datapath_only -from [get_pins i_dmi_jtag/i_dmi_cdc/i_cdc_req/i_dst/ack_dst_q_reg/C] -to [get_pins i_dmi_jtag/i_dmi_cdc/i_cdc_req/i_src/ack_src_q_reg/D] 10.000

View file

@ -13,6 +13,8 @@ module ariane_leds (
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
output logic [7:0] led_o,
input logic [3:0] pc_asserted_i,
input logic [1:0] commit_valid_i,
input logic dmactive_i
);
@ -21,11 +23,12 @@ module ariane_leds (
always_comb begin
cnt_d = cnt_q;
led_o = '0;
// hearbeat
led_o[0] = cnt_q[18];
// debugging active
led_o[1] = dmactive_i;
led_o[7] = 1'b1;
led_o[0] = pc_asserted_i[0];
led_o[1] = pc_asserted_i[1];
led_o[2] = pc_asserted_i[2];
led_o[3] = pc_asserted_i[3];
led_o[4] = commit_valid_i[0];
led_o[5] = commit_valid_i[1];
end
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_

View file

@ -38,7 +38,9 @@ module ariane_xilinx (
input logic rx,
output logic tx,
output logic [7:0] led
output logic [7:0] led,
input logic [7:0] sw,
output logic fan_pwm
);
localparam NBSlave = 4; // debug, Instruction fetch, data bypass, data
@ -86,45 +88,45 @@ logic rst_n, rst;
logic cpu_reset;
// DDR
logic [3:0] s_axi_awid;
logic [3:0] s_axi_awid;
logic [63:0] s_axi_awaddr;
logic [7:0] s_axi_awlen;
logic [2:0] s_axi_awsize;
logic [1:0] s_axi_awburst;
logic [0:0] s_axi_awlock;
logic [3:0] s_axi_awcache;
logic [2:0] s_axi_awprot;
logic [3:0] s_axi_awregion;
logic [3:0] s_axi_awqos;
logic s_axi_awvalid;
logic s_axi_awready;
logic [7:0] s_axi_awlen;
logic [2:0] s_axi_awsize;
logic [1:0] s_axi_awburst;
logic [0:0] s_axi_awlock;
logic [3:0] s_axi_awcache;
logic [2:0] s_axi_awprot;
logic [3:0] s_axi_awregion;
logic [3:0] s_axi_awqos;
logic s_axi_awvalid;
logic s_axi_awready;
logic [63:0] s_axi_wdata;
logic [7:0] s_axi_wstrb;
logic s_axi_wlast;
logic s_axi_wvalid;
logic s_axi_wready;
logic [3:0] s_axi_bid;
logic [1:0] s_axi_bresp;
logic s_axi_bvalid;
logic s_axi_bready;
logic [3:0] s_axi_arid;
logic [7:0] s_axi_wstrb;
logic s_axi_wlast;
logic s_axi_wvalid;
logic s_axi_wready;
logic [3:0] s_axi_bid;
logic [1:0] s_axi_bresp;
logic s_axi_bvalid;
logic s_axi_bready;
logic [3:0] s_axi_arid;
logic [63:0] s_axi_araddr;
logic [7:0] s_axi_arlen;
logic [2:0] s_axi_arsize;
logic [1:0] s_axi_arburst;
logic [0:0] s_axi_arlock;
logic [3:0] s_axi_arcache;
logic [2:0] s_axi_arprot;
logic [3:0] s_axi_arregion;
logic [3:0] s_axi_arqos;
logic s_axi_arvalid;
logic s_axi_arready;
logic [3:0] s_axi_rid;
logic [7:0] s_axi_arlen;
logic [2:0] s_axi_arsize;
logic [1:0] s_axi_arburst;
logic [0:0] s_axi_arlock;
logic [3:0] s_axi_arcache;
logic [2:0] s_axi_arprot;
logic [3:0] s_axi_arregion;
logic [3:0] s_axi_arqos;
logic s_axi_arvalid;
logic s_axi_arready;
logic [3:0] s_axi_rid;
logic [63:0] s_axi_rdata;
logic [1:0] s_axi_rresp;
logic s_axi_rlast;
logic s_axi_rvalid;
logic s_axi_rready;
logic [1:0] s_axi_rresp;
logic s_axi_rlast;
logic s_axi_rvalid;
logic s_axi_rready;
// ROM
logic rom_req;
@ -170,6 +172,8 @@ assign rst = ddr_sync_reset;
assign test_en = 1'b0;
assign ndmreset_n = ~ndmreset ;
logic [NBSlave-1:0] pc_asserted;
// Slice the AXI Masters (slave ports on the XBar)
for (genvar i = 0; i < NBSlave; i++) begin : slave_cut_gen
axi_cut #(
@ -183,6 +187,57 @@ for (genvar i = 0; i < NBSlave; i++) begin : slave_cut_gen
.in ( slave_slice[i] ),
.out ( slave[i] )
);
axi_protocol_checker_0 i_axi_protocol_checker (
.pc_status( ), // debug probe
.pc_asserted(pc_asserted[i]),
.aclk(clk),
.aresetn(ndmreset_n),
.pc_axi_awid(slave[i].aw_id),
.pc_axi_awaddr(slave[i].aw_addr),
.pc_axi_awlen(slave[i].aw_len),
.pc_axi_awsize(slave[i].aw_size),
.pc_axi_awburst(slave[i].aw_burst),
.pc_axi_awlock(slave[i].aw_lock),
.pc_axi_awcache(slave[i].aw_cache),
.pc_axi_awprot(slave[i].aw_prot),
.pc_axi_awqos(slave[i].aw_qos),
.pc_axi_awregion(slave[i].aw_region),
.pc_axi_awready(slave[i].aw_ready),
.pc_axi_awvalid(slave[i].aw_valid),
.pc_axi_awuser(slave[i].aw_user),
.pc_axi_wlast(slave[i].w_last),
.pc_axi_wdata(slave[i].w_data),
.pc_axi_wstrb(slave[i].w_strb),
.pc_axi_wuser(slave[i].w_user),
.pc_axi_wvalid(slave[i].w_valid),
.pc_axi_wready(slave[i].w_ready),
.pc_axi_bid(slave[i].b_id),
.pc_axi_bresp(slave[i].b_resp),
.pc_axi_buser(slave[i].b_user),
.pc_axi_bvalid(slave[i].b_valid),
.pc_axi_bready(slave[i].b_ready),
.pc_axi_arid(slave[i].ar_id),
.pc_axi_araddr(slave[i].ar_addr),
.pc_axi_arlen(slave[i].ar_len),
.pc_axi_arsize(slave[i].ar_size),
.pc_axi_arburst(slave[i].ar_burst),
.pc_axi_arlock(slave[i].ar_lock),
.pc_axi_arcache(slave[i].ar_cache),
.pc_axi_arprot(slave[i].ar_prot),
.pc_axi_arqos(slave[i].ar_qos),
.pc_axi_arregion(slave[i].ar_region),
.pc_axi_aruser(slave[i].ar_user),
.pc_axi_arvalid(slave[i].ar_valid),
.pc_axi_arready(slave[i].ar_ready),
.pc_axi_rid(slave[i].r_id),
.pc_axi_rlast(slave[i].r_last),
.pc_axi_rdata(slave[i].r_data),
.pc_axi_rresp(slave[i].r_resp),
.pc_axi_ruser(slave[i].r_user),
.pc_axi_rvalid(slave[i].r_valid),
.pc_axi_rready(slave[i].r_ready)
);
end
// ---------------
@ -283,7 +338,7 @@ ariane #(
.cluster_id_i ( '0 ),
.irq_i ( irq ),
.ipi_i ( ipi ),
.time_irq_i ( time_irq ),
.time_irq_i ( timer_irq ),
.debug_req_i ( debug_req_irq ),
.data_if ( slave_slice[2] ),
.bypass_if ( slave_slice[1] ),
@ -293,6 +348,17 @@ ariane #(
// ---------------
// CLINT
// ---------------
logic rtc;
// divide clock by two
always_ff @(posedge clk or negedge ndmreset_n) begin
if (~ndmreset_n) begin
rtc <= 0;
end else begin
rtc <= rtc ^ 1'b1;
end
end
clint #(
.AXI_ADDR_WIDTH ( AxiAddrWidth ),
.AXI_DATA_WIDTH ( AxiDataWidth ),
@ -302,8 +368,7 @@ clint #(
.clk_i ( clk ),
.rst_ni ( ndmreset_n ),
.slave ( master[ariane_soc::CLINT] ),
// TODO(zarubaf): Fix RTC
.rtc_i ( 1'b0 ),
.rtc_i ( rtc ),
.timer_irq_o ( timer_irq ),
.ipi_o ( ipi )
);
@ -351,18 +416,30 @@ ariane_peripherals #(
.tx_o ( tx )
);
// ---------------------
// Board peripherals
// ---------------------
fan_ctrl i_fan_ctrl (
.clk_i ( clk ),
.rst_ni ( ndmreset_n ),
.pwm_setting_i ( sw[3:0] ),
.fan_pwm_o ( fan_pwm )
);
ariane_leds i_ariane_leds (
.clk_i(clk),
.rst_ni(rst_n),
.led_o(led),
.dmactive_i(dmactive)
.clk_i ( clk ),
.rst_ni ( rst_n ),
.led_o ( led ),
.pc_asserted_i ( pc_asserted ),
.dmactive_i ( dmactive ),
.commit_valid_i ( '0 )
);
clk_wiz_0 i_clk_gen (
.clk_out1(clk),
.reset(cpu_reset),
.locked(), // keep open
.clk_in1(ddr_clock_out)
.clk_out1 ( clk ),
.reset ( cpu_reset ),
.locked ( ), // keep open
.clk_in1 ( ddr_clock_out )
);
// ---------------

1
fpga/bootrom/.gitignore vendored Symbolic link
View file

@ -0,0 +1 @@
../../bootrom/.gitignore

1
fpga/bootrom/Makefile Symbolic link
View file

@ -0,0 +1 @@
../../bootrom/Makefile

65
fpga/bootrom/ariane.dts Normal file
View file

@ -0,0 +1,65 @@
/dts-v1/;
/ {
#address-cells = <2>;
#size-cells = <2>;
compatible = "eth,ariane-bare-dev";
model = "eth,ariane-bare";
cpus {
#address-cells = <1>;
#size-cells = <0>;
timebase-frequency = <25000000>;
CPU0: cpu@0 {
device_type = "cpu";
reg = <0>;
status = "okay";
compatible = "riscv";
riscv,isa = "rv64imc";
mmu-type = "riscv,sv39";
clock-frequency = <50000000>;
CPU0_intc: interrupt-controller {
#interrupt-cells = <1>;
interrupt-controller;
compatible = "riscv,cpu-intc";
};
};
};
memory@80000000 {
device_type = "memory";
reg = <0x0 0x80000000 0x0 0x2000000>;
};
soc {
#address-cells = <2>;
#size-cells = <2>;
compatible = "eth,ariane-bare-soc", "simple-bus";
ranges;
clint@2000000 {
compatible = "riscv,clint0";
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";
};
uart@10000000 {
compatible = "xlnx,axi-uartlite-1.02.a";
reg = <0x0 0x10000000 0x0 0x10000>;
interrupt-parent = <&PLIC0>;
interrupts = <0 1 2>;
clock = <50000000>;
};
};
};

24
fpga/bootrom/bootrom.S Normal file
View file

@ -0,0 +1,24 @@
#define DRAM_BASE 0x80000000
.section .text.start, "ax", @progbits
.globl _start
_start:
li s0, DRAM_BASE
csrr a0, mhartid
la a1, _dtb
jr s0
.section .text.hang, "ax", @progbits
.globl _hang
_hang:
csrr a0, mhartid
la a1, _dtb
1:
wfi
j 1b
.section .rodata.dtb, "a", @progbits
.globl _dtb
.align 5, 0
_dtb:
.incbin "ariane.dtb"

BIN
fpga/bootrom/bootrom.img Normal file

Binary file not shown.

248
fpga/bootrom/bootrom.sv Normal file
View file

@ -0,0 +1,248 @@
/* 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.
*
* File: $filename.v
*
* Description: Auto-generated bootrom
*/
// Auto-generated code
module bootrom (
input logic clk_i,
input logic req_i,
input logic [63:0] addr_i,
output logic [63:0] rdata_o
);
localparam int RomSize = 211;
const logic [RomSize-1:0][63:0] mem = {
64'h006b,
64'h636f6c63_00737470,
64'h75727265_746e6900,
64'h746e6572_61702d74,
64'h70757272_65746e69,
64'h00766564_6e2c7663,
64'h73697200_79746972,
64'h6f697270_2d78616d,
64'h2c766373_69720073,
64'h656d616e_2d676572,
64'h00646564_6e657478,
64'h652d7374_70757272,
64'h65746e69_00736567,
64'h6e617200_656c646e,
64'h6168702c_78756e69,
64'h6c007265_6c6c6f72,
64'h746e6f63_2d747075,
64'h72726574_6e690073,
64'h6c6c6563_2d747075,
64'h72726574_6e692300,
64'h79636e65_75716572,
64'h662d6b63_6f6c6300,
64'h65707974_2d756d6d,
64'h00617369_2c766373,
64'h69720073_75746174,
64'h73006765_72006570,
64'h79745f65_63697665,
64'h64007963_6e657571,
64'h6572662d_65736162,
64'h656d6974_006c6564,
64'h6f6d0065_6c626974,
64'h61706d6f_6300736c,
64'h6c65632d_657a6973,
64'h2300736c_6c65632d,
64'h73736572_64646123,
64'h09000000_02000000,
64'h02000000_02000000,
64'h80f0fa02_0c010000,
64'h04000000_03000000,
64'h02000000_01000000,
64'h00000000_01010000,
64'h0c000000_03000000,
64'h02000000_f0000000,
64'h04000000_03000000,
64'h00000100_00000000,
64'h00000010_00000000,
64'h4b000000_10000000,
64'h03000000_00000000,
64'h612e3230_2e312d65,
64'h74696c74_7261752d,
64'h6978612c_786e6c78,
64'h1b000000_19000000,
64'h03000000_00000030,
64'h30303030_30303140,
64'h74726175_01000000,
64'h02000000_006c6f72,
64'h746e6f63_c8000000,
64'h08000000_03000000,
64'h00100000_00000000,
64'h00000000_00000000,
64'h4b000000_10000000,
64'h03000000_ffff0000,
64'h01000000_b4000000,
64'h08000000_03000000,
64'h00333130_2d677562,
64'h65642c76_63736972,
64'h1b000000_10000000,
64'h03000000_00003040,
64'h72656c6c_6f72746e,
64'h6f632d67_75626564,
64'h01000000_02000000,
64'h02000000_a5000000,
64'h04000000_03000000,
64'h02000000_9f000000,
64'h04000000_03000000,
64'h35000000_e5000000,
64'h04000000_03000000,
64'h07000000_d2000000,
64'h04000000_03000000,
64'h006c6f72_746e6f63,
64'hc8000000_08000000,
64'h03000000_00000004,
64'h00000000_0000000c,
64'h00000000_4b000000,
64'h10000000_03000000,
64'h09000000_01000000,
64'h0b000000_01000000,
64'hb4000000_10000000,
64'h03000000_8a000000,
64'h00000000_03000000,
64'h00306369_6c702c76,
64'h63736972_1b000000,
64'h0c000000_03000000,
64'h01000000_79000000,
64'h04000000_03000000,
64'h00000000_30303030,
64'h30306340_72656c6c,
64'h6f72746e_6f632d74,
64'h70757272_65746e69,
64'h01000000_02000000,
64'h00000c00_00000000,
64'h00000002_00000000,
64'h4b000000_10000000,
64'h03000000_07000000,
64'h01000000_03000000,
64'h01000000_b4000000,
64'h10000000_03000000,
64'h00000000_30746e69,
64'h6c632c76_63736972,
64'h1b000000_0d000000,
64'h03000000_00000030,
64'h30303030_30324074,
64'h6e696c63_01000000,
64'had000000_00000000,
64'h03000000_00007375,
64'h622d656c_706d6973,
64'h00636f73_2d657261,
64'h622d656e_61697261,
64'h2c687465_1b000000,
64'h1f000000_03000000,
64'h02000000_0f000000,
64'h04000000_03000000,
64'h02000000_00000000,
64'h04000000_03000000,
64'h00636f73_01000000,
64'h02000000_00000002,
64'h00000000_00000080,
64'h00000000_4b000000,
64'h10000000_03000000,
64'h00007972_6f6d656d,
64'h3f000000_07000000,
64'h03000000_00303030,
64'h30303030_38407972,
64'h6f6d656d_01000000,
64'h02000000_02000000,
64'h02000000_01000000,
64'ha5000000_04000000,
64'h03000000_01000000,
64'h9f000000_04000000,
64'h03000000_00006374,
64'h6e692d75_70632c76,
64'h63736972_1b000000,
64'h0f000000_03000000,
64'h8a000000_00000000,
64'h03000000_01000000,
64'h79000000_04000000,
64'h03000000_00000000,
64'h72656c6c_6f72746e,
64'h6f632d74_70757272,
64'h65746e69_01000000,
64'h80f0fa02_69000000,
64'h04000000_03000000,
64'h00003933_76732c76,
64'h63736972_60000000,
64'h0b000000_03000000,
64'h00636d69_34367672,
64'h56000000_08000000,
64'h03000000_00000076,
64'h63736972_1b000000,
64'h06000000_03000000,
64'h00000000_79616b6f,
64'h4f000000_05000000,
64'h03000000_00000000,
64'h4b000000_04000000,
64'h03000000_00757063,
64'h3f000000_04000000,
64'h03000000_00000030,
64'h40757063_01000000,
64'h40787d01_2c000000,
64'h04000000_03000000,
64'h00000000_0f000000,
64'h04000000_03000000,
64'h01000000_00000000,
64'h04000000_03000000,
64'h00000000_73757063,
64'h01000000_00657261,
64'h622d656e_61697261,
64'h2c687465_26000000,
64'h10000000_03000000,
64'h00766564_2d657261,
64'h622d656e_61697261,
64'h2c687465_1b000000,
64'h14000000_03000000,
64'h02000000_0f000000,
64'h04000000_03000000,
64'h02000000_00000000,
64'h04000000_03000000,
64'h00000000_01000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'hc8040000_12010000,
64'h00000000_10000000,
64'h11000000_28000000,
64'h00050000_38000000,
64'h12060000_edfe0dd0,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_0000bff5,
64'h10500073_03c58593,
64'h00000597_f1402573,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00008402_07458593,
64'h00000597_f1402573,
64'h01f41413_0010041b
};
logic [$clog2(RomSize)-1:0] addr_q;
always_ff @(posedge clk_i) begin
if (req_i) begin
addr_q <= addr_i[$clog2(RomSize)-1+3:3];
end
end
assign rdata_o = mem[addr_q];
endmodule

1
fpga/bootrom/gen_rom.py Symbolic link
View file

@ -0,0 +1 @@
../../bootrom/gen_rom.py

1
fpga/bootrom/linker.ld Symbolic link
View file

@ -0,0 +1 @@
../../bootrom/linker.ld

58
fpga/fan_ctrl.sv Normal file
View file

@ -0,0 +1,58 @@
// 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.
// Description: PWM Fan VDD
module fan_ctrl (
input logic clk_i,
input logic rst_ni,
input logic [3:0] pwm_setting_i,
output logic fan_pwm_o
);
logic [3:0] ms_clock_d, ms_clock_q;
logic [19:0] cycle_counter_d, cycle_counter_q;
// clock divider
always_comb begin
cycle_counter_d = cycle_counter_q;
ms_clock_d = ms_clock_q;
// divide clock by 499999
if (cycle_counter_q == 499999) begin
cycle_counter_d = 0;
ms_clock_d = ms_clock_q + 1;
end else begin
cycle_counter_d = cycle_counter_q + 1;
end
if (ms_clock_q == 15) begin
ms_clock_d = 0;
end
end
// duty cycle
always_comb begin
if (ms_clock_q < pwm_setting_i) begin
fan_pwm_o = 1'b1;
end else begin
fan_pwm_o = 1'b0;
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
ms_clock_q <= '0;
cycle_counter_q <= '0;
end else begin
ms_clock_q <= ms_clock_d;
cycle_counter_q <= '0;
end
end
endmodule

View file

@ -1,26 +1,40 @@
## Buttons
set_property -dict { PACKAGE_PIN R19 IOSTANDARD LVCMOS33 } [get_ports { cpu_resetn }]; #IO_0_14 Sch=cpu_resetn
set_property -dict {PACKAGE_PIN R19 IOSTANDARD LVCMOS33} [get_ports cpu_resetn]
## PMOD Header JC
set_property -dict { PACKAGE_PIN AC26 IOSTANDARD LVCMOS33 } [get_ports { tck }]; #IO_L19P_T3_13 Sch=jc[1]
set_property -dict { PACKAGE_PIN AJ27 IOSTANDARD LVCMOS33 } [get_ports { tdi }]; #IO_L20P_T3_13 Sch=jc[2]
set_property -dict { PACKAGE_PIN AH30 IOSTANDARD LVCMOS33 } [get_ports { tdo }]; #IO_L18N_T2_13 Sch=jc[3]
set_property -dict { PACKAGE_PIN AK29 IOSTANDARD LVCMOS33 } [get_ports { tms }]; #IO_L15P_T2_DQS_13 Sch=jc[4]
set_property -dict { PACKAGE_PIN AD26 IOSTANDARD LVCMOS33 } [get_ports { trst_n }]; #IO_L19N_T3_VREF_13 Sch=jc[7]
set_property -dict {PACKAGE_PIN AC26 IOSTANDARD LVCMOS33} [get_ports tck]
set_property -dict {PACKAGE_PIN AJ27 IOSTANDARD LVCMOS33} [get_ports tdi]
set_property -dict {PACKAGE_PIN AH30 IOSTANDARD LVCMOS33} [get_ports tdo]
set_property -dict {PACKAGE_PIN AK29 IOSTANDARD LVCMOS33} [get_ports tms]
set_property -dict {PACKAGE_PIN AD26 IOSTANDARD LVCMOS33} [get_ports trst_n]
## UART
set_property -dict { PACKAGE_PIN Y23 IOSTANDARD LVCMOS33 } [get_ports { tx }]; #IO_L1P_T0_12 Sch=uart_rx_out
set_property -dict { PACKAGE_PIN Y20 IOSTANDARD LVCMOS33 } [get_ports { rx }]; #IO_0_12 Sch=uart_tx_in
set_property -dict {PACKAGE_PIN Y23 IOSTANDARD LVCMOS33} [get_ports tx]
set_property -dict {PACKAGE_PIN Y20 IOSTANDARD LVCMOS33} [get_ports rx]
# accept sub-optimal placement
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets tck_IBUF]
## LEDs
set_property -dict { PACKAGE_PIN T28 IOSTANDARD LVCMOS33 } [get_ports { led[0] }]; #IO_L11N_T1_SRCC_14 Sch=led[0]
set_property -dict { PACKAGE_PIN V19 IOSTANDARD LVCMOS33 } [get_ports { led[1] }]; #IO_L19P_T3_A10_D26_14 Sch=led[1]
set_property -dict { PACKAGE_PIN U30 IOSTANDARD LVCMOS33 } [get_ports { led[2] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=led[2]
set_property -dict { PACKAGE_PIN U29 IOSTANDARD LVCMOS33 } [get_ports { led[3] }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=led[3]
set_property -dict { PACKAGE_PIN V20 IOSTANDARD LVCMOS33 } [get_ports { led[4] }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=led[4]
set_property -dict { PACKAGE_PIN V26 IOSTANDARD LVCMOS33 } [get_ports { led[5] }]; #IO_L16P_T2_CSI_B_14 Sch=led[5]
set_property -dict { PACKAGE_PIN W24 IOSTANDARD LVCMOS33 } [get_ports { led[6] }]; #IO_L20N_T3_A07_D23_14 Sch=led[6]
set_property -dict { PACKAGE_PIN W23 IOSTANDARD LVCMOS33 } [get_ports { led[7] }]; #IO_L20P_T3_A08_D24_14 Sch=led[7]
set_property -dict {PACKAGE_PIN T28 IOSTANDARD LVCMOS33} [get_ports {led[0]}]
set_property -dict {PACKAGE_PIN V19 IOSTANDARD LVCMOS33} [get_ports {led[1]}]
set_property -dict {PACKAGE_PIN U30 IOSTANDARD LVCMOS33} [get_ports {led[2]}]
set_property -dict {PACKAGE_PIN U29 IOSTANDARD LVCMOS33} [get_ports {led[3]}]
set_property -dict {PACKAGE_PIN V20 IOSTANDARD LVCMOS33} [get_ports {led[4]}]
set_property -dict {PACKAGE_PIN V26 IOSTANDARD LVCMOS33} [get_ports {led[5]}]
set_property -dict {PACKAGE_PIN W24 IOSTANDARD LVCMOS33} [get_ports {led[6]}]
set_property -dict {PACKAGE_PIN W23 IOSTANDARD LVCMOS33} [get_ports {led[7]}]
## Switches
set_property -dict { PACKAGE_PIN G19 IOSTANDARD LVCMOS12 } [get_ports { sw[0] }]; #IO_0_17 Sch=sw[0]
set_property -dict { PACKAGE_PIN G25 IOSTANDARD LVCMOS12 } [get_ports { sw[1] }]; #IO_25_16 Sch=sw[1]
set_property -dict { PACKAGE_PIN H24 IOSTANDARD LVCMOS12 } [get_ports { sw[2] }]; #IO_L19P_T3_16 Sch=sw[2]
set_property -dict { PACKAGE_PIN K19 IOSTANDARD LVCMOS12 } [get_ports { sw[3] }]; #IO_L6P_T0_17 Sch=sw[3]
set_property -dict { PACKAGE_PIN N19 IOSTANDARD LVCMOS12 } [get_ports { sw[4] }]; #IO_L19P_T3_A22_15 Sch=sw[4]
set_property -dict { PACKAGE_PIN P19 IOSTANDARD LVCMOS12 } [get_ports { sw[5] }]; #IO_25_15 Sch=sw[5]
set_property -dict { PACKAGE_PIN P26 IOSTANDARD LVCMOS33 } [get_ports { sw[6] }]; #IO_L10P_T1_D14_14 Sch=sw[6]
set_property -dict { PACKAGE_PIN P27 IOSTANDARD LVCMOS33 } [get_ports { sw[7] }]; #IO_L8P_T1_D11_14 Sch=sw[7]
## Fan Control
set_property -dict { PACKAGE_PIN W19 IOSTANDARD LVCMOS33 } [get_ports { fan_pwm }]; #IO_25_14 Sch=fan_pwm
#set_property -dict { PACKAGE_PIN V21 IOSTANDARD LVCMOS33 } [get_ports { FAN_TACH }]; #IO_L22P_T3_A05_D21_14 Sch=fan_tac

View file

@ -42,7 +42,7 @@ package ariane_pkg;
| (1 << 20) // U - User mode implemented
| (0 << 23) // X - Non-standard extensions present
| (1 << 63); // RV64
localparam ENABLE_RENAME = 1'b1;
localparam ENABLE_RENAME = 1'b0;
// 32 registers + 1 bit for re-naming = 6
localparam REG_ADDR_SIZE = 6;

View file

@ -15,7 +15,7 @@
import ariane_pkg::*;
`ifndef verilator
`ifndef SYNTHESIS
// import instruction_tracer_pkg::*;
import instruction_tracer_pkg::*;
`endif
`endif
@ -566,109 +566,109 @@ module ariane #(
// -------------------
// Instruction Tracer
// -------------------
// `ifndef SYNTHESIS
// `ifndef verilator
// instruction_tracer_if tracer_if (clk_i);
// // assign instruction tracer interface
// // control signals
// assign tracer_if.rstn = rst_ni;
// assign tracer_if.flush_unissued = flush_unissued_instr_ctrl_id;
// assign tracer_if.flush = flush_ctrl_ex;
// // fetch
// assign tracer_if.instruction = id_stage_i.compressed_decoder_i.instr_o;
// assign tracer_if.fetch_valid = id_stage_i.instr_realigner_i.fetch_entry_valid_o;
// assign tracer_if.fetch_ack = id_stage_i.instr_realigner_i.fetch_ack_i;
// // Issue
// assign tracer_if.issue_ack = issue_stage_i.i_scoreboard.issue_ack_i;
// assign tracer_if.issue_sbe = issue_stage_i.i_scoreboard.issue_instr_o;
// // write-back
// assign tracer_if.waddr = waddr_commit_id;
// assign tracer_if.wdata = wdata_commit_id;
// assign tracer_if.we = we_commit_id;
// // commit
// assign tracer_if.commit_instr = commit_instr_id_commit;
// assign tracer_if.commit_ack = commit_ack;
// // branch predict
// assign tracer_if.resolve_branch = resolved_branch;
// // address translation
// // stores
// assign tracer_if.st_valid = ex_stage_i.lsu_i.i_store_unit.store_buffer_i.valid_i;
// assign tracer_if.st_paddr = ex_stage_i.lsu_i.i_store_unit.store_buffer_i.paddr_i;
// // loads
// assign tracer_if.ld_valid = ex_stage_i.lsu_i.i_load_unit.req_port_o.tag_valid;
// assign tracer_if.ld_kill = ex_stage_i.lsu_i.i_load_unit.req_port_o.kill_req;
// assign tracer_if.ld_paddr = ex_stage_i.lsu_i.i_load_unit.paddr_i;
// // exceptions
// assign tracer_if.exception = commit_stage_i.exception_o;
// // assign current privilege level
// assign tracer_if.priv_lvl = priv_lvl;
// assign tracer_if.debug_mode = debug_mode;
// instr_tracer instr_tracer_i (tracer_if, cluster_id_i, core_id_i);
`ifndef SYNTHESIS
`ifndef verilator
instruction_tracer_if tracer_if (clk_i);
// assign instruction tracer interface
// control signals
assign tracer_if.rstn = rst_ni;
assign tracer_if.flush_unissued = flush_unissued_instr_ctrl_id;
assign tracer_if.flush = flush_ctrl_ex;
// fetch
assign tracer_if.instruction = id_stage_i.compressed_decoder_i.instr_o;
assign tracer_if.fetch_valid = id_stage_i.instr_realigner_i.fetch_entry_valid_o;
assign tracer_if.fetch_ack = id_stage_i.instr_realigner_i.fetch_ack_i;
// Issue
assign tracer_if.issue_ack = issue_stage_i.i_scoreboard.issue_ack_i;
assign tracer_if.issue_sbe = issue_stage_i.i_scoreboard.issue_instr_o;
// write-back
assign tracer_if.waddr = waddr_commit_id;
assign tracer_if.wdata = wdata_commit_id;
assign tracer_if.we = we_commit_id;
// commit
assign tracer_if.commit_instr = commit_instr_id_commit;
assign tracer_if.commit_ack = commit_ack;
// branch predict
assign tracer_if.resolve_branch = resolved_branch;
// address translation
// stores
assign tracer_if.st_valid = ex_stage_i.lsu_i.i_store_unit.store_buffer_i.valid_i;
assign tracer_if.st_paddr = ex_stage_i.lsu_i.i_store_unit.store_buffer_i.paddr_i;
// loads
assign tracer_if.ld_valid = ex_stage_i.lsu_i.i_load_unit.req_port_o.tag_valid;
assign tracer_if.ld_kill = ex_stage_i.lsu_i.i_load_unit.req_port_o.kill_req;
assign tracer_if.ld_paddr = ex_stage_i.lsu_i.i_load_unit.paddr_i;
// exceptions
assign tracer_if.exception = commit_stage_i.exception_o;
// assign current privilege level
assign tracer_if.priv_lvl = priv_lvl;
assign tracer_if.debug_mode = debug_mode;
instr_tracer instr_tracer_i (tracer_if, cluster_id_i, core_id_i);
// program instr_tracer (
// instruction_tracer_if tracer_if,
// input logic [5:0] cluster_id_i,
// input logic [3:0] core_id_i
// );
program instr_tracer (
instruction_tracer_if tracer_if,
input logic [5:0] cluster_id_i,
input logic [3:0] core_id_i
);
// instruction_tracer it = new (tracer_if, 1'b0);
instruction_tracer it = new (tracer_if, 1'b0);
// initial begin
// #15ns;
// it.create_file(cluster_id_i, core_id_i);
// it.trace();
// end
initial begin
#15ns;
it.create_file(cluster_id_i, core_id_i);
it.trace();
end
// final begin
// it.close();
// end
// endprogram
// // mock tracer for Verilator, to be used with spike-dasm
// `else
final begin
it.close();
end
endprogram
// mock tracer for Verilator, to be used with spike-dasm
`else
// int f;
// logic [63:0] cycles;
int f;
logic [63:0] cycles;
// initial begin
// f = $fopen("trace_core_00_0.dasm", "w");
// end
initial begin
f = $fopen("trace_core_00_0.dasm", "w");
end
// always_ff @(posedge clk_i or negedge rst_ni) begin
// if (~rst_ni) begin
// cycles <= 0;
// end else begin
// string mode = "";
// if (debug_mode) mode = "D";
// else begin
// case (priv_lvl)
// riscv::PRIV_LVL_M: mode = "M";
// riscv::PRIV_LVL_S: mode = "S";
// riscv::PRIV_LVL_U: mode = "U";
// endcase
// end
// for (int i = 0; i < NR_COMMIT_PORTS; i++) begin
// if (commit_ack[i] && !commit_instr_id_commit[i].ex.valid) begin
// $fwrite(f, "%d 0x%0h %s (0x%h) DASM(%h)\n", cycles, commit_instr_id_commit[i].pc, mode, commit_instr_id_commit[i].ex.tval[31:0], commit_instr_id_commit[i].ex.tval[31:0]);
// end else if (commit_ack[i] && commit_instr_id_commit[i].ex.valid) begin
// if (commit_instr_id_commit[i].ex.cause == 2) begin
// $fwrite(f, "Exception Cause: Illegal Instructions, DASM(%h) PC=%h\n", commit_instr_id_commit[i].ex.tval[31:0], commit_instr_id_commit[i].pc);
// end else begin
// if (debug_mode) begin
// $fwrite(f, "%d 0x%0h %s (0x%h) DASM(%h)\n", cycles, commit_instr_id_commit[i].pc, mode, commit_instr_id_commit[i].ex.tval[31:0], commit_instr_id_commit[i].ex.tval[31:0]);
// end else begin
// $fwrite(f, "Exception Cause: %5d, DASM(%h) PC=%h\n", commit_instr_id_commit[i].ex.cause, commit_instr_id_commit[i].ex.tval[31:0], commit_instr_id_commit[i].pc);
// end
// end
// end
// end
// cycles <= cycles + 1;
// end
// end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
cycles <= 0;
end else begin
string mode = "";
if (debug_mode) mode = "D";
else begin
case (priv_lvl)
riscv::PRIV_LVL_M: mode = "M";
riscv::PRIV_LVL_S: mode = "S";
riscv::PRIV_LVL_U: mode = "U";
endcase
end
for (int i = 0; i < NR_COMMIT_PORTS; i++) begin
if (commit_ack[i] && !commit_instr_id_commit[i].ex.valid) begin
$fwrite(f, "%d 0x%0h %s (0x%h) DASM(%h)\n", cycles, commit_instr_id_commit[i].pc, mode, commit_instr_id_commit[i].ex.tval[31:0], commit_instr_id_commit[i].ex.tval[31:0]);
end else if (commit_ack[i] && commit_instr_id_commit[i].ex.valid) begin
if (commit_instr_id_commit[i].ex.cause == 2) begin
$fwrite(f, "Exception Cause: Illegal Instructions, DASM(%h) PC=%h\n", commit_instr_id_commit[i].ex.tval[31:0], commit_instr_id_commit[i].pc);
end else begin
if (debug_mode) begin
$fwrite(f, "%d 0x%0h %s (0x%h) DASM(%h)\n", cycles, commit_instr_id_commit[i].pc, mode, commit_instr_id_commit[i].ex.tval[31:0], commit_instr_id_commit[i].ex.tval[31:0]);
end else begin
$fwrite(f, "Exception Cause: %5d, DASM(%h) PC=%h\n", commit_instr_id_commit[i].ex.cause, commit_instr_id_commit[i].ex.tval[31:0], commit_instr_id_commit[i].pc);
end
end
end
end
cycles <= cycles + 1;
end
end
// final begin
// $fclose(f);
// end
// `endif
// `endif
final begin
$fclose(f);
end
`endif
`endif
endmodule // ariane

View file

@ -34,11 +34,11 @@ package ariane_soc;
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;
localparam logic[63:0] DebugLength = 64'h1000;
localparam logic[63:0] ROMLength = 64'h1000;
localparam logic[63:0] CLINTLength = 64'hC0000;
// TODO(zarubaf): Put PLIC back 0x4000000
localparam logic[63:0] PLICLength = 64'h40_0000;
localparam logic[63:0] UARTLength = 64'h10000;
localparam logic[63:0] DRAMLength = 64'h4000000;
endpackage

View file

@ -19,6 +19,12 @@ import uvm_pkg::*;
`include "uvm_macros.svh"
`define MAIN_MEM(P) dut.i_sram.genblk1[0].i_ram.Mem_DP[(``P``)]
import "DPI-C" function read_elf(input string filename);
import "DPI-C" function byte get_section(output longint address, output longint len);
import "DPI-C" context function byte read_section(input longint address, inout byte buffer[]);
module ariane_tb;
// static uvm_cmdline_processor uvcl = uvm_cmdline_processor::get_inst();
@ -27,6 +33,7 @@ module ariane_tb;
// toggle with half the clock period
localparam int unsigned RTC_CLOCK_PERIOD = CLOCK_PERIOD/2;
localparam NUM_WORDS = 2**25;
logic clk_i;
logic rst_ni;
logic rtc_i;
@ -36,7 +43,9 @@ module ariane_tb;
logic [31:0] exit_o;
ariane_testharness dut (
ariane_testharness #(
.NUM_WORDS ( NUM_WORDS )
) dut (
.clk_i,
.rst_ni,
.rtc_i,
@ -83,4 +92,39 @@ module ariane_tb;
end
end
initial begin
automatic string BINARY = "/scratch/zarubaf/ariane/fpga/bbl";
automatic logic [7:0][7:0] mem_row;
longint address, len;
byte buffer[];
`uvm_info( "Core Test", "Zeroing memory", UVM_LOW)
// avoid X pesimism
for (int i = 0; i < NUM_WORDS; i++) begin
`MAIN_MEM(i) = '0;
end
`uvm_info( "Core Test", $sformatf("Loading ELF: %s", BINARY), UVM_LOW)
void'(read_elf(BINARY));
// while there are more sections to process
while (get_section(address, len)) begin
`uvm_info( "Core Test", $sformatf("Loading Address: %x, Length: %x", address, len), UVM_LOW)
buffer = new [len];
void'(read_section(address, buffer));
// preload memories
// 64-bit
for (int i = 0; i < buffer.size()/8; i++) begin
mem_row = '0;
for (int j = 0; j < 8; j++) begin
mem_row[j] = buffer[i*8 + j];
end
`MAIN_MEM((address[28:0] >> 3) + i) = mem_row;
end
end
end
endmodule

View file

@ -14,18 +14,18 @@
// Instantiates an AXI-Bus and memories
module ariane_testharness #(
parameter logic [63:0] CACHE_START_ADDR = 64'h8000_0000, // address on which to decide whether the request is cache-able or not
parameter int unsigned AXI_ID_WIDTH = 10,
parameter int unsigned AXI_USER_WIDTH = 1,
parameter int unsigned AXI_ADDRESS_WIDTH = 64,
parameter int unsigned AXI_DATA_WIDTH = 64,
parameter int unsigned NUM_WORDS = 2**24 // memory size
)(
input logic clk_i,
input logic rtc_i,
input logic rst_ni,
output logic [31:0] exit_o
);
parameter logic [63:0] CACHE_START_ADDR = 64'h8000_0000, // address on which to decide whether the request is cache-able or not
parameter int unsigned AXI_ID_WIDTH = 10,
parameter int unsigned AXI_USER_WIDTH = 1,
parameter int unsigned AXI_ADDRESS_WIDTH = 64,
parameter int unsigned AXI_DATA_WIDTH = 64,
parameter int unsigned NUM_WORDS = 2**25 // memory size
)(
input logic clk_i,
input logic rtc_i,
input logic rst_ni,
output logic [31:0] exit_o
);
// disable test-enable
logic test_en;
@ -296,6 +296,16 @@ module ariane_testharness #(
// ---------------
logic ipi;
logic timer_irq;
logic rtc;
// divide clock by two
always_ff @(posedge clk_i or negedge ndmreset_n) begin
if (~ndmreset_n) begin
rtc <= 0;
end else begin
rtc <= rtc ^ 1'b1;
end
end
clint #(
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
@ -304,9 +314,9 @@ module ariane_testharness #(
.NR_CORES ( 1 )
) i_clint (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.rst_ni ( ndmreset_n ),
.slave ( master[ariane_soc::CLINT] ),
.rtc_i,
.rtc_i ( rtc ),
.timer_irq_o ( timer_irq ),
.ipi_o ( ipi )
);
@ -317,11 +327,34 @@ module ariane_testharness #(
logic [ariane_soc::NumTargets-1:0] irqs;
logic [ariane_soc::NumSources-1:0] irq_sources;
AXI_LITE #(
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH )
) axi_lite_plic ();
REG_BUS #(
.ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.DATA_WIDTH ( AXI_DATA_WIDTH )
) reg_bus (clk_i);
axi_to_axi_lite i_axi_to_axi_lite_eth (
.clk_i,
.rst_ni,
.testmode_i ( 1'b0 ),
.in ( master[ariane_soc::PLIC] ),
.out ( axi_lite_plic )
);
axi_lite_to_reg #(
.ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.DATA_WIDTH ( AXI_DATA_WIDTH )
) i_axi_lite_to_reg (
.clk_i,
.rst_ni,
.axi_i ( axi_lite_plic ), // AXI Lite
.reg_o ( reg_bus )
);
plic #(
.ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.DATA_WIDTH ( AXI_DATA_WIDTH ),
@ -340,14 +373,9 @@ module ariane_testharness #(
// ---------------
// Peripheral
// ---------------
mock_uartlite i_mock_uartlite (.clk_i(clk_i), .rst_ni(rst_ni), .slave(master[ariane_soc::UART]));
// 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

View file

@ -0,0 +1,74 @@
// 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
// Date: 28/09/2018
// Description: Mock replacement for UART in testbench
module mock_uartlite (
input logic clk_i, // Clock
input logic rst_ni,
AXI_BUS.Slave slave
);
// string buffer
byte buffer [$];
function void flush();
string s;
// dump the buffer out the whole buffer
foreach (buffer[i]) begin
s = $sformatf("%s%c",s, buffer[i]);
end
$display(s);
// clear buffer afterwards
buffer = {};
endfunction : flush
// put a char to the buffer
function void append(byte ch);
// wait for the new line
if (ch == 8'hA)
flush();
else
buffer.push_back(ch);
endfunction : append
logic req_o;
logic we_o;
logic [63:0] addr_o;
logic [64/8-1:0] be_o;
logic [63:0] data_o;
axi2mem #(
.AXI_ID_WIDTH($bits(slave.aw_id)),
.AXI_USER_WIDTH($bits(slave.aw_user))
) i_axi2mem (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.slave ( slave ),
.req_o ( req_o ),
.we_o ( we_o ),
.addr_o ( addr_o ),
.be_o ( be_o ),
.data_o ( data_o ),
.data_i ( '0 )
);
always_ff @(posedge clk_i or negedge rst_ni) begin
if (rst_ni) begin
if (req_o & we_o & addr_o[3:0] == 'h4) append(byte'(data_o[40:32]));
end
end
endmodule

View file

@ -13,17 +13,14 @@
// Description: This module takes data over UART and prints them to the console
// A string is printed to the console as soon as a '\n' character is found
interface uart_bus
#(
interface uart_bus #(
parameter BAUD_RATE = 115200,
parameter PARITY_EN = 0
)
(
)(
input logic rx,
output logic tx,
input logic rx_en
);
);
localparam BIT_PERIOD = (1000000000/BAUD_RATE*1000);

138
tb/dpi/elfloader.cc Normal file
View file

@ -0,0 +1,138 @@
// #include "elfloader.h"
#include <fesvr/elf.h>
#include <fesvr/memif.h>
#include <svdpi.h>
#include <cstring>
#include <string>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <assert.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <map>
#include <iostream>
#define SHT_PROGBITS 0x1
#define SHT_GROUP 0x11
// address and size
std::vector<std::pair<reg_t, reg_t>> sections;
std::map<std::string, uint64_t> symbols;
// memory based address and content
std::map<reg_t, std::vector<uint8_t>> mems;
reg_t entry;
int section_index = 0;
void write (uint64_t address, uint64_t len, uint8_t* buf) {
uint64_t datum;
std::vector<uint8_t> mem;
for (int i = 0; i < len; i++) {
mem.push_back(buf[i]);
}
mems.insert(std::make_pair(address, mem));
}
// Communicate the section address and len
// Returns:
// 0 if there are no more sections
// 1 if there are more sections to load
extern "C" char get_section (long long* address, long long* len) {
if (section_index < sections.size()) {
*address = sections[section_index].first;
*len = sections[section_index].second;
section_index++;
return 1;
} else return 0;
}
extern "C" char read_section (long long address, const svOpenArrayHandle buffer) {
// get actual poitner
void* buf = svGetArrayPtr(buffer);
// check that the address points to a section
assert(mems.count(address) > 0);
// copy array
int i = 0;
for (auto &datum : mems.find(address)->second) {
*((char *) buf + i) = datum;
i++;
}
}
extern "C" void read_elf(const char* filename) {
int fd = open(filename, O_RDONLY);
struct stat s;
assert(fd != -1);
if (fstat(fd, &s) < 0)
abort();
size_t size = s.st_size;
char* buf = (char*)mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
assert(buf != MAP_FAILED);
close(fd);
assert(size >= sizeof(Elf64_Ehdr));
const Elf64_Ehdr* eh64 = (const Elf64_Ehdr*)buf;
assert(IS_ELF32(*eh64) || IS_ELF64(*eh64));
std::vector<uint8_t> zeros;
std::map<std::string, uint64_t> symbols;
#define LOAD_ELF(ehdr_t, phdr_t, shdr_t, sym_t) do { \
ehdr_t* eh = (ehdr_t*)buf; \
phdr_t* ph = (phdr_t*)(buf + eh->e_phoff); \
entry = eh->e_entry; \
assert(size >= eh->e_phoff + eh->e_phnum*sizeof(*ph)); \
for (unsigned i = 0; i < eh->e_phnum; i++) { \
if(ph[i].p_type == PT_LOAD && ph[i].p_memsz) { \
if (ph[i].p_filesz) { \
assert(size >= ph[i].p_offset + ph[i].p_filesz); \
sections.push_back(std::make_pair(ph[i].p_paddr, ph[i].p_memsz)); \
write(ph[i].p_paddr, ph[i].p_filesz, (uint8_t*)buf + ph[i].p_offset); \
} \
zeros.resize(ph[i].p_memsz - ph[i].p_filesz); \
} \
} \
shdr_t* sh = (shdr_t*)(buf + eh->e_shoff); \
assert(size >= eh->e_shoff + eh->e_shnum*sizeof(*sh)); \
assert(eh->e_shstrndx < eh->e_shnum); \
assert(size >= sh[eh->e_shstrndx].sh_offset + sh[eh->e_shstrndx].sh_size); \
char *shstrtab = buf + sh[eh->e_shstrndx].sh_offset; \
unsigned strtabidx = 0, symtabidx = 0; \
for (unsigned i = 0; i < eh->e_shnum; i++) { \
unsigned max_len = sh[eh->e_shstrndx].sh_size - sh[i].sh_name; \
if ((sh[i].sh_type & SHT_GROUP) && strcmp(shstrtab + sh[i].sh_name, ".strtab") != 0 && strcmp(shstrtab + sh[i].sh_name, ".shstrtab") != 0) \
assert(strnlen(shstrtab + sh[i].sh_name, max_len) < max_len); \
if (sh[i].sh_type & SHT_PROGBITS) continue; \
assert(size >= sh[i].sh_offset + sh[i].sh_size); \
if (strcmp(shstrtab + sh[i].sh_name, ".strtab") == 0) \
strtabidx = i; \
if (strcmp(shstrtab + sh[i].sh_name, ".symtab") == 0) \
symtabidx = i; \
} \
if (strtabidx && symtabidx) { \
char* strtab = buf + sh[strtabidx].sh_offset; \
sym_t* sym = (sym_t*)(buf + sh[symtabidx].sh_offset); \
for (unsigned i = 0; i < sh[symtabidx].sh_size/sizeof(sym_t); i++) { \
unsigned max_len = sh[strtabidx].sh_size - sym[i].st_name; \
assert(sym[i].st_name < sh[strtabidx]. sh_size); \
assert(strnlen(strtab + sym[i].st_name, max_len) < max_len); \
symbols[strtab + sym[i].st_name] = sym[i].st_value; \
} \
} \
} while(0)
if (IS_ELF32(*eh64))
LOAD_ELF(Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Sym);
else
LOAD_ELF(Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Sym);
munmap(buf, size);
}