tmp commit, unstable

Signed-off-by: liangkangnan <liangkangnan@163.com>
pull/4/head
Blue Liang 2021-03-29 15:14:50 +08:00
parent 5c87fc09ef
commit 8214134b89
65 changed files with 930 additions and 2249 deletions

View File

@ -1,2 +1,2 @@
本分支(bram)是在master分支的基础上将指令和数据存储器由LUTRAM(DRAM)改为BRAM以便可以运行更大的(C语言)程序。

44
rtl.flist Normal file
View File

@ -0,0 +1,44 @@
+incdir+../rtl/core
../rtl/core/clint.sv
../rtl/core/csr_reg.sv
../rtl/core/defines.sv
../rtl/core/divider.sv
../rtl/core/exu.sv
../rtl/core/exu_alu_datapath.sv
../rtl/core/exu_commit.sv
../rtl/core/exu_dispatch.sv
../rtl/core/exu_mem.sv
../rtl/core/exu_muldiv.sv
../rtl/core/gpr_reg.sv
../rtl/core/idu.sv
../rtl/core/idu_exu.sv
../rtl/core/ifu.sv
../rtl/core/ifu_idu.sv
../rtl/core/pipe_ctrl.sv
../rtl/core/rst_ctrl.sv
../rtl/core/tinyriscv_core.sv
../rtl/debug/jtag_dm.sv
../rtl/debug/jtag_driver.sv
../rtl/debug/jtag_top.sv
../rtl/perips/gpio.sv
../rtl/perips/ram.sv
../rtl/perips/rom.sv
../rtl/perips/timer.sv
../rtl/perips/uart.sv
../rtl/sys_bus/rib.sv
../rtl/top/tinyriscv_soc_top.sv
../rtl/utils/full_handshake_rx.sv
../rtl/utils/full_handshake_tx.sv
../rtl/utils/gen_buf.sv
../rtl/utils/gen_dff.sv
../rtl/utils/gen_ram.sv
../rtl/utils/vld_rdy.sv

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
// core local interruptor module
// 核心中断管理、仲裁模块

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
// CSR寄存器模块
module csr_reg(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
// 除法模块
// 试商法实现32位整数除法

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
// 执行模块
// 纯组合逻辑电路

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
`define DATAPATH_MUX_WIDTH (32+32+16)

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
module exu_commit(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
module exu_dispatch(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
module exu_mem(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
module exu_muldiv(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
// 通用寄存器模块
module gpr_reg(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
// 译码模块
// 纯组合逻辑电路

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
// 将译码结果向执行模块传递
module idu_exu(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
// 取指模块
module ifu(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
// 将指令向译码模块传递
module ifu_idu(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
// 流水线控制模块
// 发出暂停、冲刷流水线信号

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
// 复位控制模块
module rst_ctrl(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "defines.v"
`include "defines.sv"
// tinyriscv处理器核顶层模块
module tinyriscv_core(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "../core/defines.v"
`include "../core/defines.sv"
// JTAG顶层模块
module jtag_top #(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "../core/defines.v"
`include "../core/defines.sv"
module ram #(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "../core/defines.v"
`include "../core/defines.sv"
module rom #(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "../core/defines.v"
`include "../core/defines.sv"
// 32位向上计数定时器模块
module timer(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "../core/defines.v"
`include "../core/defines.sv"
// 串口收发模块(默认: 115200, 8N1)
module uart(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "../core/defines.v"
`include "../core/defines.sv"
// tinyriscv soc顶层模块
module tinyriscv_soc_top(

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
`include "../core/defines.v"
`include "../core/defines.sv"
module gen_ram #(

View File

@ -1,6 +1,5 @@
RISCV_TOOLS_PATH := $(TOOLCHAIN_DIR)/tools/gnu-mcu-eclipse-riscv-none-gcc-8.2.0-2.2-20190521-0004-win64/bin
RISCV_TOOLS_PREFIX := riscv-none-embed-
RISCV_TOOLS_PATH := /opt/riscv/bin
RISCV_TOOLS_PREFIX := riscv32-unknown-elf-
RISCV_GCC := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)gcc)
RISCV_AS := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)as)
@ -11,6 +10,8 @@ RISCV_AR := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)ar)
RISCV_OBJCOPY := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)objcopy)
RISCV_READELF := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)readelf)
BIN_TO_MEM := $(COMMON_DIR)/../../tools/BinToMem.py
.PHONY: all
all: $(TARGET)
@ -34,7 +35,7 @@ C_OBJS := $(C_SRCS:.c=.o)
LINK_OBJS += $(ASM_OBJS) $(C_OBJS)
LINK_DEPS += $(LINKER_SCRIPT)
CLEAN_OBJS += $(TARGET) $(LINK_OBJS) $(TARGET).dump $(TARGET).bin
CLEAN_OBJS += $(TARGET) $(LINK_OBJS) $(TARGET).dump $(TARGET).bin $(TARGET).hex $(TARGET).mem
CFLAGS += -march=$(RISCV_ARCH)
CFLAGS += -mabi=$(RISCV_ABI)
@ -44,6 +45,7 @@ $(TARGET): $(LINK_OBJS) $(LINK_DEPS) Makefile
$(RISCV_GCC) $(CFLAGS) $(INCLUDES) $(LINK_OBJS) -o $@ $(LDFLAGS)
$(RISCV_OBJCOPY) -O binary $@ $@.bin
$(RISCV_OBJDUMP) --disassemble-all $@ > $@.dump
$(BIN_TO_MEM) $@.bin $@.mem
$(ASM_OBJS): %.o: %.S
$(RISCV_GCC) $(CFLAGS) $(INCLUDES) -c -o $@ $<

14
sim/.gitignore vendored
View File

@ -1,10 +1,6 @@
# Object files
*.o
*.ko
*.obj
testbench_verilator
*.log
*.vcd
*.bin
*.dump
inst.data
out.vvp
tinyriscv_soc_tb.vcd
jtag_tb.vcd
cobj_dir/

90
sim/Makefile Normal file
View File

@ -0,0 +1,90 @@
PROG := ../sdk/examples/simple/simple.mem
PROG_DIR := $(shell dirname $(PROG))
MAKE := make
VERILATOR := verilator
VERI_FLAGS += +vcd
VERI_CFLAGS +=
VERI_VFLAGS += -DRVFI
TRACE_ENABLE := 1
RTL_FILES = ../rtl.flist
VERI_OBJ_DIR := cobj_dir
ifeq ($(findstring +vcd,$(VERI_FLAGS)),+vcd)
VERI_TRACE = "--trace"
VERI_CFLAGS += "-DVCD_TRACE"
else
VERI_TRACE =
endif
SIM_SRC := sim_jtag.sv
SIM_SRC += tb_top_verilator.sv \
tb_top_verilator.cpp
SIM_TOP_MODULE := tb_top_verilator
.DEFAULT_GOAL := sim
all: sim
.PHONY: recompile
recompile:
rm -rf $(VERI_OBJ_DIR) testbench_verilator
$(MAKE) -C ./remote_bitbang clean
$(MAKE) -C $(PROG_DIR) clean
$(MAKE) compile
.PHONY: compile
compile: remote_bitbang/librbs.so $(PROG) testbench_verilator
testbench_verilator:
$(VERILATOR) --cc --sv --exe \
$(VERI_TRACE) \
--Wno-lint --Wno-UNOPTFLAT \
--Wno-MODDUP --top-module \
$(SIM_TOP_MODULE) \
-f $(RTL_FILES) \
$(SIM_SRC) \
--Mdir $(VERI_OBJ_DIR) \
$(VERI_VFLAGS) \
-LDFLAGS "-L../remote_bitbang \
-Wl,--enable-new-dtags -Wl,-rpath,remote_bitbang -lrbs" \
-CFLAGS "-std=gnu++11 $(VERI_CFLAGS)"
$(MAKE) -C $(VERI_OBJ_DIR) -f V$(SIM_TOP_MODULE).mk
cp $(VERI_OBJ_DIR)/V$(SIM_TOP_MODULE) testbench_verilator
remote_bitbang/librbs.so:
$(MAKE) -C ./remote_bitbang all
$(PROG):
$(MAKE) -C $(PROG_DIR)
.PHONY: run
run:
./testbench_verilator "+firmware=$(PROG)"
.PHONY: sim
sim: recompile run
.PHONY: clean
clean:
rm -rf $(VERI_OBJ_DIR) testbench_verilator *.log *.vcd
$(MAKE) -C ./remote_bitbang clean
$(MAKE) -C $(PROG_DIR) clean
.PHONY: help
help:
@echo 'rebuild all:'
@echo 'make PROG=/path/file.mem recompile'
@echo 'run directly:'
@echo 'make PROG=/path/file.mem run'
@echo 'rebuild & run:'
@echo 'make PROG=/path/file.mem sim'
@echo 'clean obj files:'
@echo 'make PROG=/path/file.mem clean'

