add test of verilator in one folder

This commit is contained in:
Colin 2021-12-16 12:07:50 +00:00
parent 87c23b9952
commit 911f65874f
13 changed files with 6783 additions and 0 deletions

4
.gitignore vendored
View File

@ -2,6 +2,7 @@
*.log *.log
RCS RCS
*~ *~
.vscode
.*.swp .*.swp
.*.swo .*.swo
.DS_Store .DS_Store
@ -46,3 +47,6 @@ unit_level_testbench/pic/workspace/simulation/sim
tools/codegenerators/AAPGV2/swerv/asm/out* tools/codegenerators/AAPGV2/swerv/asm/out*
tools/codegenerators/AAPGV2/swerv/bin/out* tools/codegenerators/AAPGV2/swerv/bin/out*
tools/codegenerators/AAPGV2/swerv/objdump/out* tools/codegenerators/AAPGV2/swerv/objdump/out*
obj_dir
build

2267
test/helloworld/JSON.pm Normal file

File diff suppressed because it is too large Load Diff

90
test/helloworld/Makefile Normal file
View File

@ -0,0 +1,90 @@
export RV_ROOT = ${PWD}/../..
RV_DESIGN = ${RV_ROOT}/design
TEST_CFLAGS = -g -O3 -funroll-all-loops
ABI = -mabi=ilp32 -march=rv32imc
# Allow snapshot override
target = default
# Allow tool override
VERILATOR = verilator
GCC_PREFIX = /opt/riscv/bin/riscv64-unknown-elf
TESTDIR = ${PWD}
BUILD_DIR = ${TESTDIR}/build
SWERV_CONFIG = ${TESTDIR}/swerv.config
TEST = hello_world
ifdef debug
DEBUG_PLUS = +dumpon
VERILATOR_DEBUG = --trace
endif
LINK = $(TESTDIR)/link.ld
OFILES = $(TEST).o
VPATH = $(BUILD_DIR) $(TESTDIR)
TESTFILES = $(TESTDIR)/tb_top.sv $(TESTDIR)/ahb_sif.sv
defines = $(BUILD_DIR)/common_defines.vh ${RV_DESIGN}/include/swerv_types.sv
includes = -I${RV_DESIGN}/include -I${RV_DESIGN}/lib -I${BUILD_DIR}
# CFLAGS for verilator generated Makefiles. Without -std=c++11 it complains for `auto` variables
CFLAGS += "-std=c++11"
# Optimization for better performance; alternative is nothing for slower runtime (faster compiles)
# -O2 for faster runtime (slower compiles), or -O for balance.
VERILATOR_MAKE_FLAGS = OPT_FAST="-Os"
# Targets
all: clean verilator
clean:
rm -rf build obj_dir
# *.log *.hex *.dis *.tbl simv* *.map snapshots \
# verilator* *.exe obj* *.o hello_world.cpp.s ucli.key vc_hdrs.h csrc *.csv \
# work dataset.asdb library.cfg hello_world.o
# If define files do not exist, then run swerv.config.
${BUILD_DIR}/defines.h :
BUILD_PATH=${BUILD_DIR} ${SWERV_CONFIG} -target=$(target) -set iccm_enable
##################### Verilog Builds #####################################
verilator-build: ${TESTFILES} ${BUILD_DIR}/defines.h test_tb_top.cpp
echo '`undef ASSERT_ON' >> ${BUILD_DIR}/common_defines.vh
$(VERILATOR) --cc -CFLAGS ${CFLAGS} $(defines) $(includes) \
-Wno-UNOPTFLAT \
-I${TESTDIR} \
-f ${TESTDIR}/flist \
${TESTFILES} \
--top-module tb_top -exe test_tb_top.cpp --autoflush $(VERILATOR_DEBUG)
cp ${TESTDIR}/test_tb_top.cpp obj_dir
$(MAKE) -j -C obj_dir/ -f Vtb_top.mk $(VERILATOR_MAKE_FLAGS)
##################### Simulation Runs #####################################
verilator: program.hex verilator-build
cd build && ../obj_dir/Vtb_top ${DEBUG_PLUS}
##################### Test Build #####################################
program.hex: $(OFILES) $(LINK)
@echo Building $(TEST)
$(GCC_PREFIX)-gcc $(ABI) -Wl,-Map=$(BUILD_DIR)/$(TEST).map -lgcc -T$(LINK) -o $(BUILD_DIR)/$(TEST).exe $(BUILD_DIR)/$(OFILES) -nostartfiles $(TEST_LIBS)
$(GCC_PREFIX)-objcopy -O verilog $(BUILD_DIR)/$(TEST).exe $(BUILD_DIR)/program.hex
$(GCC_PREFIX)-objdump -S $(BUILD_DIR)/$(TEST).exe > $(BUILD_DIR)/$(TEST).dis
@echo Completed building $(TEST)
%.o : %.s ${BUILD_DIR}/defines.h
$(GCC_PREFIX)-cpp -I${BUILD_DIR} $< > $(BUILD_DIR)/$*.cpp.s
$(GCC_PREFIX)-as $(ABI) $(BUILD_DIR)/$*.cpp.s -o $(BUILD_DIR)/$@
%.o : %.c ${BUILD_DIR}/defines.h
$(GCC_PREFIX)-gcc -I${BUILD_DIR} ${TEST_CFLAGS} ${ABI} -nostdlib -c $< -o $(BUILD_DIR)/$@
help:
@echo Possible targets: verilator help clean all verilator-build program.hex
.PHONY: help clean verilator

View File