View File

@ -1,50 +1,3 @@
# compile_rtl.py
编译rtl代码。
使用方法:
`python compile_rtl.py [rtl目录相对路径]`
比如:
`python compile_rtl.py ..`
# sim_new_nowave.py
对指定的bin文件(重新生成inst.data文件)进行测试。
使用方法:
windows系统下
`python sim_new_nowave.py ..\tests\isa\generated\rv32ui-p-add.bin inst.data`
Linux系统下
`python sim_new_nowave.py ../tests/isa/generated/rv32ui-p-add.bin inst.data`
# sim_default_nowave.py
对已经存在的inst.data文件进行测试。
使用方法:
`python sim_default_nowave.py`
# test_all_isa.py
一次性测试../tests/isa/generated目录下的所有指令。
使用方法:
`python test_all_isa.py`
# test_jtag.py
测试JTAG的内存读、写功能。
使用方法:
`python test_jtag.py`

View File

@ -1,75 +0,0 @@
import sys
import filecmp
import subprocess
import sys
import os
# 主函数
def main():
rtl_dir = sys.argv[1]
if rtl_dir != r'..':
tb_file = r'/tb/compliance_test/tinyriscv_soc_tb.v'
else:
tb_file = r'/tb/tinyriscv_soc_tb.v'
# iverilog程序
iverilog_cmd = ['iverilog']
# 顶层模块
#iverilog_cmd += ['-s', r'tinyriscv_soc_tb']
# 编译生成文件
iverilog_cmd += ['-o', r'out.vvp']
# 头文件(defines.v)路径
iverilog_cmd += ['-I', rtl_dir + r'/rtl/core']
# 宏定义,仿真输出文件
iverilog_cmd += ['-D', r'OUTPUT="signature.output"']
# testbench文件
iverilog_cmd.append(rtl_dir + tb_file)
# ../rtl/core
iverilog_cmd.append(rtl_dir + r'/rtl/core/clint.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/csr_reg.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/defines.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/divider.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_alu_datapath.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_commit.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_dispatch.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_mem.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_muldiv.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/gpr_reg.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/idu.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/idu_exu.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/ifu.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/ifu_idu.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/pipe_ctrl.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/tinyriscv_core.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/rst_ctrl.v')
# ../rtl/perips
iverilog_cmd.append(rtl_dir + r'/rtl/perips/ram.v')
iverilog_cmd.append(rtl_dir + r'/rtl/perips/rom.v')
iverilog_cmd.append(rtl_dir + r'/rtl/perips/timer.v')
iverilog_cmd.append(rtl_dir + r'/rtl/perips/uart.v')
iverilog_cmd.append(rtl_dir + r'/rtl/perips/gpio.v')
# ../rtl/debug
iverilog_cmd.append(rtl_dir + r'/rtl/debug/jtag_dm.v')
iverilog_cmd.append(rtl_dir + r'/rtl/debug/jtag_driver.v')
iverilog_cmd.append(rtl_dir + r'/rtl/debug/jtag_top.v')
# ../rtl/sys_bus
iverilog_cmd.append(rtl_dir + r'/rtl/sys_bus/rib.v')
# ../rtl/utils
iverilog_cmd.append(rtl_dir + r'/rtl/utils/full_handshake_rx.v')
iverilog_cmd.append(rtl_dir + r'/rtl/utils/full_handshake_tx.v')
iverilog_cmd.append(rtl_dir + r'/rtl/utils/gen_buf.v')
iverilog_cmd.append(rtl_dir + r'/rtl/utils/gen_dff.v')
iverilog_cmd.append(rtl_dir + r'/rtl/utils/gen_ram.v')
iverilog_cmd.append(rtl_dir + r'/rtl/utils/vld_rdy.v')
# ../rtl/top
iverilog_cmd.append(rtl_dir + r'/rtl/top/tinyriscv_soc_top.v')
# 编译
process = subprocess.Popen(iverilog_cmd)
process.wait(timeout=5)
if __name__ == '__main__':
sys.exit(main())

View File

@ -1,11 +0,0 @@
# Object files
*.o
*.ko
*.obj
*.bin
*.dump
inst.data
out.vvp
tinyriscv_soc_tb.vcd
run.log
signature.output

View File

@ -1,11 +0,0 @@
对新的指令测试项进行测试。
使用方法:
Windows系统下
`python compliance_test.py ..\..\tests\riscv-compliance\build_generated\rv32i\I-ADD-01.elf.bin inst.data`
Linux系统下
`python compliance_test.py ../../tests/riscv-compliance/build_generated/rv32i/I-ADD-01.elf.bin inst.data`

View File

@ -1,96 +0,0 @@
import sys
import filecmp
import subprocess
import sys
import os
# 找出path目录下的所有reference_output文件
def list_ref_files(path):
files = []
list_dir = os.walk(path)
for maindir, subdir, all_file in list_dir:
for filename in all_file:
apath = os.path.join(maindir, filename)
if apath.endswith('.reference_output'):
files.append(apath)
return files
# 根据bin文件找到对应的reference_output文件
def get_reference_file(bin_file):
file_path, file_name = os.path.split(bin_file)
tmp = file_name.split('.')
# 得到bin文件的前缀部分
prefix = tmp[0]
#print('bin prefix: %s' % prefix)
files = []
if (bin_file.find('rv32im') != -1):
files = list_ref_files(r'../../tests/riscv-compliance/riscv-test-suite/rv32im/references')
elif (bin_file.find('rv32i') != -1):
files = list_ref_files(r'../../tests/riscv-compliance/riscv-test-suite/rv32i/references')
elif (bin_file.find('rv32Zicsr') != -1):
files = list_ref_files(r'../../tests/riscv-compliance/riscv-test-suite/rv32Zicsr/references')
elif (bin_file.find('rv32Zifencei') != -1):
files = list_ref_files(r'../../tests/riscv-compliance/riscv-test-suite/rv32Zifencei/references')
else:
return None
# 根据bin文件前缀找到对应的reference_output文件
for file in files:
if (file.find(prefix) != -1):
return file
return None
# 主函数
def main():
#print(sys.argv[0] + ' ' + sys.argv[1] + ' ' + sys.argv[2])
# 1.将bin文件转成mem文件
cmd = r'python ../../tools/BinToMem_CLI.py' + ' ' + sys.argv[1] + ' ' + sys.argv[2]
f = os.popen(cmd)
f.close()
# 2.编译rtl文件
cmd = r'python ../compile_rtl.py' + r' ../..'
f = os.popen(cmd)
f.close()
# 3.运行
logfile = open('run.log', 'w')
vvp_cmd = [r'vvp']
vvp_cmd.append(r'out.vvp')
process = subprocess.Popen(vvp_cmd, stdout=logfile, stderr=logfile)
process.wait(timeout=5)
logfile.close()
# 4.比较结果
ref_file = get_reference_file(sys.argv[1])
if (ref_file != None):
# 如果文件大小不一致直接报fail
if (os.path.getsize('signature.output') != os.path.getsize(ref_file)):
print('!!! FAIL, size != !!!')
return
f1 = open('signature.output')
f2 = open(ref_file)
f1_lines = f1.readlines()
i = 0
# 逐行比较
for line in f2.readlines():
# 只要有一行内容不一样就报fail
if (f1_lines[i] != line):
print('!!! FAIL, content != !!!')
f1.close()
f2.close()
return
i = i + 1
f1.close()
f2.close()
print('### PASS ###')
else:
print('No ref file found, please check result by yourself.')
if __name__ == '__main__':
sys.exit(main())

3
sim/remote_bitbang/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.o
*.d
*.so

124
sim/remote_bitbang/Makefile Normal file
View File

@ -0,0 +1,124 @@
# Copyright (C) 2020 ETH Zurich and University of Bologna
#
# 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.
#
#
# Author: Robert Balas (balasr@iis.ee.ethz.ch)
CFLAGS = -Wall -Wextra -Wno-missing-field-initializers \
-Wno-unused-function -Wno-missing-braces \
-O2 -g -march=native \
-DENABLE_LOGGING -DNDEBUG
CFLAGS_DBG =
# we need gnu11 and no-strict-aliasing
ALL_CFLAGS = -std=gnu11 -fno-strict-aliasing $(CFLAGS)
ALL_CFLAGS_DBG = -std=gnu11 -Wall -Wextra -Wno-missing-field-initializers \
-Wno-unused-function -Wno-missing-braces \
-O0 -g -fno-strict-aliasing \
-fsanitize=address -fno-omit-frame-pointer \
-DENABLE_LOGGING -DENABLE_DEBUG $(CFLAGS_DBG)\
# -fsanitize=undefined \
# -fsanitize=leak \
# TODO: better path?
LIB_DIRS =
LIBS =
INCLUDE_DIRS = ./
LDFLAGS = $(addprefix -L, $(LIB_DIRS))
LDLIBS = $(addprefix -l, $(LIBS))
SRCS = remote_bitbang.c sim_jtag.c
OBJS = $(SRCS:.c=.o)
INCLUDES = $(addprefix -I, $(INCLUDE_DIRS))
HEADERS = $(wildcard *.h)
# libs
SV_LIB = librbs.so
# header file dependency generation
DEPDIR := .d
DEPDIRS := $(addsuffix /$(DEPDIR),.)
# goal: make gcc put a dependency file called obj.Td (derived from subdir/obj.o)
# in subdir/.d/
DEPFLAGS = -MT $@ -MMD -MP -MF $(@D)/$(DEPDIR)/$(patsubst %.o,%.Td,$(@F))
# move gcc generated header dependencies to DEPDIR
# this rename step is here to make the header dependency generation "atomic"
POSTCOMPILE = @mv -f $(@D)/$(DEPDIR)/$(patsubst %.o,%.Td,$(@F)) \
$(@D)/$(DEPDIR)/$(patsubst %.o,%.d,$(@F)) && touch $@
# GNU recommendations for install targets
prefix = /usr/local
exec_prefix = $(prefix)
bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
includedir = $(prefix)/include
INSTALL = install
INSTALL_PROGRAM = $(INSTALL)
INSTALL_DATA = ${INSTALL} -m 644
CTAGS = ctags
# compilation targets
all: sv-lib
debug: ALL_CFLAGS = $(ALL_CFLAGS_DBG)
debug: all
sv-lib: ALL_CFLAGS += -fPIC
sv-lib: $(SV_LIB)
#compilation boilerplate
$(SV_LIB): $(OBJS)
$(LD) -shared -E --exclude-libs ALL -o $(SV_LIB) $(LDFLAGS) \
$(OBJS) $(LDLIBS)
# $@ = name of target
# $< = first dependency
%.o: %.c
%.o: %.c $(DEPDIR)/%.d $(DEPDIRS)
$(CC) $(DEPFLAGS) $(ALL_CFLAGS) $(INCLUDES) $(LDFLAGS) \
-c $(CPPFLAGS) $< -o $@ $(LDLIBS)
$(POSTCOMPILE)
# check if we need to create the dependencies folders (gcc doesn't)
$(DEPDIRS):
$(shell mkdir -p $(DEPDIRS) > /dev/null)
# make won't fail if the dependency file doesn't exist
$(addsuffix /$(DEPDIR)/%.d,. main benchmark test dpi): ;
# prevent automatic deletion as intermediate file
.PRECIOUS: $(addsuffix /$(DEPDIR)/%.d,. main benchmark test dpi)
# emacs tag generation
.PHONY: TAGS
TAGS:
$(CTAGS) -R -e -h=".c.h" --tag-relative=always \
. $(LIB_DIRS) $(INCLUDE_DIRS) $(BINUTILS_PATH)/bfd
# TODO: missing install targets
# cleanup
.PHONY: clean
clean:
rm -rf $(SV_LIB) $(OBJS) $(DEPDIRS)
.PHONY: distclean
distclean: clean
rm -f TAGS
# include auto generated header dependency information
include $(wildcard $(addsuffix /*.d,$(DEPDIRS)))

View File

@ -0,0 +1,34 @@
/* Copyright (C) 2020 ETH Zurich and University of Bologna
*
* 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.
*
*
* Author: Robert Balas (balasr@iis.ee.ethz.ch)
*/
#include <stdio.h>
#include "remote_bitbang.h"
int main()
{
unsigned char jtag_TCK, jtag_TMS, jtag_TDI, jtag_TRSTn;
unsigned char jtag_TDO = 0;
printf("calling rbs_init\n");
int v = rbs_init(0);
printf("tick 1\n");
rbs_tick(&jtag_TCK, &jtag_TMS, &jtag_TDI, &jtag_TRSTn, jtag_TDO);
printf("jtag exit is %d\n", rbs_done());
return 0;
}

View File

@ -0,0 +1,275 @@
// See LICENSE.Berkeley for license details.
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "remote_bitbang.h"
int rbs_init(uint16_t port)
{
socket_fd = 0;
client_fd = 0;
recv_start = 0;
recv_end = 0;
rbs_err = 0;
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (socket_fd == -1) {
fprintf(stderr, "remote_bitbang failed to make socket: %s (%d)\n",
strerror(errno), errno);
abort();
}
fcntl(socket_fd, F_SETFL, O_NONBLOCK);
int reuseaddr = 1;
if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
sizeof(int)) == -1) {
fprintf(stderr, "remote_bitbang failed setsockopt: %s (%d)\n",
strerror(errno), errno);
abort();
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
fprintf(stderr, "remote_bitbang failed to bind socket: %s (%d)\n",
strerror(errno), errno);
abort();
}
if (listen(socket_fd, 1) == -1) {
fprintf(stderr, "remote_bitbang failed to listen on socket: %s (%d)\n",
strerror(errno), errno);
abort();
}
socklen_t addrlen = sizeof(addr);
if (getsockname(socket_fd, (struct sockaddr *)&addr, &addrlen) == -1) {
fprintf(stderr, "remote_bitbang getsockname failed: %s (%d)\n",
strerror(errno), errno);
abort();
}
tck = 1;
tms = 1;
tdi = 1;
trstn = 1;
quit = 0;
fprintf(stderr, "JTAG remote bitbang server is ready\n");
fprintf(stderr, "Listening on port %d\n", ntohs(addr.sin_port));
return 1;
}
void rbs_accept()
{
fprintf(stderr, "Attempting to accept client socket\n");
int again = 1;
while (again != 0) {
client_fd = accept(socket_fd, NULL, NULL);
if (client_fd == -1) {
if (errno == EAGAIN) {
// No client waiting to connect right now.
} else {
fprintf(stderr, "failed to accept on socket: %s (%d)\n",
strerror(errno), errno);
again = 0;
abort();
}
} else {
fcntl(client_fd, F_SETFL, O_NONBLOCK);
fprintf(stderr, "Accepted successfully.");
again = 0;
}
}
}
void rbs_tick(unsigned char *jtag_tck, unsigned char *jtag_tms,
unsigned char *jtag_tdi, unsigned char *jtag_trstn,
unsigned char jtag_tdo)
{
if (client_fd > 0) {
tdo = jtag_tdo;
rbs_execute_command();
} else {
rbs_accept();
}
*jtag_tck = tck;
*jtag_tms = tms;
*jtag_tdi = tdi;
*jtag_trstn = trstn;
}
void rbs_reset()
{
// trstn = 0;
}
void rbs_set_pins(char _tck, char _tms, char _tdi)
{
tck = _tck;
tms = _tms;
tdi = _tdi;
}
void rbs_execute_command()
{
char command;
int again = 1;
while (again) {
ssize_t num_read = read(client_fd, &command, sizeof(command));
if (num_read == -1) {
if (errno == EAGAIN) {
// We'll try again the next call.
if (VERBOSE)
fprintf(
stderr,
"Received no command. Will try again on the next call\n");
} else {
fprintf(stderr,
"remote_bitbang failed to read on socket: %s (%d)\n",
strerror(errno), errno);
again = 0;
abort();
}
} else if (num_read == 0) {
fprintf(stderr, "No command received. Stopping further reads.\n");
// again = 1;
return;
} else {
again = 0;
}
}
int dosend = 0;
char tosend = '?';
switch (command) {
case 'B':
if (VERBOSE)
fprintf(stderr, "*BLINK*\n");
break;
case 'b':
if (VERBOSE)
fprintf(stderr, "blink off\n");
break;
case 'r':
if (VERBOSE)
fprintf(stderr, "r-reset\n");
rbs_reset();
break; // This is wrong. 'r' has other bits that indicated TRST and
// SRST.
case 's':
if (VERBOSE)
fprintf(stderr, "s-reset\n");
rbs_reset();
break; // This is wrong.
case 't':
if (VERBOSE)
fprintf(stderr, "t-reset\n");
rbs_reset();
break; // This is wrong.
case 'u':
if (VERBOSE)
fprintf(stderr, "u-reset\n");
rbs_reset();
break; // This is wrong.
case '0':
if (VERBOSE)
fprintf(stderr, "Write 0 0 0\n");
rbs_set_pins(0, 0, 0);
break;
case '1':
if (VERBOSE)
fprintf(stderr, "Write 0 0 1\n");
rbs_set_pins(0, 0, 1);
break;
case '2':
if (VERBOSE)
fprintf(stderr, "Write 0 1 0\n");
rbs_set_pins(0, 1, 0);
break;
case '3':
if (VERBOSE)
fprintf(stderr, "Write 0 1 1\n");
rbs_set_pins(0, 1, 1);
break;
case '4':
if (VERBOSE)
fprintf(stderr, "Write 1 0 0\n");
rbs_set_pins(1, 0, 0);
break;
case '5':
if (VERBOSE)
fprintf(stderr, "Write 1 0 1\n");
rbs_set_pins(1, 0, 1);
break;
case '6':
if (VERBOSE)
fprintf(stderr, "Write 1 1 0\n");
rbs_set_pins(1, 1, 0);
break;
case '7':
if (VERBOSE)
fprintf(stderr, "Write 1 1 1\n");
rbs_set_pins(1, 1, 1);
break;
case 'R':
if (VERBOSE)
fprintf(stderr, "Read req\n");
dosend = 1;
tosend = tdo ? '1' : '0';
break;
case 'Q':
if (VERBOSE)
fprintf(stderr, "Quit req\n");
quit = 1;
break;
default:
fprintf(stderr, "remote_bitbang got unsupported command '%c'\n",
command);
}
if (dosend) {
while (1) {
ssize_t bytes = write(client_fd, &tosend, sizeof(tosend));
if (bytes == -1) {
fprintf(stderr, "failed to write to socket: %s (%d)\n",
strerror(errno), errno);
abort();
}
if (bytes > 0) {
break;
}
}
}
if (quit) {
fprintf(stderr, "Remote end disconnected\n");
close(client_fd);
client_fd = 0;
}
}
unsigned char rbs_done()
{
return quit;
}
int rbs_exit_code()
{
return rbs_err;
}