@ -0,0 +1,225 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2019 Western Digital Corporation or its affiliates.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the 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.
//
`ifdef RV_BUILD_AHB_LITE
module ahb_sif (
input logic [63:0] HWDATA,
input logic HCLK,
input logic HSEL,
input logic [3:0] HPROT,
input logic HWRITE,
input logic [1:0] HTRANS,
input logic [2:0] HSIZE,
input logic HREADY,
input logic HRESETn,
input logic [31:0] HADDR,
input logic [2:0] HBURST,
output logic HREADYOUT,
output logic HRESP,
output logic [63:0] HRDATA
);
parameter MAILBOX_ADDR = 32'hD0580000;
logic write;
logic [31:0] laddr, addr;
logic [7:0] strb_lat;
logic [63:0] rdata;
bit [7:0] mem [bit[31:0]];
bit [7:0] wscnt;
int dws = 0;
int iws = 0;
bit dws_rand;
bit iws_rand;
bit ok;
// Wires
wire [63:0] WriteData = HWDATA;
wire [7:0] strb = HSIZE == 3'b000 ? 8'h1 << HADDR[2:0] :
HSIZE == 3'b001 ? 8'h3 << {HADDR[2:1],1'b0} :
HSIZE == 3'b010 ? 8'hf << {HADDR[2],2'b0} : 8'hff;
wire mailbox_write = write && laddr==MAILBOX_ADDR;
initial begin
if ($value$plusargs("iws=%d", iws));
if ($value$plusargs("dws=%d", dws));
dws_rand = dws < 0;
iws_rand = iws < 0;
end
always @ (negedge HCLK ) begin
if(HREADY)
addr = HADDR;
if (write & HREADY) begin
if(strb_lat[7]) mem[{laddr[31:3],3'd7}] = HWDATA[63:56];
if(strb_lat[6]) mem[{laddr[31:3],3'd6}] = HWDATA[55:48];
if(strb_lat[5]) mem[{laddr[31:3],3'd5}] = HWDATA[47:40];
if(strb_lat[4]) mem[{laddr[31:3],3'd4}] = HWDATA[39:32];
if(strb_lat[3]) mem[{laddr[31:3],3'd3}] = HWDATA[31:24];
if(strb_lat[2]) mem[{laddr[31:3],3'd2}] = HWDATA[23:16];
if(strb_lat[1]) mem[{laddr[31:3],3'd1}] = HWDATA[15:08];
if(strb_lat[0]) mem[{laddr[31:3],3'd0}] = HWDATA[07:00];
end
if(HREADY & HSEL & |HTRANS) begin
`ifdef VERILATOR
if(iws_rand & ~HPROT[0])
iws = $random & 15;
if(dws_rand & HPROT[0])
dws = $random & 15;
`else
if(iws_rand & ~HPROT[0])
ok = std::randomize(iws) with {iws dist {0:=10, [1:3]:/2, [4:15]:/1};};
if(dws_rand & HPROT[0])
ok = std::randomize(dws) with {dws dist {0:=10, [1:3]:/2, [4:15]:/1};};
`endif
end
end
assign HRDATA = HREADY ? rdata : ~rdata;
assign HREADYOUT = wscnt == 0;
assign HRESP = 0;
always @(posedge HCLK or negedge HRESETn) begin
if(~HRESETn) begin
laddr <= 32'b0;
write <= 1'b0;
rdata <= '0;
wscnt <= 0;
end
else begin
if(HREADY & HSEL) begin
laddr <= HADDR;
write <= HWRITE & |HTRANS;
if(|HTRANS & ~HWRITE)
rdata <= {mem[{addr[31:3],3'd7}],
mem[{addr[31:3],3'd6}],
mem[{addr[31:3],3'd5}],
mem[{addr[31:3],3'd4}],
mem[{addr[31:3],3'd3}],
mem[{addr[31:3],3'd2}],
mem[{addr[31:3],3'd1}],
mem[{addr[31:3],3'd0}]};
strb_lat <= strb;
end
end
if(HREADY & HSEL & |HTRANS)
wscnt <= HPROT[0] ? dws[7:0] : iws[7:0];
else if(wscnt != 0)
wscnt <= wscnt-1;
end
endmodule
`endif
`ifdef RV_BUILD_AXI4
module axi_slv #(TAGW=1) (
input aclk,
input rst_l,
input arvalid,
output reg arready,
input [31:0] araddr,
input [TAGW-1:0] arid,
input [7:0] arlen,
input [1:0] arburst,
input [2:0] arsize,
output reg rvalid,
input rready,
output reg [63:0] rdata,
output reg [1:0] rresp,
output reg [TAGW-1:0] rid,
output rlast,
input awvalid,
output awready,
input [31:0] awaddr,
input [TAGW-1:0] awid,
input [7:0] awlen,
input [1:0] awburst,
input [2:0] awsize,
input [63:0] wdata,
input [7:0] wstrb,
input wvalid,
output wready,
output reg bvalid,
input bready,
output reg [1:0] bresp,
output reg [TAGW-1:0] bid
);
parameter MAILBOX_ADDR = 32'hD0580000;
parameter MEM_SIZE_DW = 8192;
bit [7:0] mem [bit[31:0]];
bit [63:0] memdata;
wire [63:0] WriteData;
wire mailbox_write;
assign mailbox_write = awvalid && awaddr==MAILBOX_ADDR && rst_l;
assign WriteData = wdata;
always @ ( posedge aclk or negedge rst_l) begin
if(!rst_l) begin
rvalid <= 0;
bvalid <= 0;
end
else begin
bid <= awid;
rid <= arid;
rvalid <= arvalid;
bvalid <= awvalid;
rdata <= memdata;
end
end
always @ ( negedge aclk) begin
if(arvalid) memdata <= {mem[araddr+7], mem[araddr+6], mem[araddr+5], mem[araddr+4],
mem[araddr+3], mem[araddr+2], mem[araddr+1], mem[araddr]};
if(awvalid) begin
if(wstrb[7]) mem[awaddr+7] = wdata[63:56];
if(wstrb[6]) mem[awaddr+6] = wdata[55:48];
if(wstrb[5]) mem[awaddr+5] = wdata[47:40];
if(wstrb[4]) mem[awaddr+4] = wdata[39:32];
if(wstrb[3]) mem[awaddr+3] = wdata[31:24];
if(wstrb[2]) mem[awaddr+2] = wdata[23:16];
if(wstrb[1]) mem[awaddr+1] = wdata[15:08];
if(wstrb[0]) mem[awaddr+0] = wdata[07:00];
end
end
assign arready = 1'b1;
assign awready = 1'b1;
assign wready = 1'b1;
assign rresp = 2'b0;
assign bresp = 2'b0;
assign rlast = 1'b1;
endmodule
`endif

225
test/helloworld/ahb_sif.sv Normal file
View File

@ -0,0 +1,225 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2019 Western Digital Corporation or its affiliates.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the 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.
//
`ifdef RV_BUILD_AHB_LITE
module ahb_sif (
input logic [63:0] HWDATA,
input logic HCLK,
input logic HSEL,
input logic [3:0] HPROT,
input logic HWRITE,
input logic [1:0] HTRANS,
input logic [2:0] HSIZE,
input logic HREADY,
input logic HRESETn,
input logic [31:0] HADDR,
input logic [2:0] HBURST,
output logic HREADYOUT,
output logic HRESP,
output logic [63:0] HRDATA
);
parameter MAILBOX_ADDR = 32'hD0580000;
logic write;
logic [31:0] laddr, addr;
logic [7:0] strb_lat;
logic [63:0] rdata;
bit [7:0] mem [bit[31:0]];
bit [7:0] wscnt;
int dws = 0;
int iws = 0;
bit dws_rand;
bit iws_rand;
bit ok;
// Wires
wire [63:0] WriteData = HWDATA;
wire [7:0] strb = HSIZE == 3'b000 ? 8'h1 << HADDR[2:0] :
HSIZE == 3'b001 ? 8'h3 << {HADDR[2:1],1'b0} :
HSIZE == 3'b010 ? 8'hf << {HADDR[2],2'b0} : 8'hff;
wire mailbox_write = write && laddr==MAILBOX_ADDR;
initial begin
if ($value$plusargs("iws=%d", iws));
if ($value$plusargs("dws=%d", dws));
dws_rand = dws < 0;
iws_rand = iws < 0;
end
always @ (negedge HCLK ) begin
if(HREADY)
addr = HADDR;
if (write & HREADY) begin
if(strb_lat[7]) mem[{laddr[31:3],3'd7}] = HWDATA[63:56];
if(strb_lat[6]) mem[{laddr[31:3],3'd6}] = HWDATA[55:48];
if(strb_lat[5]) mem[{laddr[31:3],3'd5}] = HWDATA[47:40];
if(strb_lat[4]) mem[{laddr[31:3],3'd4}] = HWDATA[39:32];
if(strb_lat[3]) mem[{laddr[31:3],3'd3}] = HWDATA[31:24];
if(strb_lat[2]) mem[{laddr[31:3],3'd2}] = HWDATA[23:16];
if(strb_lat[1]) mem[{laddr[31:3],3'd1}] = HWDATA[15:08];
if(strb_lat[0]) mem[{laddr[31:3],3'd0}] = HWDATA[07:00];
end
if(HREADY & HSEL & |HTRANS) begin
`ifdef VERILATOR
if(iws_rand & ~HPROT[0])
iws = $random & 15;
if(dws_rand & HPROT[0])
dws = $random & 15;
`else
if(iws_rand & ~HPROT[0])
ok = std::randomize(iws) with {iws dist {0:=10, [1:3]:/2, [4:15]:/1};};
if(dws_rand & HPROT[0])
ok = std::randomize(dws) with {dws dist {0:=10, [1:3]:/2, [4:15]:/1};};
`endif
end
end
assign HRDATA = HREADY ? rdata : ~rdata;
assign HREADYOUT = wscnt == 0;
assign HRESP = 0;
always @(posedge HCLK or negedge HRESETn) begin
if(~HRESETn) begin
laddr <= 32'b0;
write <= 1'b0;
rdata <= '0;
wscnt <= 0;
end
else begin
if(HREADY & HSEL) begin
laddr <= HADDR;
write <= HWRITE & |HTRANS;
if(|HTRANS & ~HWRITE)
rdata <= {mem[{addr[31:3],3'd7}],
mem[{addr[31:3],3'd6}],
mem[{addr[31:3],3'd5}],
mem[{addr[31:3],3'd4}],
mem[{addr[31:3],3'd3}],
mem[{addr[31:3],3'd2}],
mem[{addr[31:3],3'd1}],
mem[{addr[31:3],3'd0}]};
strb_lat <= strb;
end
end
if(HREADY & HSEL & |HTRANS)
wscnt <= HPROT[0] ? dws[7:0] : iws[7:0];
else if(wscnt != 0)
wscnt <= wscnt-1;
end
endmodule
`endif
`ifdef RV_BUILD_AXI4
module axi_slv #(TAGW=1) (
input aclk,
input rst_l,
input arvalid,
output reg arready,
input [31:0] araddr,
input [TAGW-1:0] arid,
input [7:0] arlen,
input [1:0] arburst,
input [2:0] arsize,
output reg rvalid,
input rready,
output reg [63:0] rdata,
output reg [1:0] rresp,
output reg [TAGW-1:0] rid,
output rlast,
input awvalid,
output awready,
input [31:0] awaddr,
input [TAGW-1:0] awid,
input [7:0] awlen,
input [1:0] awburst,
input [2:0] awsize,
input [63:0] wdata,
input [7:0] wstrb,
input wvalid,
output wready,
output reg bvalid,
input bready,
output reg [1:0] bresp,
output reg [TAGW-1:0] bid
);
parameter MAILBOX_ADDR = 32'hD0580000;
parameter MEM_SIZE_DW = 8192;
bit [7:0] mem [bit[31:0]];
bit [63:0] memdata;
wire [63:0] WriteData;
wire mailbox_write;
assign mailbox_write = awvalid && awaddr==MAILBOX_ADDR && rst_l;
assign WriteData = wdata;
always @ ( posedge aclk or negedge rst_l) begin
if(!rst_l) begin
rvalid <= 0;
bvalid <= 0;
end
else begin
bid <= awid;
rid <= arid;
rvalid <= arvalid;
bvalid <= awvalid;
rdata <= memdata;
end
end
always @ ( negedge aclk) begin
if(arvalid) memdata <= {mem[araddr+7], mem[araddr+6], mem[araddr+5], mem[araddr+4],
mem[araddr+3], mem[araddr+2], mem[araddr+1], mem[araddr]};
if(awvalid) begin
if(wstrb[7]) mem[awaddr+7] = wdata[63:56];
if(wstrb[6]) mem[awaddr+6] = wdata[55:48];
if(wstrb[5]) mem[awaddr+5] = wdata[47:40];
if(wstrb[4]) mem[awaddr+4] = wdata[39:32];
if(wstrb[3]) mem[awaddr+3] = wdata[31:24];
if(wstrb[2]) mem[awaddr+2] = wdata[23:16];
if(wstrb[1]) mem[awaddr+1] = wdata[15:08];
if(wstrb[0]) mem[awaddr+0] = wdata[07:00];
end
end
assign arready = 1'b1;
assign awready = 1'b1;
assign wready = 1'b1;
assign rresp = 2'b0;
assign bresp = 2'b0;
assign rlast = 1'b1;
endmodule
`endif

View File

@ -0,0 +1,201 @@
// connects LSI master to external AXI slave and DMA slave
module axi_lsu_dma_bridge
#(
parameter M_ID_WIDTH = 8,
parameter S0_ID_WIDTH = 8
)
(
input clk,
input reset_l,
// master read bus
input m_arvalid,
input [M_ID_WIDTH-1:0] m_arid,
input[31:0] m_araddr,
output m_arready,
output m_rvalid,
input m_rready,
output [63:0] m_rdata,
output [M_ID_WIDTH-1:0] m_rid,
output [1:0] m_rresp,
output m_rlast,
// master write bus
input m_awvalid,
input [M_ID_WIDTH-1:0] m_awid,
input[31:0] m_awaddr,
output m_awready,
input m_wvalid,
output m_wready,
output[1:0] m_bresp,
output m_bvalid,
output[M_ID_WIDTH-1:0] m_bid,
input m_bready,
// slave 0 if general ext memory
output s0_arvalid,
input s0_arready,
input s0_rvalid,
input[S0_ID_WIDTH-1:0] s0_rid,
input[1:0] s0_rresp,
input[63:0] s0_rdata,
input s0_rlast,
output s0_rready,
output s0_awvalid,
input s0_awready,
output s0_wvalid,
input s0_wready,
input[1:0] s0_bresp,
input s0_bvalid,
input[S0_ID_WIDTH-1:0] s0_bid,
output s0_bready,
// slave 1 if DMA port
output s1_arvalid,
input s1_arready,
input s1_rvalid,
input[1:0] s1_rresp,
input[63:0] s1_rdata,
input s1_rlast,
output s1_rready,
output s1_awvalid,
input s1_awready,
output s1_wvalid,
input s1_wready,
input[1:0] s1_bresp,
input s1_bvalid,
output s1_bready
);
parameter ICCM_BASE = `RV_ICCM_BITS; // in LSBs
localparam IDFIFOSZ = $clog2(`RV_DMA_BUF_DEPTH);
bit[31:0] iccm_real_base_addr = `RV_ICCM_SADR ;
wire ar_slave_select;
wire aw_slave_select;
wire w_slave_select;
wire rresp_select;
wire bresp_select;
wire ar_iccm_select;
wire aw_iccm_select;
reg [1:0] wsel_iptr, wsel_optr;
reg [2:0] wsel_count;
reg [3:0] wsel;
reg [M_ID_WIDTH-1:0] arid [1<<IDFIFOSZ];
reg [M_ID_WIDTH-1:0] awid [1<<IDFIFOSZ];
reg [IDFIFOSZ-1:0] arid_cnt;
reg [IDFIFOSZ-1:0] awid_cnt;
reg [IDFIFOSZ-1:0] rid_cnt;
reg [IDFIFOSZ-1:0] bid_cnt;
// 1 select slave 1; 0 - slave 0
assign ar_slave_select = ar_iccm_select;
assign aw_slave_select = aw_iccm_select;
assign ar_iccm_select = m_araddr[31:ICCM_BASE] == iccm_real_base_addr[31:ICCM_BASE];
assign aw_iccm_select = m_awaddr[31:ICCM_BASE] == iccm_real_base_addr[31:ICCM_BASE];
assign s0_arvalid = m_arvalid & ~ar_slave_select;
assign s1_arvalid = m_arvalid & ar_slave_select;
assign m_arready = ar_slave_select ? s1_arready : s0_arready;
assign s0_awvalid = m_awvalid & ~aw_slave_select;
assign s1_awvalid = m_awvalid & aw_slave_select;
assign m_awready = aw_slave_select ? s1_awready : s0_awready;
assign s0_wvalid = m_wvalid & ~w_slave_select;
assign s1_wvalid = m_wvalid & w_slave_select;
assign m_wready = w_slave_select ? s1_wready : s0_wready;
assign w_slave_select = (wsel_count == 0 || wsel_count[2]) ? aw_slave_select : wsel[wsel_optr];
assign m_rvalid = s0_rvalid | s1_rvalid;
assign s0_rready = m_rready & ~rresp_select;
assign s1_rready = m_rready & rresp_select;
assign m_rdata = rresp_select ? s1_rdata : s0_rdata;
assign m_rresp = rresp_select ? s1_rresp : s0_rresp;
assign m_rid = rresp_select ? arid[rid_cnt] : s0_rid;
assign m_rlast = rresp_select ? s1_rlast : s0_rlast;
assign rresp_select = s1_rvalid & ~s0_rvalid;
assign m_bvalid = s0_bvalid | s1_bvalid;
assign s0_bready = m_bready & ~bresp_select;
assign s1_bready = m_bready & bresp_select;
assign m_bid = bresp_select ? awid[bid_cnt] : s0_bid;
assign m_bresp = bresp_select ? s1_bresp : s0_bresp;
assign bresp_select = s1_bvalid & ~s0_bvalid;
// W-channel select fifo
always @ (posedge clk or negedge reset_l)
if(!reset_l) begin
wsel_count <= '0;
wsel_iptr <= '0;
wsel_optr <= '0;
end
else begin
if(m_awvalid & m_awready) begin
wsel[wsel_iptr] <= aw_slave_select;
if(!(m_wready & m_wvalid )) wsel_count <= wsel_count + 1;
wsel_iptr <= wsel_iptr + 1;
end
if(m_wvalid & m_wready) begin
if(!(m_awready & m_awvalid ) ) wsel_count <= wsel_count - 1;
wsel_optr <= wsel_optr + 1;
end
end
// id replacement for narrow ID slave
always @ (posedge clk or negedge reset_l)
if(!reset_l) begin
arid_cnt <= '0;
rid_cnt <= '0;
end
else begin
if(ar_slave_select & m_arready & m_arvalid) begin
arid[arid_cnt] <= m_arid;
arid_cnt <= arid_cnt + 1;
end
if(rresp_select & m_rready & m_rvalid) begin
rid_cnt <= rid_cnt + 1;
end
end
always @ (posedge clk or negedge reset_l)
if(!reset_l) begin
awid_cnt <= '0;
bid_cnt <= '0;
end
else begin
if(aw_slave_select & m_awready & m_awvalid) begin
awid[awid_cnt] <= m_awid;
awid_cnt <= awid_cnt + 1;
end
if(bresp_select & m_bready & m_bvalid) begin
bid_cnt <= bid_cnt + 1;
end
end
endmodule

395
test/helloworld/dasm.svi Normal file
View File

@ -0,0 +1,395 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2019 Western Digital Corporation or its affiliates.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the 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.
//
// Run time disassembler functions
// supports RISCV extentions I, C, M, A
`ifndef RV_NUM_THREADS
`define RV_NUM_THREADS 1
`endif
bit[31:0] [31:0] gpr[`RV_NUM_THREADS];
// main DASM function
function string dasm(input[31:0] opcode, input[31:0] pc, input[4:0] regn, input[31:0] regv, input tid=0);
dasm = (opcode[1:0] == 2'b11) ? dasm32(opcode, pc, tid) : dasm16(opcode, pc, tid);
if(regn) gpr[tid][regn] = regv;
endfunction
///////////////// 16 bits instructions ///////////////////////
function string dasm16( input[31:0] opcode, input[31:0] pc, input tid=0);
case(opcode[1:0])
0: return dasm16_0(opcode, tid);
1: return dasm16_1(opcode, pc);
2: return dasm16_2(opcode);
endcase
return $sformatf(".short 0x%h", opcode[15:0]);
endfunction
function string dasm16_0( input[31:0] opcode, tid);
case(opcode[15:13])
3'b000: return dasm16_ciw(opcode);
3'b001: return {"c.fld ", dasm16_cl(opcode, tid)};
3'b010: return {"c.lw ", dasm16_cl(opcode, tid)};
3'b011: return {"c.flw ", dasm16_cl(opcode, tid)};
3'b101: return {"c.fsd ", dasm16_cl(opcode, tid)};
3'b110: return {"c.sw ", dasm16_cl(opcode, tid)};
3'b111: return {"c.fsw ", dasm16_cl(opcode, tid)};
endcase
return $sformatf(".short 0x%h", opcode[15:0]);
endfunction
function string dasm16_ciw( input[31:0] opcode);
int imm;
imm=0;
if(opcode[15:0] == 0) return ".short 0";
{imm[5:4],imm[9:6],imm[2],imm[3]} = opcode[12:5];
return $sformatf("c.addi4spn %s,0x%0h", abi_reg[opcode[4:2]+8], imm);
endfunction
function string dasm16_cl( input[31:0] opcode, input tid=0);
int imm;
imm=0;
imm[5:3] = opcode[12:10];
imm[7:6] = opcode[6:5];
return $sformatf(" %s,%0d(%s) [%h]", abi_reg[opcode[4:2]+8], imm, abi_reg[opcode[9:7]+8], gpr[tid][opcode[9:7]+8]+imm);
endfunction
function string dasm16_1( input[31:0] opcode, input[31:0] pc);
case(opcode[15:13])
3'b000: return opcode[11:7]==0 ? "c.nop" : {"c.addi ",dasm16_ci(opcode)};
3'b001: return {"c.jal ", dasm16_cj(opcode, pc)};
3'b010: return {"c.li ", dasm16_ci(opcode)};
3'b011: return dasm16_1_3(opcode);
3'b100: return dasm16_cr(opcode);
3'b101: return {"c.j ", dasm16_cj(opcode, pc)};
3'b110: return {"c.beqz ", dasm16_cb(opcode, pc)};
3'b111: return {"c.bnez ", dasm16_cb(opcode, pc)};
endcase
endfunction
function string dasm16_ci( input[31:0] opcode);
int imm;
imm=0;
imm[4:0] = opcode[6:2];
if(opcode[12]) imm [31:5] = '1;
return $sformatf("%s,%0d", abi_reg[opcode[11:7]], imm);
endfunction
function string dasm16_cj( input[31:0] opcode, input[31:0] pc);
bit[31:0] imm;
imm=0;
{imm[11],imm[4],imm[9:8],imm[10],imm[6], imm[7],imm[3:1], imm[5]} = opcode[12:2];
if(opcode[12]) imm [31:12] = '1;
return $sformatf("0x%0h", imm+pc);
endfunction
function string dasm16_cb( input[31:0] opcode, input[31:0] pc);
bit[31:0] imm;
imm=0;
{imm[8],imm[4:3]} = opcode[12:10];
{imm[7:6],imm[2:1], imm[5]} = opcode[6:2];
if(opcode[12]) imm [31:9] = '1;
return $sformatf("%s,0x%0h",abi_reg[opcode[9:7]+8], imm+pc);
endfunction
function string dasm16_cr( input[31:0] opcode);
bit[31:0] imm;
imm = 0;
imm[4:0] = opcode[6:2];
if(opcode[5]) imm [31:5] = '1;
case(opcode[11:10])
0: return $sformatf("c.srli %s,%0d", abi_reg[opcode[9:7]+8], imm[5:0]);
1: return $sformatf("c.srai %s,%0d", abi_reg[opcode[9:7]+8], imm[5:0]);
2: return $sformatf("c.andi %s,0x%0h", abi_reg[opcode[9:7]+8], imm);
endcase
case(opcode[6:5])
0: return $sformatf("c.sub %s,%s", abi_reg[opcode[9:7]+8], abi_reg[opcode[4:2]+8]);
1: return $sformatf("c.xor %s,%s", abi_reg[opcode[9:7]+8], abi_reg[opcode[4:2]+8]);
2: return $sformatf("c.or %s,%s", abi_reg[opcode[9:7]+8], abi_reg[opcode[4:2]+8]);
3: return $sformatf("c.and %s,%s", abi_reg[opcode[9:7]+8], abi_reg[opcode[4:2]+8]);
endcase
endfunction
function string dasm16_1_3( input[31:0] opcode);
int imm;
imm=0;
if(opcode[11:7] == 2) begin
{imm[4], imm[6],imm[8:7], imm[5]} = opcode[6:2];
if(opcode[12]) imm [31:9] = '1;
return $sformatf("c.addi16sp %0d", imm);
end
else begin
imm[16:12] = opcode[6:2];
if(opcode[12]) imm [31:17] = '1;
return $sformatf("c.lui %s,0x%0h", abi_reg[opcode[11:7]], imm);
end
endfunction
function string dasm16_2( input[31:0] opcode, input tid=0);
case(opcode[15:13])
3'b000: return {"c.slli ", dasm16_ci(opcode)};
3'b001: return {"c.fldsp ", dasm16_cls(opcode,1,tid)};
3'b010: return {"c.lwsp ", dasm16_cls(opcode,0,tid)};
3'b011: return {"c.flwsp ", dasm16_cls(opcode,0,tid)};
3'b101: return {"c.fsdsp ", dasm16_css(opcode,1,tid)};
3'b110: return {"c.swsp ", dasm16_css(opcode,0,tid)};
3'b111: return {"c.fswsp ", dasm16_css(opcode,0,tid)};
endcase
if(opcode[12]) begin
if(opcode[12:2] == 0) return "c.ebreak";
else if(opcode[6:2] == 0) return $sformatf("c.jalr %s", abi_reg[opcode[11:7]]);
else return $sformatf("c.add %s,%s", abi_reg[opcode[11:7]], abi_reg[opcode[6:2]]);
end
else begin
if(opcode[6:2] == 0) return $sformatf("c.jr %s", abi_reg[opcode[11:7]]);
else return $sformatf("c.mv %s,%s", abi_reg[opcode[11:7]], abi_reg[opcode[6:2]]);
end
endfunction
function string dasm16_cls( input[31:0] opcode, input sh1=0, tid=0);
bit[31:0] imm;
imm=0;
if(sh1) {imm[4:3],imm[8:6]} = opcode[6:2];
else {imm[4:2],imm[7:6]} = opcode[6:2];
imm[5] = opcode[12];
return $sformatf("%s,0x%0h [%h]", abi_reg[opcode[11:7]], imm, gpr[tid][2]+imm);
endfunction
function string dasm16_css( input[31:0] opcode, input sh1=0, tid=0);
bit[31:0] imm;
imm=0;
if(sh1) {imm[5:3],imm[8:6]} = opcode[12:7];
else {imm[5:2],imm[7:6]} = opcode[12:7];
return $sformatf("%s,0x%0h [%h]", abi_reg[opcode[6:2]], imm, gpr[tid][2]+imm);
endfunction
///////////////// 32 bit instructions ///////////////////////
function string dasm32( input[31:0] opcode, input[31:0] pc, input tid=0);
case(opcode[6:0])
7'b0110111: return {"lui ", dasm32_u(opcode)};
7'b0010111: return {"auipc ", dasm32_u(opcode)};
7'b1101111: return {"jal ", dasm32_j(opcode,pc)};
7'b1100111: return {"jalr ", dasm32_jr(opcode,pc)};
7'b1100011: return dasm32_b(opcode,pc);
7'b0000011: return dasm32_l(opcode,tid);
7'b0100011: return dasm32_s(opcode,tid);
7'b0010011: return dasm32_ai(opcode);
7'b0110011: return dasm32_ar(opcode);
7'b0001111: return {"fence", dasm32_fence(opcode)};
7'b1110011: return dasm32_e(opcode);
7'b0101111: return dasm32_a(opcode,tid);
endcase
return $sformatf(".long 0x%h", opcode);
endfunction
function string dasm32_u( input[31:0] opcode);
bit[31:0] imm;
imm=0;
imm[31:12] = opcode[31:12];
return $sformatf("%s,0x%0h", abi_reg[opcode[11:7]], imm);
endfunction
function string dasm32_j( input[31:0] opcode, input[31:0] pc);
int imm;
imm=0;
{imm[20], imm[10:1], imm[11], imm[19:12]} = opcode[31:12];
if(opcode[31]) imm[31:20] = '1;
return $sformatf("%s,0x%0h",abi_reg[opcode[11:7]], imm+pc);
endfunction
function string dasm32_jr( input[31:0] opcode, input[31:0] pc);
int imm;
imm=0;
imm[11:1] = opcode[31:19];
if(opcode[31]) imm[31:12] = '1;
return $sformatf("%s,%s,0x%0h",abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], imm+pc);
endfunction
function string dasm32_b( input[31:0] opcode, input[31:0] pc);
int imm;
string mn;
imm=0;
{imm[12],imm[10:5]} = opcode[31:25];
{imm[4:1],imm[11]} = opcode[11:7];
if(opcode[31]) imm[31:12] = '1;
case(opcode[14:12])
0: mn = "beq ";
1: mn = "bne ";
2,3 : return $sformatf(".long 0x%h", opcode);
4: mn = "blt ";
5: mn = "bge ";
6: mn = "bltu ";
7: mn = "bgeu ";
endcase
return $sformatf("%s%s,%s,0x%0h", mn, abi_reg[opcode[19:15]], abi_reg[opcode[24:20]], imm+pc);
endfunction
function string dasm32_l( input[31:0] opcode, input tid=0);
int imm;
string mn;
imm=0;
imm[11:0] = opcode[31:20];
if(opcode[31]) imm[31:12] = '1;
case(opcode[14:12])
0: mn = "lb ";
1: mn = "lh ";
2: mn = "lw ";
4: mn = "lbu ";
5: mn = "lhu ";
default : return $sformatf(".long 0x%h", opcode);
endcase
return $sformatf("%s%s,%0d(%s) [%h]", mn, abi_reg[opcode[11:7]], imm, abi_reg[opcode[19:15]], imm+gpr[tid][opcode[19:15]]);
endfunction
function string dasm32_s( input[31:0] opcode, input tid=0);
int imm;
string mn;
imm=0;
imm[11:5] = opcode[31:25];
imm[4:0] = opcode[11:7];
if(opcode[31]) imm[31:12] = '1;
case(opcode[14:12])
0: mn = "sb ";
1: mn = "sh ";
2: mn = "sw ";
default : return $sformatf(".long 0x%h", opcode);
endcase
return $sformatf("%s%s,%0d(%s) [%h]", mn, abi_reg[opcode[24:20]], imm, abi_reg[opcode[19:15]], imm+gpr[tid][opcode[19:15]]);
endfunction
function string dasm32_ai( input[31:0] opcode);
int imm;
string mn;
imm=0;
imm[11:0] = opcode[31:20];
if(opcode[31]) imm[31:12] = '1;
case(opcode[14:12])
0: mn = "addi ";
2: mn = "slti ";
3: mn = "sltiu ";
4: mn = "xori ";
6: mn = "ori ";
7: mn = "andi ";
default: return dasm32_si(opcode);
endcase
return $sformatf("%s%s,%s,%0d", mn, abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], imm);
endfunction
function string dasm32_si( input[31:0] opcode);
int imm;
string mn;
imm = opcode[24:20];
case(opcode[14:12])
1: mn = "slli";
5: mn = opcode[30] ? "srli": "srai";
endcase
return $sformatf("%s %s,%s,%0d", mn, abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], imm);
endfunction
function string dasm32_ar( input[31:0] opcode);
string mn;
if(opcode[25])
case(opcode[14:12])
0: mn = "mul ";
1: mn = "mulh ";
2: mn = "mulhsu ";
3: mn = "mulhu ";
4: mn = "div ";
5: mn = "divu ";
6: mn = "rem ";
7: mn = "remu ";
endcase
else
case(opcode[14:12])
0: mn = opcode[30]? "sub ":"add ";
1: mn = "sll ";
2: mn = "slt ";
3: mn = "sltu ";
4: mn = "xor ";
5: mn = opcode[30]? "sra ":"srl ";
6: mn = "or ";
7: mn = "and ";
endcase
return $sformatf("%s%s,%s,%s", mn, abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], abi_reg[opcode[24:20]]);
endfunction
function string dasm32_fence( input[31:0] opcode);
return opcode[12] ? ".i" : "";
endfunction
function string dasm32_e(input[31:0] opcode);
if(opcode[31:7] == 0) return "ecall";
else if({opcode[31:21],opcode [19:7]} == 0) return "ebreak";
else
case(opcode[14:12])
1: return {"csrrw ", dasm32_csr(opcode)};
2: return {"csrrs ", dasm32_csr(opcode)};
3: return {"csrrc ", dasm32_csr(opcode)};
5: return {"csrrwi ", dasm32_csr(opcode, 1)};
6: return {"csrrsi ", dasm32_csr(opcode, 1)};
7: return {"csrrci ", dasm32_csr(opcode, 1)};
endcase
endfunction
function string dasm32_csr(input[31:0] opcode, input im=0);
bit[11:0] csr;
csr = opcode[31:20];
if(im) begin
return $sformatf("%s,csr_%0h,0x%h", abi_reg[opcode[11:7]], csr, opcode[19:15]);
end
else begin
return $sformatf("%s,csr_%0h,%s", abi_reg[opcode[11:7]], csr, abi_reg[opcode[19:15]]);
end
endfunction
//atomics
function string dasm32_a(input[31:0] opcode, input tid=0);
case(opcode[31:27])
'b00010: return $sformatf("lr.w %s,(%s) [%h]", abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], gpr[tid][opcode[19:15]]);
'b00011: return $sformatf("sc.w %s,%s,(%s) [%h]", abi_reg[opcode[11:7]], abi_reg[opcode[24:20]], abi_reg[opcode[19:15]], gpr[tid][opcode[19:15]]);
'b00001: return {"amoswap.w", dasm32_amo(opcode, tid)};
'b00000: return {"amoadd.w", dasm32_amo(opcode, tid)};
'b00100: return {"amoxor.w", dasm32_amo(opcode, tid)};
'b01100: return {"amoand.w", dasm32_amo(opcode, tid)};
'b01000: return {"amoor.w", dasm32_amo(opcode, tid)};
'b10000: return {"amomin.w", dasm32_amo(opcode, tid)};
'b10100: return {"amomax.w", dasm32_amo(opcode, tid)};
'b11000: return {"amominu.w", dasm32_amo(opcode, tid)};
'b11100: return {"amomaxu.w", dasm32_amo(opcode, tid)};
endcase
return $sformatf(".long 0x%h", opcode);
endfunction
function string dasm32_amo( input[31:0] opcode, input tid=0);
return $sformatf(" %s,%s,(%s) [%h]", abi_reg[opcode[11:7]], abi_reg[opcode[24:20]], abi_reg[opcode[19:15]], gpr[tid][opcode[19:15]]);
endfunction

43
test/helloworld/flist Normal file
View File

@ -0,0 +1,43 @@
+incdir+$RV_ROOT/testbench
$RV_ROOT/design/swerv_wrapper.sv
$RV_ROOT/design/mem.sv
$RV_ROOT/design/pic_ctrl.sv
$RV_ROOT/design/swerv.sv
$RV_ROOT/design/dma_ctrl.sv
$RV_ROOT/design/ifu/ifu_aln_ctl.sv
$RV_ROOT/design/ifu/ifu_compress_ctl.sv
$RV_ROOT/design/ifu/ifu_ifc_ctl.sv
$RV_ROOT/design/ifu/ifu_bp_ctl.sv
$RV_ROOT/design/ifu/ifu_ic_mem.sv
$RV_ROOT/design/ifu/ifu_mem_ctl.sv
$RV_ROOT/design/ifu/ifu_iccm_mem.sv
$RV_ROOT/design/ifu/ifu.sv
$RV_ROOT/design/dec/dec_decode_ctl.sv
$RV_ROOT/design/dec/dec_gpr_ctl.sv
$RV_ROOT/design/dec/dec_ib_ctl.sv
$RV_ROOT/design/dec/dec_tlu_ctl.sv
$RV_ROOT/design/dec/dec_trigger.sv
$RV_ROOT/design/dec/dec.sv
$RV_ROOT/design/exu/exu_alu_ctl.sv
$RV_ROOT/design/exu/exu_mul_ctl.sv
$RV_ROOT/design/exu/exu_div_ctl.sv
$RV_ROOT/design/exu/exu.sv
$RV_ROOT/design/lsu/lsu.sv
$RV_ROOT/design/lsu/lsu_clkdomain.sv
$RV_ROOT/design/lsu/lsu_addrcheck.sv
$RV_ROOT/design/lsu/lsu_lsc_ctl.sv
$RV_ROOT/design/lsu/lsu_stbuf.sv
$RV_ROOT/design/lsu/lsu_bus_buffer.sv
$RV_ROOT/design/lsu/lsu_bus_intf.sv
$RV_ROOT/design/lsu/lsu_ecc.sv
$RV_ROOT/design/lsu/lsu_dccm_mem.sv
$RV_ROOT/design/lsu/lsu_dccm_ctl.sv
$RV_ROOT/design/lsu/lsu_trigger.sv
$RV_ROOT/design/dbg/dbg.sv
$RV_ROOT/design/dmi/dmi_wrapper.v
$RV_ROOT/design/dmi/dmi_jtag_to_core_sync.v
$RV_ROOT/design/dmi/rvjtag_tap.sv
-v $RV_ROOT/design/lib/beh_lib.sv
-v $RV_ROOT/design/lib/mem_lib.sv
-v $RV_ROOT/design/lib/ahb_to_axi4.sv
-v $RV_ROOT/design/lib/axi4_to_ahb.sv

View File

@ -0,0 +1,81 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2019 Western Digital Corporation or its affiliates.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the 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.
//
// Assembly code for Hello World
// Not using only ALU ops for creating the string
#include "defines.h"
#define STDOUT 0xd0580000
// Code to execute
.section .text
.global _start
_start:
// Clear minstret
csrw minstret, zero
csrw minstreth, zero
// Set up MTVEC - not expecting to use it though
li x1, RV_ICCM_SADR
csrw mtvec, x1
// Enable Caches in MRAC
li x1, 0x5f555555
csrw 0x7c0, x1
// Load string from hw_data
// and write to stdout address
li x3, STDOUT
la x4, hw_data
loop:
lb x5, 0(x4)
sb x5, 0(x3)
addi x4, x4, 1
bnez x5, loop
li x3, STDOUT
la x4, hw_data
loop2:
lb x5, 0(x4)
sb x5, 0(x3)
addi x4, x4, 1
bnez x5, loop2
// Write 0xff to STDOUT for TB to terminate test.
_finish:
li x3, STDOUT
addi x5, x0, 0xff
sb x5, 0(x3)
beq x0, x0, _finish
.rept 100
nop
.endr
.global hw_data
.data
hw_data:
.ascii "----------------------------------\n"
.ascii "Hello World from Colin EH1 @WDC !!\n"
.ascii "----------------------------------\n"
.byte 0

15
test/helloworld/link.ld Normal file
View File

@ -0,0 +1,15 @@
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
SECTIONS
{
. = 0;
.text : { *(.text*) }
_end = .;
. = 0x10000;
.data : ALIGN(0x800) { *(.*data) *(.rodata*) STACK = ALIGN(16) + 0x8000; }
.bss : { *(.bss) }
. = 0xd0580000;
.data.io : { *(.data.io) }
}

2057
test/helloworld/swerv.config Executable file

File diff suppressed because it is too large Load Diff

1115
test/helloworld/tb_top.sv Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,65 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2019 Western Digital Corporation or its affiliates.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the 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.
//
#include <stdlib.h>
#include <iostream>
#include <utility>
#include <string>
#include "Vtb_top.h"
#include "verilated.h"
#include "verilated_vcd_c.h"
vluint64_t main_time = 0;
double sc_time_stamp () {
return main_time;
}
int main(int argc, char** argv) {
std::cout << "\nVerilatorTB: Start of sim\n" << std::endl;
Verilated::commandArgs(argc, argv);
Vtb_top* tb = new Vtb_top;
// init trace dump
VerilatedVcdC* tfp = NULL;
#if VM_TRACE
Verilated::traceEverOn(true);
tfp = new VerilatedVcdC;
tb->trace (tfp, 24);
tfp->open ("sim.vcd");
#endif
// Simulate
while(!Verilated::gotFinish()){
#if VM_TRACE
tfp->dump (main_time);
#endif
main_time += 5;
tb->core_clk = !tb->core_clk;
tb->eval();
}
#if VM_TRACE
tfp->close();
#endif
std::cout << "\nVerilatorTB: End of sim" << std::endl;
exit(EXIT_SUCCESS);
}