View File

@ -0,0 +1,52 @@
// See LICENSE.Berkeley for license details.
#ifndef REMOTE_BITBANG_H
#define REMOTE_BITBANG_H
#include <stdint.h>
#include <sys/types.h>
#define VERBOSE 0
int rbs_err;
unsigned char tck;
unsigned char tms;
unsigned char tdi;
unsigned char trstn;
unsigned char tdo;
unsigned char quit;
int socket_fd;
int client_fd;
static const ssize_t buf_size = 64 * 1024;
char recv_buf[64 * 1024];
ssize_t recv_start, recv_end;
// Create a new server, listening for connections from localhost on the given
// port.
int rbs_init(uint16_t port);
// Do a bit of work.
void rbs_tick(unsigned char *jtag_tck, unsigned char *jtag_tms,
unsigned char *jtag_tdi, unsigned char *jtag_trstn,
unsigned char jtag_tdo);
unsigned char rbs_done();
int rbs_exit_code();
// Check for a client connecting, and accept if there is one.
void rbs_accept();
// Execute any commands the client has for us.
// But we only execute 1 because we need time for the
// simulation to run.
void rbs_execute_command();
// Reset. Currently does nothing.
void rbs_reset();
void rbs_set_pins(char _tck, char _tms, char _tdi);
#endif

View File

@ -0,0 +1,29 @@
// See LICENSE.SiFive for license details.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "remote_bitbang.h"
int init = 0;
int jtag_tick(int port, unsigned char *jtag_TCK, unsigned char *jtag_TMS,
unsigned char *jtag_TDI, unsigned char *jtag_TRSTn,
unsigned char jtag_TDO)
{
if (!init) {
if (port < 0 || port > UINT16_MAX)
fprintf(stderr, "Port number of out range: %d\n", port);
init = rbs_init(port);
}
rbs_tick(jtag_TCK, jtag_TMS, jtag_TDI, jtag_TRSTn, jtag_TDO);
if (VERBOSE)
fprintf(
stderr,
"Tick with: TCK=%hhd TMS=%hhd TDI=%hhd TRSTn=%hhd --> TDO=%hhd\n",
*jtag_TCK, *jtag_TMS, *jtag_TDI, *jtag_TRSTn, jtag_TDO);
return rbs_done() ? (rbs_exit_code() << 1 | 1) : 0;
}

View File

@ -1,28 +0,0 @@
import sys
import filecmp
import subprocess
import sys
import os
# 主函数
def main():
#print(sys.argv[0] + ' ' + sys.argv[1] + ' ' + sys.argv[2])
# 1.编译rtl文件
cmd = r'python compile_rtl.py' + r' ..'
f = os.popen(cmd)
f.close()
# 2.运行
vvp_cmd = [r'vvp']
vvp_cmd.append(r'out.vvp')
process = subprocess.Popen(vvp_cmd)
try:
process.wait(timeout=10)
except subprocess.TimeoutExpired:
print('!!!Fail, vvp exec timeout!!!')
if __name__ == '__main__':
sys.exit(main())

85
sim/sim_jtag.sv Normal file
View File

@ -0,0 +1,85 @@
// See LICENSE.SiFive for license details.
//VCS coverage exclude_file
import "DPI-C" function int jtag_tick
(
input int port,
output bit jtag_TCK,
output bit jtag_TMS,
output bit jtag_TDI,
output bit jtag_TRSTn,
input bit jtag_TDO
);
module sim_jtag #(
parameter TICK_DELAY = 50,
parameter PORT = 0
)(
input clock,
input reset,
input enable,
input init_done,
output jtag_TCK,
output jtag_TMS,
output jtag_TDI,
output jtag_TRSTn,
input jtag_TDO_data,
input jtag_TDO_driven,
output [31:0] exit
);
reg [31:0] tickCounterReg;
wire [31:0] tickCounterNxt;
assign tickCounterNxt = (tickCounterReg == 0) ? TICK_DELAY : (tickCounterReg - 1);
bit r_reset;
wire [31:0] random_bits = $random;
wire #0.1 __jtag_TDO = jtag_TDO_driven ?
jtag_TDO_data : random_bits[0];
bit __jtag_TCK;
bit __jtag_TMS;
bit __jtag_TDI;
bit __jtag_TRSTn;
int __exit;
reg init_done_sticky;
assign #0.1 jtag_TCK = __jtag_TCK;
assign #0.1 jtag_TMS = __jtag_TMS;
assign #0.1 jtag_TDI = __jtag_TDI;
assign #0.1 jtag_TRSTn = __jtag_TRSTn;
assign #0.1 exit = __exit;
always @(posedge clock) begin
r_reset <= reset;
if (reset || r_reset) begin
__exit = 0;
tickCounterReg <= TICK_DELAY;
init_done_sticky <= 1'b0;
end else begin
init_done_sticky <= init_done | init_done_sticky;
if (enable && init_done_sticky) begin
tickCounterReg <= tickCounterNxt;
if (tickCounterReg == 0) begin
__exit = jtag_tick(PORT,
__jtag_TCK,
__jtag_TMS,
__jtag_TDI,
__jtag_TRSTn,
__jtag_TDO);
end
end // if (enable && init_done_sticky)
end // else: !if(reset || r_reset)
end // always @ (posedge clock)
endmodule

View File

@ -1,33 +0,0 @@
import sys
import filecmp
import subprocess
import sys
import os
# 主函数
def main():
#print(sys.argv[0] + ' ' + sys.argv[1] + ' ' + sys.argv[2])
# 1.将bin文件转成mem文件
cmd = r'python ../tools/BinToMem_CLI.py' + ' ' + sys.argv[1] + ' ' + sys.argv[2]
f = os.popen(cmd)
f.close()
# 2.编译rtl文件
cmd = r'python compile_rtl.py' + r' ..'
f = os.popen(cmd)
f.close()
# 3.运行
vvp_cmd = [r'vvp']
vvp_cmd.append(r'out.vvp')
process = subprocess.Popen(vvp_cmd)
try:
process.wait(timeout=20)
except subprocess.TimeoutExpired:
print('!!!Fail, vvp exec timeout!!!')
if __name__ == '__main__':
sys.exit(main())

108
sim/tb_top_verilator.cpp Normal file
View File

@ -0,0 +1,108 @@
// Copyright 2018 Robert Balas <balasr@student.ethz.ch>
//
// 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.
// Top level wrapper for a verilator RI5CY testbench
// Contributor: Robert Balas <balasr@student.ethz.ch>
#include "svdpi.h"
#include "Vtb_top_verilator__Dpi.h"
#include "Vtb_top_verilator.h"
#include "verilated_vcd_c.h"
#include "verilated.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <exception>
#include <cstdio>
#include <cstdint>
#include <cerrno>
//void dump_memory();
double sc_time_stamp();
static vluint64_t t = 0;
Vtb_top_verilator *top;
int main(int argc, char **argv, char **env)
{
Verilated::commandArgs(argc, argv);
Verilated::traceEverOn(true);
top = new Vtb_top_verilator();
//svSetScope(svGetScopeFromName(
// "TOP.tb_top_verilator.u_ram.ram"));
//Verilated::scopesDump();
#ifdef VCD_TRACE
VerilatedVcdC *tfp = new VerilatedVcdC;
top->trace(tfp, 99);
tfp->open("verilator_tb.vcd");
#endif
top->fetch_enable_i = 1;
top->clk_i = 0;
top->rst_ni = 0;
top->eval();
//dump_memory();
while (!Verilated::gotFinish()) {
if (t > 40)
top->rst_ni = 1;
top->clk_i = !top->clk_i;
top->eval();
#ifdef VCD_TRACE
tfp->dump(t);
#endif
t += 5;
if (t > 1000)
break;
}
#ifdef VCD_TRACE
tfp->close();
#endif
delete top;
exit(0);
}
double sc_time_stamp()
{
return t;
}
/*
void dump_memory()
{
errno = 0;
std::ofstream mem_file;
svLogicVecVal addr = {0};
mem_file.exceptions(std::ofstream::failbit | std::ofstream::badbit);
try {
mem_file.open("memory_dump.bin");
for (size_t i = 0; i < 1048576; i++) {
addr.aval = i;
uint32_t val = read_byte(&addr);
mem_file << std::setfill('0') << std::setw(2) << std::hex << val
<< std::endl;
}
mem_file.close();
std::cout << "finished dumping memory" << std::endl;
} catch (std::ofstream::failure e) {
std::cerr << "exception opening/reading/closing file memory_dump.bin\n";
}
}
*/

48
sim/tb_top_verilator.sv Normal file
View File

@ -0,0 +1,48 @@
// Copyright 2018 Robert Balas <balasr@student.ethz.ch>
// 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.
// Top level wrapper for a verilator RI5CY testbench
// Contributor: Robert Balas <balasr@student.ethz.ch>
module tb_top_verilator #(
) (
input clk_i,
input rst_ni,
input fetch_enable_i
);
initial begin: load_prog
automatic logic [1023:0] firmware;
if($value$plusargs("firmware=%s", firmware)) begin
//if($test$plusargs("verbose"))
$display("[TESTBENCH] %t: loading firmware %0s ...",
$time, firmware);
$readmemh (firmware, u_tinyriscv_soc_top.u_rom.u_gen_ram.ram);
//$display("mem[0x80]=0x%x", u_ram.ram.mem[32]);
//$display("mem[0x84]=0x%x", u_ram.ram.mem[33]);
end else begin
$display("No firmware specified");
end
end
tinyriscv_soc_top u_tinyriscv_soc_top(
.clk(clk_i),
.rst_ext_i(rst_ni)
);
endmodule // tb_top_verilator

View File

@ -1,43 +0,0 @@
import os
import subprocess
import sys
# 找出path目录下的所有bin文件
def list_binfiles(path):
files = []
list_dir = os.walk(path)
for maindir, subdir, all_file in list_dir:
for filename in all_file:
apath = os.path.join(maindir, filename)
if apath.endswith('.bin'):
files.append(apath)
return files
# 主函数
def main():
bin_files = list_binfiles(r'../tests/isa/generated')
anyfail = False
# 对每一个bin文件进行测试
for file in bin_files:
#print(file)
cmd = r'python sim_new_nowave.py' + ' ' + file + ' ' + 'inst.data'
f = os.popen(cmd)
r = f.read()
f.close()
if (r.find('TEST_PASS') != -1):
print(file + ' PASS')
else:
print(file + ' !!!FAIL!!!')
anyfail = True
break
if (anyfail == False):
print('Congratulation, All PASS...')
if __name__ == '__main__':
sys.exit(main())

View File

@ -1,72 +0,0 @@
import sys
import filecmp
import subprocess
import sys
import os
# 主函数
def main():
rtl_dir = '..'
tb_file = r'/tb/jtag_tb.v'
# iverilog程序
iverilog_cmd = ['iverilog']
# 顶层模块
#iverilog_cmd += ['-s', r'tinyriscv_soc_tb']
# 编译生成文件
iverilog_cmd += ['-o', r'out.vvp']
# 头文件(defines.v)路径
iverilog_cmd += ['-I', rtl_dir + r'/rtl/core']
# 宏定义,仿真输出文件
iverilog_cmd += ['-D', r'OUTPUT="signature.output"']
# testbench文件
iverilog_cmd.append(rtl_dir + tb_file)
# ../rtl/core
iverilog_cmd.append(rtl_dir + r'/rtl/core/clint.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/csr_reg.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/defines.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/divider.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_alu_datapath.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_commit.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_dispatch.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_mem.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_muldiv.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/gpr_reg.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/idu.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/idu_exu.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/ifu.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/ifu_idu.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/pipe_ctrl.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/tinyriscv_core.v')
iverilog_cmd.append(rtl_dir + r'/rtl/core/rst_ctrl.v')
# ../rtl/perips
iverilog_cmd.append(rtl_dir + r'/rtl/perips/ram.v')
iverilog_cmd.append(rtl_dir + r'/rtl/perips/rom.v')
iverilog_cmd.append(rtl_dir + r'/rtl/perips/timer.v')
iverilog_cmd.append(rtl_dir + r'/rtl/perips/uart.v')
iverilog_cmd.append(rtl_dir + r'/rtl/perips/gpio.v')
# ../rtl/debug
iverilog_cmd.append(rtl_dir + r'/rtl/debug/jtag_dm.v')
iverilog_cmd.append(rtl_dir + r'/rtl/debug/jtag_driver.v')
iverilog_cmd.append(rtl_dir + r'/rtl/debug/jtag_top.v')
# ../rtl/sys_bus
iverilog_cmd.append(rtl_dir + r'/rtl/sys_bus/rib.v')
# ../rtl/utils
iverilog_cmd.append(rtl_dir + r'/rtl/utils/full_handshake_rx.v')
iverilog_cmd.append(rtl_dir + r'/rtl/utils/full_handshake_tx.v')
iverilog_cmd.append(rtl_dir + r'/rtl/utils/gen_buf.v')
iverilog_cmd.append(rtl_dir + r'/rtl/utils/gen_dff.v')
iverilog_cmd.append(rtl_dir + r'/rtl/utils/gen_ram.v')
iverilog_cmd.append(rtl_dir + r'/rtl/utils/vld_rdy.v')
# ../rtl/top
iverilog_cmd.append(rtl_dir + r'/rtl/top/tinyriscv_soc_top.v')
# 编译
process = subprocess.Popen(iverilog_cmd)
process.wait(timeout=5)
if __name__ == '__main__':
sys.exit(main())

View File

@ -1,3 +0,0 @@
tinyriscv_soc_tb.v是适用于旧的指令测试testbench文件。
compliance_test/tinyriscv_soc_tb.v是适用于新的指令测试testbench文件。

View File

@ -1,535 +0,0 @@
`timescale 1 ns / 1 ps
`include "defines.v"
// select one option only
`define TEST_PROG 1
//`define TEST_JTAG 1
// testbench module
module tinyriscv_soc_tb;
reg clk;
reg rst_n;
always #10 clk = ~clk; // 50MHz
wire[31:0] x3 = tinyriscv_soc_top_0.u_tinyriscv_core.u_gpr_reg.regs[3];
wire[31:0] x26 = tinyriscv_soc_top_0.u_tinyriscv_core.u_gpr_reg.regs[26];
wire[31:0] x27 = tinyriscv_soc_top_0.u_tinyriscv_core.u_gpr_reg.regs[27];
wire[31:0] ex_end_flag = tinyriscv_soc_top_0.u_ram.u_gen_ram.ram[4];
wire[31:0] begin_signature = tinyriscv_soc_top_0.u_ram.u_gen_ram.ram[2];
wire[31:0] end_signature = tinyriscv_soc_top_0.u_ram.u_gen_ram.ram[3];
integer r;
integer fd;
`ifdef TEST_JTAG
reg TCK;
reg TMS;
reg TDI;
wire TDO;
integer i;
reg[39:0] shift_reg;
reg in;
wire[39:0] req_data = tinyriscv_soc_top_0.u_jtag_top.u_jtag_driver.dtm_req_data;
wire[4:0] ir_reg = tinyriscv_soc_top_0.u_jtag_top.u_jtag_driver.ir_reg;
wire dtm_req_valid = tinyriscv_soc_top_0.u_jtag_top.u_jtag_driver.dtm_req_valid;
wire[31:0] dmstatus = tinyriscv_soc_top_0.u_jtag_top.u_jtag_dm.dmstatus;
`endif
initial begin
clk = 0;
rst_n = 1'b1;
`ifdef TEST_JTAG
TCK = 1;
TMS = 1;
TDI = 1;
`endif
$display("test running...");
#100
rst_n = 1'b0;
#100
rst_n = 1'b1;
#200
/*
`ifdef TEST_PROG
wait(x26 == 32'b1) // wait sim end, when x26 == 1
#100
if (x27 == 32'b1) begin
$display("~~~~~~~~~~~~~~~~~~~ TEST_PASS ~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~ ##### ## #### #### ~~~~~~~~~");
$display("~~~~~~~~~ # # # # # # ~~~~~~~~~");
$display("~~~~~~~~~ # # # # #### #### ~~~~~~~~~");
$display("~~~~~~~~~ ##### ###### # #~~~~~~~~~");
$display("~~~~~~~~~ # # # # # # #~~~~~~~~~");
$display("~~~~~~~~~ # # # #### #### ~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
end else begin
$display("~~~~~~~~~~~~~~~~~~~ TEST_FAIL ~~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~~###### ## # # ~~~~~~~~~~");
$display("~~~~~~~~~~# # # # # ~~~~~~~~~~");
$display("~~~~~~~~~~##### # # # # ~~~~~~~~~~");
$display("~~~~~~~~~~# ###### # # ~~~~~~~~~~");
$display("~~~~~~~~~~# # # # # ~~~~~~~~~~");
$display("~~~~~~~~~~# # # # ######~~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
$display("fail testnum = %2d", x3);
for (r = 0; r < 32; r = r + 1)
$display("x%2d = 0x%x", r, tinyriscv_soc_top_0.u_tinyriscv_core.u_gpr_reg.regs[r]);
end
`endif
*/
wait(ex_end_flag == 32'h1); // wait sim end
fd = $fopen(`OUTPUT); // OUTPUT
for (r = begin_signature; r < end_signature; r = r + 4) begin
$fdisplay(fd, "%x", tinyriscv_soc_top_0.u_rom.u_gen_ram.ram[r[31:2]]);
end
$fclose(fd);
`ifdef TEST_JTAG
// reset
for (i = 0; i < 8; i++) begin
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
end
// IR
shift_reg = 40'b10001;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SELECT-DR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SELECT-IR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// CAPTURE-IR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SHIFT-IR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SHIFT-IR & EXIT1-IR
for (i = 5; i > 0; i--) begin
if (shift_reg[0] == 1'b1)
TDI = 1'b1;
else
TDI = 1'b0;
if (i == 1)
TMS = 1;
TCK = 0;
#100
in = TDO;
TCK = 1;
#100
TCK = 0;
shift_reg = {{(35){1'b0}}, in, shift_reg[4:1]};
end
// PAUSE-IR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// EXIT2-IR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// UPDATE-IR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// dmi write
shift_reg = {6'h10, {(32){1'b0}}, 2'b10};
// SELECT-DR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// CAPTURE-DR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SHIFT-DR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SHIFT-DR & EXIT1-DR
for (i = 40; i > 0; i--) begin
if (shift_reg[0] == 1'b1)
TDI = 1'b1;
else
TDI = 1'b0;
if (i == 1)
TMS = 1;
TCK = 0;
#100
in = TDO;
TCK = 1;
#100
TCK = 0;
shift_reg = {in, shift_reg[39:1]};
end
// PAUSE-DR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// EXIT2-DR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// UPDATE-DR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
$display("ir_reg = 0x%x", ir_reg);
$display("dtm_req_valid = %d", dtm_req_valid);
$display("req_data = 0x%x", req_data);
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
$display("dmstatus = 0x%x", dmstatus);
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SELECT-DR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// dmi read
shift_reg = {6'h11, {(32){1'b0}}, 2'b01};
// CAPTURE-DR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SHIFT-DR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SHIFT-DR & EXIT1-DR
for (i = 40; i > 0; i--) begin
if (shift_reg[0] == 1'b1)
TDI = 1'b1;
else
TDI = 1'b0;
if (i == 1)
TMS = 1;
TCK = 0;
#100
in = TDO;
TCK = 1;
#100
TCK = 0;
shift_reg = {in, shift_reg[39:1]};
end
// PAUSE-DR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// EXIT2-DR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// UPDATE-DR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SELECT-DR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// dmi read
shift_reg = {6'h11, {(32){1'b0}}, 2'b00};
// CAPTURE-DR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SHIFT-DR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SHIFT-DR & EXIT1-DR
for (i = 40; i > 0; i--) begin
if (shift_reg[0] == 1'b1)
TDI = 1'b1;
else
TDI = 1'b0;
if (i == 1)
TMS = 1;
TCK = 0;
#100
in = TDO;
TCK = 1;
#100
TCK = 0;
shift_reg = {in, shift_reg[39:1]};
end
#100
$display("shift_reg = 0x%x", shift_reg[33:2]);
if (dmstatus == shift_reg[33:2]) begin
$display("######################");
$display("### jtag test pass ###");
$display("######################");
end else begin
$display("######################");
$display("!!! jtag test fail !!!");
$display("######################");
end
`endif
$finish;
end
// sim timeout
initial begin
#500000
$display("Time Out.");
$finish;
end
// read mem data
initial begin
$readmemh ("inst.data", tinyriscv_soc_top_0.u_rom.u_gen_ram.ram);
end
// generate wave file, used by gtkwave
initial begin
$dumpfile("tinyriscv_soc_tb.vcd");
$dumpvars(0, tinyriscv_soc_tb);
end
tinyriscv_soc_top tinyriscv_soc_top_0(
.clk(clk),
.rst_ext_i(rst_n)
`ifdef TEST_JTAG
,
.jtag_TCK(TCK),
.jtag_TMS(TMS),
.jtag_TDI(TDI),
.jtag_TDO(TDO)
`endif
);
endmodule

View File

@ -1,733 +0,0 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
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.
*/
`timescale 1 ns / 1 ps
`include "defines.v"
`define JTAG_CLK 500 // 1MHz. This value do not less than 100
module jtag_tb;
reg clk;
reg rst_n;
reg TCK;
reg TMS;
reg TDI;
wire TDO;
reg[39:0] shift_reg;
reg in;
reg[39:0] resp_data;
always #10 clk = ~clk; // core clock = 50MHz
integer i;
integer j;
task tap_reset;
begin
for (i = 0; i < 8; i = i + 1) begin
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
end
end
endtask
task select_ir;
input[39:0] ir;
begin
// IR
shift_reg = ir;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// SELECT-DR
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// SELECT-IR
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// CAPTURE-IR
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// SHIFT-IR
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// SHIFT-IR & EXIT1-IR
for (i = 5; i > 0; i = i - 1) begin
if (shift_reg[0] == 1'b1)
TDI = 1'b1;
else
TDI = 1'b0;
if (i == 1)
TMS = 1;
TCK = 0;
#`JTAG_CLK
in = TDO;
TCK = 1;
#`JTAG_CLK
TCK = 0;
shift_reg = {{(35){1'b0}}, in, shift_reg[4:1]};
end
// PAUSE-IR
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// EXIT2-IR
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// UPDATE-IR
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
end
endtask
task dmi_write;
input[5:0] addr;
input[31:0] data;
output[39:0] out;
begin
// op write
shift_reg = {addr, data, 2'b10};
// SELECT-DR
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// CAPTURE-DR
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// SHIFT-DR
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// SHIFT-DR & EXIT1-DR
for (i = 40; i > 0; i = i - 1) begin
if (shift_reg[0] == 1'b1)
TDI = 1'b1;
else
TDI = 1'b0;
if (i == 1)
TMS = 1;
TCK = 0;
#`JTAG_CLK
in = TDO;
TCK = 1;
#`JTAG_CLK
TCK = 0;
shift_reg = {in, shift_reg[39:1]};
end
// PAUSE-DR
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// EXIT2-DR
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// UPDATE-DR
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// op nop
shift_reg = {addr, {(32){1'b0}}, 2'b00};
// SELECT-DR
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// CAPTURE-DR
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// SHIFT-DR
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// SHIFT-DR & EXIT1-DR
for (i = 40; i > 0; i = i - 1) begin
if (shift_reg[0] == 1'b1)
TDI = 1'b1;
else
TDI = 1'b0;
if (i == 1)
TMS = 1;
TCK = 0;
#`JTAG_CLK
in = TDO;
TCK = 1;
#`JTAG_CLK
TCK = 0;
shift_reg = {in, shift_reg[39:1]};
end
// PAUSE-DR
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// EXIT2-DR
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// UPDATE-DR
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
out = shift_reg;
end
endtask
task dmi_read;
input[5:0] addr;
output[39:0] out;
begin
// op read
shift_reg = {addr, {(32){1'b0}}, 2'b01};
// SELECT-DR
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// CAPTURE-DR
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// SHIFT-DR
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// SHIFT-DR & EXIT1-DR
for (i = 40; i > 0; i = i - 1) begin
if (shift_reg[0] == 1'b1)
TDI = 1'b1;
else
TDI = 1'b0;
if (i == 1)
TMS = 1;
TCK = 0;
#`JTAG_CLK
in = TDO;
TCK = 1;
#`JTAG_CLK
TCK = 0;
shift_reg = {in, shift_reg[39:1]};
end
// PAUSE-DR
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// EXIT2-DR
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// UPDATE-DR
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// op nop
shift_reg = {addr, {(32){1'b0}}, 2'b00};
// SELECT-DR
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// CAPTURE-DR
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// SHIFT-DR
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// SHIFT-DR & EXIT1-DR
for (i = 40; i > 0; i = i - 1) begin
if (shift_reg[0] == 1'b1)
TDI = 1'b1;
else
TDI = 1'b0;
if (i == 1)
TMS = 1;
TCK = 0;
#`JTAG_CLK
in = TDO;
TCK = 1;
#`JTAG_CLK
TCK = 0;
shift_reg = {in, shift_reg[39:1]};
end
// PAUSE-DR
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// EXIT2-DR
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// UPDATE-DR
TMS = 1;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#`JTAG_CLK
TCK = 1;
#`JTAG_CLK
TCK = 0;
out = shift_reg;
end
endtask
initial begin
clk = 0;
rst_n = 1'b1;
TCK = 1;
TMS = 1;
TDI = 1;
shift_reg = 40'h0;
resp_data = 40'h0;
in = 1'b0;
$display("test running...");
#100
rst_n = 1'b0;
#100
rst_n = 1'b1;
#200
/*************************** start test ***************************/
// reset TAP state machine
tap_reset();
// select dm regs
select_ir(40'b10001);
// reset dm module
dmi_write(6'h10, 32'h0, resp_data);
// read dmstatus reg
dmi_read(6'h11, resp_data);
$display("dmstatus = 0x%x", resp_data[33:2]);
// write data to memory
dmi_write(6'h38, 32'h20050404, resp_data); // write sbcs
dmi_write(6'h39, 32'h0, resp_data); // write sbaddress0
for (j = 0; j < 5; j = j + 1) begin
$display("write: addr = 0x%x, data = 0x%x", j * 4, 32'h0 + j);
dmi_write(6'h3c, 32'h0 + j, resp_data); // write sbdata0
end
// read data from memory
dmi_write(6'h38, 32'h20158404, resp_data); // write sbcs
dmi_write(6'h39, 32'h0, resp_data); // write sbaddress0
for (j = 0; j < 5; j = j + 1) begin
dmi_read(6'h3c, resp_data); // read sbdata0
$display("read: addr = 0x%x, data = 0x%x", j * 4, resp_data[33:2]);
end
///////////////////////////////////////////////////////////
// Check whether the data read is equal to the data written.
///////////////////////////////////////////////////////////
$finish;
end
// sim timeout
initial begin
#10000000
$display("Time Out.");
$finish;
end
// generate wave file, used by gtkwave
initial begin
$dumpfile("jtag_tb.vcd");
$dumpvars(0, jtag_tb);
end
tinyriscv_soc_top tinyriscv_soc_top_0(
.clk(clk),
.rst_ext_i(rst_n),
.jtag_TCK(TCK),
.jtag_TMS(TMS),
.jtag_TDI(TDI),
.jtag_TDO(TDO)
);
endmodule

View File

@ -1,521 +0,0 @@
`timescale 1 ns / 1 ps
`include "defines.v"
// select one option only
`define TEST_PROG 1
//`define TEST_JTAG 1
// testbench module
module tinyriscv_soc_tb;
reg clk;
reg rst_n;
always #10 clk = ~clk; // 50MHz
wire[31:0] x3 = tinyriscv_soc_top_0.u_tinyriscv_core.u_gpr_reg.regs[3];
wire[31:0] x26 = tinyriscv_soc_top_0.u_tinyriscv_core.u_gpr_reg.regs[26];
wire[31:0] x27 = tinyriscv_soc_top_0.u_tinyriscv_core.u_gpr_reg.regs[27];
integer r;
`ifdef TEST_JTAG
reg TCK;
reg TMS;
reg TDI;
wire TDO;
integer i;
reg[39:0] shift_reg;
reg in;
wire[39:0] req_data = tinyriscv_soc_top_0.u_jtag_top.u_jtag_driver.dtm_req_data;
wire[4:0] ir_reg = tinyriscv_soc_top_0.u_jtag_top.u_jtag_driver.ir_reg;
wire dtm_req_valid = tinyriscv_soc_top_0.u_jtag_top.u_jtag_driver.dtm_req_valid;
wire[31:0] dmstatus = tinyriscv_soc_top_0.u_jtag_top.u_jtag_dm.dmstatus;
`endif
initial begin
clk = 0;
rst_n = 1'b1;
`ifdef TEST_JTAG
TCK = 1;
TMS = 1;
TDI = 1;
`endif
$display("test running...");
#100
rst_n = 1'b0;
#100
rst_n = 1'b1;
#200
`ifdef TEST_PROG
wait(x26 == 32'b1) // wait sim end, when x26 == 1
#100
if (x27 == 32'b1) begin
$display("~~~~~~~~~~~~~~~~~~~ TEST_PASS ~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~ ##### ## #### #### ~~~~~~~~~");
$display("~~~~~~~~~ # # # # # # ~~~~~~~~~");
$display("~~~~~~~~~ # # # # #### #### ~~~~~~~~~");
$display("~~~~~~~~~ ##### ###### # #~~~~~~~~~");
$display("~~~~~~~~~ # # # # # # #~~~~~~~~~");
$display("~~~~~~~~~ # # # #### #### ~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
end else begin
$display("~~~~~~~~~~~~~~~~~~~ TEST_FAIL ~~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~~###### ## # # ~~~~~~~~~~");
$display("~~~~~~~~~~# # # # # ~~~~~~~~~~");
$display("~~~~~~~~~~##### # # # # ~~~~~~~~~~");
$display("~~~~~~~~~~# ###### # # ~~~~~~~~~~");
$display("~~~~~~~~~~# # # # # ~~~~~~~~~~");
$display("~~~~~~~~~~# # # # ######~~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
$display("fail testnum = %2d", x3);
for (r = 0; r < 32; r = r + 1)
$display("x%2d = 0x%x", r, tinyriscv_soc_top_0.u_tinyriscv_core.u_gpr_reg.regs[r]);
end
`endif
`ifdef TEST_JTAG
// reset
for (i = 0; i < 8; i++) begin
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
end
// IR
shift_reg = 40'b10001;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SELECT-DR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SELECT-IR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// CAPTURE-IR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SHIFT-IR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SHIFT-IR & EXIT1-IR
for (i = 5; i > 0; i--) begin
if (shift_reg[0] == 1'b1)
TDI = 1'b1;
else
TDI = 1'b0;
if (i == 1)
TMS = 1;
TCK = 0;
#100
in = TDO;
TCK = 1;
#100
TCK = 0;
shift_reg = {{(35){1'b0}}, in, shift_reg[4:1]};
end
// PAUSE-IR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// EXIT2-IR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// UPDATE-IR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// dmi write
shift_reg = {6'h10, {(32){1'b0}}, 2'b10};
// SELECT-DR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// CAPTURE-DR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SHIFT-DR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SHIFT-DR & EXIT1-DR
for (i = 40; i > 0; i--) begin
if (shift_reg[0] == 1'b1)
TDI = 1'b1;
else
TDI = 1'b0;
if (i == 1)
TMS = 1;
TCK = 0;
#100
in = TDO;
TCK = 1;
#100
TCK = 0;
shift_reg = {in, shift_reg[39:1]};
end
// PAUSE-DR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// EXIT2-DR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// UPDATE-DR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
$display("ir_reg = 0x%x", ir_reg);
$display("dtm_req_valid = %d", dtm_req_valid);
$display("req_data = 0x%x", req_data);
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
$display("dmstatus = 0x%x", dmstatus);
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SELECT-DR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// dmi read
shift_reg = {6'h11, {(32){1'b0}}, 2'b01};
// CAPTURE-DR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SHIFT-DR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SHIFT-DR & EXIT1-DR
for (i = 40; i > 0; i--) begin
if (shift_reg[0] == 1'b1)
TDI = 1'b1;
else
TDI = 1'b0;
if (i == 1)
TMS = 1;
TCK = 0;
#100
in = TDO;
TCK = 1;
#100
TCK = 0;
shift_reg = {in, shift_reg[39:1]};
end
// PAUSE-DR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// EXIT2-DR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// UPDATE-DR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// IDLE
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SELECT-DR
TMS = 1;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// dmi read
shift_reg = {6'h11, {(32){1'b0}}, 2'b00};
// CAPTURE-DR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SHIFT-DR
TMS = 0;
TCK = 0;
#100
TCK = 1;
#100
TCK = 0;
// SHIFT-DR & EXIT1-DR
for (i = 40; i > 0; i--) begin
if (shift_reg[0] == 1'b1)
TDI = 1'b1;
else
TDI = 1'b0;
if (i == 1)
TMS = 1;
TCK = 0;
#100
in = TDO;
TCK = 1;
#100
TCK = 0;
shift_reg = {in, shift_reg[39:1]};
end
#100
$display("shift_reg = 0x%x", shift_reg[33:2]);
if (dmstatus == shift_reg[33:2]) begin
$display("######################");
$display("### jtag test pass ###");
$display("######################");
end else begin
$display("######################");
$display("!!! jtag test fail !!!");
$display("######################");
end
`endif
$finish;
end
// sim timeout
initial begin
#1000000
$display("Time Out.");
$finish;
end
// read mem data
initial begin
$readmemh ("inst.data", tinyriscv_soc_top_0.u_rom.u_gen_ram.ram);
end
// generate wave file, used by gtkwave
initial begin
$dumpfile("tinyriscv_soc_tb.vcd");
$dumpvars(0, tinyriscv_soc_tb);
end
tinyriscv_soc_top tinyriscv_soc_top_0(
.clk(clk),
.rst_ext_i(rst_n)
`ifdef TEST_JTAG
,
.jtag_TCK(TCK),
.jtag_TMS(TMS),
.jtag_TDI(TDI),
.jtag_TDO(TDO)
`endif
);
endmodule

3
tools/.gitignore vendored
View File

@ -4,6 +4,3 @@
*.obj
*.bin
*.dump
__pycache__
gnu-mcu-eclipse-riscv-none-gcc-8.2.0-2.2-20190521-0004-win64

View File

@ -1,3 +1,5 @@
#!/usr/bin/env python3
import sys
import os

BIN
tools/openocd/openocd Normal file

Binary file not shown.

Binary file not shown.