Merge pull request #1179 from freechipsproject/refactored_rbb
Add Debug tests to Regressions
This commit is contained in:
commit
8799508b1f
@ -1,8 +1,7 @@
|
||||
git:
|
||||
submodules: false
|
||||
language: scala
|
||||
# run on new infrastructure
|
||||
sudo: false
|
||||
sudo: required
|
||||
cache:
|
||||
apt: true
|
||||
directories:
|
||||
@ -32,6 +31,7 @@ addons:
|
||||
- texinfo
|
||||
- device-tree-compiler
|
||||
- libusb-1.0-0-dev
|
||||
- python-pexpect
|
||||
|
||||
|
||||
# blacklist private branches
|
||||
@ -69,6 +69,11 @@ jobs:
|
||||
- export CXX=g++-4.8 CC=gcc-4.8
|
||||
- &test
|
||||
stage: Test
|
||||
script:
|
||||
- travis_wait 80 make emulator-ndebug -C regression SUITE=JtagDtmSuite JVM_MEMORY=3G
|
||||
- travis_wait 80 make emulator-jtag-dtm-tests-32 -C regression SUITE=JtagDtmSuite JVM_MEMORY=3G
|
||||
- travis_wait 80 make emulator-jtag-dtm-tests-64 -C regression SUITE=JtagDtmSuite JVM_MEMORY=3G
|
||||
- <<: *test
|
||||
script:
|
||||
- travis_wait 80 make emulator-ndebug -C regression SUITE=UnittestSuite JVM_MEMORY=3G
|
||||
- travis_wait 80 make emulator-regression-tests -C regression SUITE=UnittestSuite JVM_MEMORY=3G
|
||||
|
@ -6,27 +6,6 @@
|
||||
|
||||
dtm_t* dtm;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
// Remove args that will confuse dtm, such as those that require two tokens, like VCS code coverage "-cm line+cond"
|
||||
std::vector<std::string> filter_argv_for_dtm(int argc, char** argv)
|
||||
{
|
||||
std::vector<std::string> out;
|
||||
for (int i = 1; i < argc; ++i) { // start with 1 to skip my executable name
|
||||
if (!strncmp(argv[i], "-cm", 3)) {
|
||||
++i; // skip this one and the next one
|
||||
}
|
||||
else {
|
||||
out.push_back(argv[i]);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
extern "C" int debug_tick
|
||||
(
|
||||
unsigned char* debug_req_valid,
|
||||
@ -44,7 +23,7 @@ extern "C" int debug_tick
|
||||
s_vpi_vlog_info info;
|
||||
if (!vpi_get_vlog_info(&info))
|
||||
abort();
|
||||
dtm = new dtm_t(filter_argv_for_dtm(info.argc, info.argv));
|
||||
dtm = new dtm_t(info.argc, info.argv);
|
||||
}
|
||||
|
||||
dtm_t::resp resp_bits;
|
||||
|
32
csrc/SimJTAG.cc
Normal file
32
csrc/SimJTAG.cc
Normal file
@ -0,0 +1,32 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
#include <vpi_user.h>
|
||||
#include <svdpi.h>
|
||||
#include <cstdlib>
|
||||
#include "remote_bitbang.h"
|
||||
|
||||
remote_bitbang_t* jtag;
|
||||
|
||||
extern "C" int jtag_tick
|
||||
(
|
||||
unsigned char * jtag_TCK,
|
||||
unsigned char * jtag_TMS,
|
||||
unsigned char * jtag_TDI,
|
||||
unsigned char * jtag_TRSTn,
|
||||
unsigned char jtag_TDO
|
||||
)
|
||||
{
|
||||
if (!jtag) {
|
||||
s_vpi_vlog_info info;
|
||||
if (!vpi_get_vlog_info(&info)) {
|
||||
abort();
|
||||
}
|
||||
// TODO: Pass in real port number
|
||||
jtag = new remote_bitbang_t(0);
|
||||
}
|
||||
|
||||
jtag->tick(jtag_TCK, jtag_TMS, jtag_TDI, jtag_TRSTn, jtag_TDO);
|
||||
|
||||
return jtag->done() ? (jtag->exit_code() << 1 | 1) : 0;
|
||||
|
||||
}
|
192
csrc/emulator.cc
192
csrc/emulator.cc
@ -6,6 +6,7 @@
|
||||
#include "verilated_vcd_c.h"
|
||||
#endif
|
||||
#include <fesvr/dtm.h>
|
||||
#include "remote_bitbang.h"
|
||||
#include <iostream>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
@ -14,7 +15,16 @@
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
//TODO: GENERATE THESE AUTOMATICALLY!
|
||||
static const char * verilog_plusargs [] = { "max-core-cycles",
|
||||
"jtag_rbb_enable",
|
||||
"tilelink_timeout",
|
||||
0};
|
||||
|
||||
|
||||
extern dtm_t* dtm;
|
||||
extern remote_bitbang_t * jtag;
|
||||
|
||||
static uint64_t trace_count = 0;
|
||||
bool verbose;
|
||||
bool done_reset;
|
||||
@ -34,33 +44,58 @@ extern "C" int vpi_get_vlog_info(void* arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usage(const char * program_name) {
|
||||
printf("Usage: %s [OPTION]... BINARY [BINARY ARGS]\n", program_name);
|
||||
static void usage(const char * program_name)
|
||||
{
|
||||
printf("Usage: %s [EMULATOR OPTION]... [VERILOG PLUSARG]... [HOST OPTION]... BINARY [TARGET OPTION]...\n",
|
||||
program_name);
|
||||
fputs("\
|
||||
Run a BINARY on the Rocket Chip emulator.\n\
|
||||
\n\
|
||||
Mandatory arguments to long options are mandatory for short options too.\n\
|
||||
-c, --cycle-count print the cycle count before exiting\n\
|
||||
\n\
|
||||
EMULATOR OPTIONS\n\
|
||||
-c, --cycle-count Print the cycle count before exiting\n\
|
||||
+cycle-count\n\
|
||||
-h, --help display this help and exit\n\
|
||||
-m, --max-cycles=CYCLES kill the emulation after CYCLES\n\
|
||||
-h, --help Display this help and exit\n\
|
||||
-m, --max-cycles=CYCLES Kill the emulation after CYCLES\n\
|
||||
+max-cycles=CYCLES\n\
|
||||
-s, --seed=SEED use random number seed SEED\n\
|
||||
-V, --verbose enable all Chisel printfs\n\
|
||||
-s, --seed=SEED Use random number seed SEED\n\
|
||||
-V, --verbose Enable all Chisel printfs (cycle-by-cycle info)\n\
|
||||
+verbose\n\
|
||||
", stdout);
|
||||
#if VM_TRACE
|
||||
#if VM_TRACE == 0
|
||||
fputs("\
|
||||
-v, --vcd=FILE, write vcd trace to FILE (or '-' for stdout)\n\
|
||||
-x, --dump-start=CYCLE start VCD tracing at CYCLE\n\
|
||||
+dump-start\n\
|
||||
", stdout);
|
||||
#else
|
||||
fputs("\
|
||||
VCD options (e.g., -v, +dump-start) require a debug-enabled emulator.\n\
|
||||
Try `make debug`.\n\
|
||||
", stdout);
|
||||
\n\
|
||||
EMULATOR OPTIONS (only supported in debug build -- try `make debug`)\n",
|
||||
stdout);
|
||||
#endif
|
||||
fputs("\
|
||||
-v, --vcd=FILE, Write vcd trace to FILE (or '-' for stdout)\n\
|
||||
-x, --dump-start=CYCLE Start VCD tracing at CYCLE\n\
|
||||
+dump-start\n\
|
||||
", stdout);
|
||||
fputs("\
|
||||
\n\
|
||||
VERILOG PLUSARGS (accepted by the Verilog itself):\n" , stdout);
|
||||
const char ** vpa = &verilog_plusargs[0];
|
||||
while (*vpa) {
|
||||
fprintf(stdout, " +%s=...\n", *vpa);
|
||||
vpa ++;
|
||||
}
|
||||
fputs("\n" HTIF_USAGE_OPTIONS, stdout);
|
||||
printf("\n"
|
||||
"EXAMPLES\n"
|
||||
" - run a bare metal test:\n"
|
||||
" %s $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add\n"
|
||||
" - run a bare metal test showing cycle-by-cycle information:\n"
|
||||
" %s +verbose $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add 2>&1 | spike-dasm\n"
|
||||
#if VM_TRACE
|
||||
" - run a bare metal test to generate a VCD waveform:\n"
|
||||
" %s -v rv64ui-p-add.vcd $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add\n"
|
||||
#endif
|
||||
" - run an ELF (you wrote, called 'hello') using the proxy kernel:\n"
|
||||
" %s pk hello\n",
|
||||
program_name, program_name, program_name, program_name);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
@ -73,8 +108,9 @@ int main(int argc, char** argv)
|
||||
FILE * vcdfile = NULL;
|
||||
uint64_t start = 0;
|
||||
#endif
|
||||
char ** htif_argv = NULL;
|
||||
int verilog_plusargs_legal = 1;
|
||||
|
||||
std::vector<std::string> to_dtm;
|
||||
while (1) {
|
||||
static struct option long_options[] = {
|
||||
{"cycle-count", no_argument, 0, 'c' },
|
||||
@ -86,7 +122,7 @@ int main(int argc, char** argv)
|
||||
{"vcd", required_argument, 0, 'v' },
|
||||
{"dump-start", required_argument, 0, 'x' },
|
||||
#endif
|
||||
{0, 0, 0, 0}
|
||||
HTIF_LONG_OPTIONS
|
||||
};
|
||||
int option_index = 0;
|
||||
#if VM_TRACE
|
||||
@ -95,8 +131,9 @@ int main(int argc, char** argv)
|
||||
int c = getopt_long(argc, argv, "-chm:s:V", long_options, &option_index);
|
||||
#endif
|
||||
if (c == -1) break;
|
||||
retry:
|
||||
switch (c) {
|
||||
// Process "normal" options with '--' long options or '-' short options
|
||||
// Process long and short EMULATOR options
|
||||
case '?': usage(argv[0]); return 1;
|
||||
case 'c': print_cycles = true; break;
|
||||
case 'h': usage(argv[0]); return 0;
|
||||
@ -114,39 +151,86 @@ int main(int argc, char** argv)
|
||||
}
|
||||
case 'x': start = atoll(optarg); break;
|
||||
#endif
|
||||
// Processing of legacy '+' options and recognition of when
|
||||
// we've hit the binary. The binary is expected to be a
|
||||
// non-option and not start with '-' or '+'.
|
||||
// Process legacy '+' EMULATOR arguments by replacing them with
|
||||
// their getopt equivalents
|
||||
case 1: {
|
||||
std::string arg = optarg;
|
||||
if (arg == "+verbose")
|
||||
verbose = true;
|
||||
else if (arg.substr(0, 12) == "+max-cycles=")
|
||||
max_cycles = atoll(optarg+12);
|
||||
#if VM_TRACE
|
||||
else if (arg.substr(0, 12) == "+dump-start=")
|
||||
start = atoll(optarg+12);
|
||||
#endif
|
||||
else if (arg.substr(0, 12) == "+cycle-count")
|
||||
print_cycles = true;
|
||||
else {
|
||||
to_dtm.push_back(optarg);
|
||||
if (arg.substr(0, 1) != "+") {
|
||||
optind--;
|
||||
goto done_processing;
|
||||
}
|
||||
break;
|
||||
if (arg == "+verbose")
|
||||
c = 'V';
|
||||
else if (arg.substr(0, 12) == "+max-cycles=") {
|
||||
c = 'm';
|
||||
optarg = optarg+12;
|
||||
}
|
||||
#if VM_TRACE
|
||||
else if (arg.substr(0, 12) == "+dump-start=") {
|
||||
c = 'x';
|
||||
optarg = optarg+12;
|
||||
}
|
||||
#endif
|
||||
else if (arg.substr(0, 12) == "+cycle-count")
|
||||
c = 'c';
|
||||
// If we don't find a legacy '+' EMULATOR argument, it still could be
|
||||
// a VERILOG_PLUSARG and not an error.
|
||||
else if (verilog_plusargs_legal) {
|
||||
const char ** plusarg = &verilog_plusargs[0];
|
||||
int legal_verilog_plusarg = 0;
|
||||
while (*plusarg && (legal_verilog_plusarg == 0)){
|
||||
if (arg.substr(1, strlen(*plusarg)) == *plusarg) {
|
||||
legal_verilog_plusarg = 1;
|
||||
}
|
||||
plusarg ++;
|
||||
}
|
||||
if (!legal_verilog_plusarg) {
|
||||
verilog_plusargs_legal = 0;
|
||||
} else {
|
||||
c = 'P';
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
// If we STILL don't find a legacy '+' argument, it still could be
|
||||
// an HTIF (HOST) argument and not an error. If this is the case, then
|
||||
// we're done processing EMULATOR and VERILOG arguments.
|
||||
else {
|
||||
static struct option htif_long_options [] = { HTIF_LONG_OPTIONS };
|
||||
struct option * htif_option = &htif_long_options[0];
|
||||
while (htif_option->name) {
|
||||
if (arg.substr(1, strlen(htif_option->name)) == htif_option->name) {
|
||||
optind--;
|
||||
goto done_processing;
|
||||
}
|
||||
htif_option++;
|
||||
}
|
||||
std::cerr << argv[0] << ": invalid HTIF legacy plus-arg \"" << arg << "\"\n";
|
||||
c = '?';
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
case 'P': break; // Nothing to do here, Verilog PlusArg
|
||||
// Realize that we've hit HTIF (HOST) arguments or error out
|
||||
default:
|
||||
if (c >= HTIF_LONG_OPTIONS_OPTIND) {
|
||||
optind--;
|
||||
goto done_processing;
|
||||
}
|
||||
c = '?';
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
done_processing:
|
||||
if (optind < argc)
|
||||
while (optind < argc)
|
||||
to_dtm.push_back(argv[optind++]);
|
||||
if (!to_dtm.size()) {
|
||||
if (optind == argc) {
|
||||
std::cerr << "No binary specified for emulator\n";
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
int htif_argc = 1 + argc - optind;
|
||||
htif_argv = (char **) malloc((htif_argc) * sizeof (char *));
|
||||
htif_argv[0] = argv[0];
|
||||
for (int i = 1; optind < argc;) htif_argv[i++] = argv[optind++];
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "using random seed %u\n", random_seed);
|
||||
@ -168,26 +252,39 @@ done_processing:
|
||||
}
|
||||
#endif
|
||||
|
||||
dtm = new dtm_t(to_dtm);
|
||||
jtag = new remote_bitbang_t(0);
|
||||
dtm = new dtm_t(htif_argc, htif_argv);
|
||||
|
||||
signal(SIGTERM, handle_sigterm);
|
||||
|
||||
bool dump;
|
||||
// reset for several cycles to handle pipelined reset
|
||||
for (int i = 0; i < 10; i++) {
|
||||
tile->reset = 1;
|
||||
tile->clock = 0;
|
||||
tile->eval();
|
||||
#if VM_TRACE
|
||||
dump = tfp && trace_count >= start;
|
||||
if (dump)
|
||||
tfp->dump(static_cast<vluint64_t>(trace_count * 2));
|
||||
#endif
|
||||
tile->clock = 1;
|
||||
tile->eval();
|
||||
tile->reset = 0;
|
||||
#if VM_TRACE
|
||||
if (dump)
|
||||
tfp->dump(static_cast<vluint64_t>(trace_count * 2 + 1));
|
||||
#endif
|
||||
trace_count ++;
|
||||
}
|
||||
tile->reset = 0;
|
||||
done_reset = true;
|
||||
|
||||
while (!dtm->done() && !tile->io_success && trace_count < max_cycles) {
|
||||
while (!dtm->done() && !jtag->done() &&
|
||||
!tile->io_success && trace_count < max_cycles) {
|
||||
tile->clock = 0;
|
||||
tile->eval();
|
||||
#if VM_TRACE
|
||||
bool dump = tfp && trace_count >= start;
|
||||
dump = tfp && trace_count >= start;
|
||||
if (dump)
|
||||
tfp->dump(static_cast<vluint64_t>(trace_count * 2));
|
||||
#endif
|
||||
@ -213,6 +310,11 @@ done_processing:
|
||||
fprintf(stderr, "*** FAILED *** (code = %d, seed %d) after %ld cycles\n", dtm->exit_code(), random_seed, trace_count);
|
||||
ret = dtm->exit_code();
|
||||
}
|
||||
else if (jtag->exit_code())
|
||||
{
|
||||
fprintf(stderr, "*** FAILED *** (code = %d, seed %d) after %ld cycles\n", jtag->exit_code(), random_seed, trace_count);
|
||||
ret = jtag->exit_code();
|
||||
}
|
||||
else if (trace_count == max_cycles)
|
||||
{
|
||||
fprintf(stderr, "*** FAILED *** (timeout, seed %d) after %ld cycles\n", random_seed, trace_count);
|
||||
@ -224,6 +326,8 @@ done_processing:
|
||||
}
|
||||
|
||||
if (dtm) delete dtm;
|
||||
if (jtag) delete jtag;
|
||||
if (tile) delete tile;
|
||||
if (htif_argv) free(htif_argv);
|
||||
return ret;
|
||||
}
|
||||
|
202
csrc/remote_bitbang.cc
Normal file
202
csrc/remote_bitbang.cc
Normal file
@ -0,0 +1,202 @@
|
||||
// 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 <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "remote_bitbang.h"
|
||||
|
||||
/////////// remote_bitbang_t
|
||||
|
||||
remote_bitbang_t::remote_bitbang_t(uint16_t port) :
|
||||
socket_fd(0),
|
||||
client_fd(0),
|
||||
recv_start(0),
|
||||
recv_end(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;
|
||||
|
||||
printf ("This emulator compiled with JTAG Remote Bitbang client. To enable, use +jtag_rbb_enable=1.\n");
|
||||
printf("Listening on port %d\n",
|
||||
ntohs(addr.sin_port));
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void remote_bitbang_t::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 remote_bitbang_t::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;
|
||||
execute_command();
|
||||
} else {
|
||||
this->accept();
|
||||
}
|
||||
|
||||
* jtag_tck = tck;
|
||||
* jtag_tms = tms;
|
||||
* jtag_tdi = tdi;
|
||||
* jtag_trstn = trstn;
|
||||
|
||||
}
|
||||
|
||||
void remote_bitbang_t::reset(){
|
||||
//trstn = 0;
|
||||
}
|
||||
|
||||
void remote_bitbang_t::set_pins(char _tck, char _tms, char _tdi){
|
||||
tck = _tck;
|
||||
tms = _tms;
|
||||
tdi = _tdi;
|
||||
}
|
||||
|
||||
void remote_bitbang_t::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.
|
||||
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.\n");
|
||||
again = 1;
|
||||
} else {
|
||||
again = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Received a command %c\n", command);
|
||||
|
||||
int dosend = 0;
|
||||
|
||||
char tosend = '?';
|
||||
|
||||
switch (command) {
|
||||
case 'B': /* fprintf(stderr, "*BLINK*\n"); */ break;
|
||||
case 'b': /* fprintf(stderr, "_______\n"); */ break;
|
||||
case 'r': reset(); break; // This is wrong. 'r' has other bits that indicated TRST and SRST.
|
||||
case '0': set_pins(0, 0, 0); break;
|
||||
case '1': set_pins(0, 0, 1); break;
|
||||
case '2': set_pins(0, 1, 0); break;
|
||||
case '3': set_pins(0, 1, 1); break;
|
||||
case '4': set_pins(1, 0, 0); break;
|
||||
case '5': set_pins(1, 0, 1); break;
|
||||
case '6': set_pins(1, 1, 0); break;
|
||||
case '7': set_pins(1, 1, 1); break;
|
||||
case 'R': dosend = 1; tosend = tdo ? '1' : '0'; break;
|
||||
case 'Q': 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) {
|
||||
// The remote disconnected.
|
||||
fprintf(stderr, "Remote end disconnected\n");
|
||||
close(client_fd);
|
||||
client_fd = 0;
|
||||
}
|
||||
}
|
59
csrc/remote_bitbang.h
Normal file
59
csrc/remote_bitbang.h
Normal file
@ -0,0 +1,59 @@
|
||||
// See LICENSE.Berkeley for license details.
|
||||
|
||||
#ifndef REMOTE_BITBANG_H
|
||||
#define REMOTE_BITBANG_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
class remote_bitbang_t
|
||||
{
|
||||
public:
|
||||
// Create a new server, listening for connections from localhost on the given
|
||||
// port.
|
||||
remote_bitbang_t(uint16_t port);
|
||||
|
||||
// Do a bit of work.
|
||||
void tick(unsigned char * jtag_tck,
|
||||
unsigned char * jtag_tms,
|
||||
unsigned char * jtag_tdi,
|
||||
unsigned char * jtag_trstn,
|
||||
unsigned char jtag_tdo);
|
||||
|
||||
unsigned char done() {return quit;}
|
||||
|
||||
int exit_code() {return err;}
|
||||
|
||||
private:
|
||||
|
||||
int 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[buf_size];
|
||||
ssize_t recv_start, recv_end;
|
||||
|
||||
// Check for a client connecting, and accept if there is one.
|
||||
void accept();
|
||||
// Execute any commands the client has for us.
|
||||
// But we only execute 1 because we need time for the
|
||||
// simulation to run.
|
||||
void execute_command();
|
||||
|
||||
// Reset. Currently does nothing.
|
||||
void reset();
|
||||
|
||||
void set_pins(char _tck, char _tms, char _tdi);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -8,7 +8,7 @@ output_dir = $(sim_dir)/output
|
||||
|
||||
include $(base_dir)/Makefrag
|
||||
|
||||
CXXSRCS := emulator SimDTM
|
||||
CXXSRCS := emulator SimDTM SimJTAG remote_bitbang
|
||||
CXXFLAGS := $(CXXFLAGS) -std=c++11 -I$(RISCV)/include -I$(base_dir)/csrc
|
||||
LDFLAGS := $(LDFLAGS) -L$(RISCV)/lib -Wl,-rpath,$(RISCV)/lib -L$(abspath $(sim_dir)) -lfesvr -lpthread
|
||||
|
||||
|
@ -62,8 +62,9 @@ CONFIGS=AMBAUnitTestConfig TLSimpleUnitTestConfig TLWidthUnitTestConfig
|
||||
endif
|
||||
|
||||
ifeq ($(SUITE), JtagDtmSuite)
|
||||
CONFIGS_32=WithJtagDTM_DefaultRV32Config
|
||||
CONFIGS_64=WithJtagDTM_DefaultConfig
|
||||
PROJECT=freechips.rocketchip.system
|
||||
CONFIGS_32=WithJtagDTMSystem_DefaultRV32Config
|
||||
CONFIGS_64=WithJtagDTMSystem_DefaultConfig
|
||||
CONFIGS += $(CONFIGS_32)
|
||||
CONFIGS += $(CONFIGS_64)
|
||||
endif
|
||||
@ -208,44 +209,87 @@ stamps/%/emulator-torture-$(TORTURE_CONFIG).stamp: stamps/%/emulator-debug.stamp
|
||||
|
||||
# Targets for JTAG DTM full-chain simulation
|
||||
|
||||
OPENOCD_DIR ?= $(RISCV)
|
||||
|
||||
# If this is defined empty, then all tests would run.
|
||||
JTAG_DTM_TEST ?= MemTest64
|
||||
GDBSERVER = $(abspath $(TOP))/riscv-tools/riscv-tests/debug/gdbserver.py \
|
||||
--print-failures \
|
||||
--print-log-names
|
||||
|
||||
ifdef DEBUG
|
||||
JTAG_STAMP_SUFFIX=-debug
|
||||
JTAG_DEBUG_SUFFIX=-debug
|
||||
JTAG_VCDPLUS_32= +vcdplusfile=regression32.vcd
|
||||
JTAG_VCDPLUS_64= +vcdplusfile=regression64.vcd
|
||||
VSIM_JTAG_VCDPLUS_32= +vcdplusfile=regression32.vcd
|
||||
VSIM_JTAG_VCDPLUS_64= +vcdplusfile=regression64.vcd
|
||||
EMULATOR_JTAG_VCDPLUS_32= -v regression32.vcd
|
||||
EMULATOR_JTAG_VCDPLUS_64= -v regression64.vcd
|
||||
OPENOCD_DEBUG= -d
|
||||
else
|
||||
JTAG_STAMP_SUFFIX=-ndebug
|
||||
endif
|
||||
|
||||
stamps/%/jtag-dtm-32-$(JTAG_DTM_TEST).stamp: stamps/%/vsim$(JTAG_STAMP_SUFFIX).stamp
|
||||
export RISCV=$(RISCV) && $(abspath $(TOP))/riscv-tools/riscv-tests/debug/gdbserver.py \
|
||||
--sim_cmd "$(abspath $(TOP))/vsim/simv-$(PROJECT)-$*$(JTAG_DEBUG_SUFFIX) +verbose $(JTAG_VCDPLUS_32)" \
|
||||
--server_cmd="$(OPENOCD_DIR)/bin/openocd $(OPENOCD_DEBUG) \
|
||||
--s $(OPENOCD_DIR)/share/openocd/scripts" \
|
||||
--freedom-e300-sim \
|
||||
ifdef SEED
|
||||
SEED_ARG = --seed $(SEED)
|
||||
endif
|
||||
|
||||
JTAG_DTM_SIM_ARGS = +verbose +jtag_rbb_enable=1 $(SEED_ARG)
|
||||
|
||||
stamps/riscv-tests.stamp:
|
||||
git -C $(abspath $(TOP)) submodule update --init riscv-tools
|
||||
git -C $(abspath $(TOP))/riscv-tools submodule update --init --recursive riscv-tests
|
||||
date > $@
|
||||
|
||||
stamps/%/vsim-jtag-dtm-32-$(JTAG_DTM_TEST).stamp: stamps/%/vsim$(JTAG_STAMP_SUFFIX).stamp stamps/riscv-tests.stamp
|
||||
RISCV=$(RISCV) $(GDBSERVER) \
|
||||
--sim_cmd="$(abspath $(TOP))/vsim/simv-$(PROJECT)-$*$(JTAG_DEBUG_SUFFIX) $(JTAG_DTM_SIM_ARGS) $(VSIM_JTAG_VCDPLUS_32)" \
|
||||
--server_cmd="$(RISCV)/bin/openocd $(OPENOCD_DEBUG) \
|
||||
-s $(RISCV)/share/openocd/scripts" \
|
||||
--32 \
|
||||
$(abspath $(TOP))/scripts/RocketSim32.py \
|
||||
$(JTAG_DTM_TEST)
|
||||
date > $@
|
||||
|
||||
stamps/%/jtag-dtm-64-$(JTAG_DTM_TEST).stamp: stamps/%/vsim$(JTAG_STAMP_SUFFIX).stamp
|
||||
export RISCV=$(RISCV) && $(abspath $(TOP))/riscv-tools/riscv-tests/debug/gdbserver.py \
|
||||
--sim_cmd "$(abspath $(TOP))/vsim/simv-$(PROJECT)-$*$(JTAG_DEBUG_SUFFIX) +verbose $(JTAG_VCDPLUS_64)" \
|
||||
stamps/%/vsim-jtag-dtm-64-$(JTAG_DTM_TEST).stamp: stamps/%/vsim$(JTAG_STAMP_SUFFIX).stamp stamps/riscv-tests.stamp
|
||||
RISCV=$(RISCV) $(GDBSERVER) \
|
||||
--sim_cmd="$(abspath $(TOP))/vsim/simv-$(PROJECT)-$*$(JTAG_DEBUG_SUFFIX) $(JTAG_DTM_SIM_ARGS) $(VSIM_JTAG_VCDPLUS_64)" \
|
||||
--server_cmd="$(OPENOCD_INSTALL)_$(OPENOCD_VERSION)/bin/openocd $(OPENOCD_DEBUG) \
|
||||
--s $(OPENOCD_INSTALL)_$(OPENOCD_VERSION)/share/openocd/scripts" \
|
||||
--freedom-u500-sim \
|
||||
-s $(OPENOCD_INSTALL)_$(OPENOCD_VERSION)/share/openocd/scripts" \
|
||||
--64 \
|
||||
$(abspath $(TOP))/scripts/RocketSim64.py \
|
||||
$(JTAG_DTM_TEST)
|
||||
date > $@
|
||||
|
||||
JTAG_DTM_32_TEST_STAMPS=$(foreach config,$(CONFIGS_32),stamps/$(config)/jtag-dtm-32-$(JTAG_DTM_TEST).stamp)
|
||||
JTAG_DTM_64_TEST_STAMPS=$(foreach config,$(CONFIGS_64),stamps/$(config)/jtag-dtm-64-$(JTAG_DTM_TEST).stamp)
|
||||
stamps/%/emulator-jtag-dtm-32-$(JTAG_DTM_TEST).stamp: stamps/%/emulator$(JTAG_STAMP_SUFFIX).stamp stamps/riscv-tests.stamp
|
||||
RISCV=$(RISCV) $(GDBSERVER) \
|
||||
--sim_cmd="$(abspath $(TOP))/emulator/emulator-$(PROJECT)-$*$(JTAG_DEBUG_SUFFIX) $(JTAG_DTM_SIM_ARGS) $(EMULATOR_JTAG_VCDPLUS_32) dummybin" \
|
||||
--server_cmd="$(RISCV)/bin/openocd $(OPENOCD_DEBUG) \
|
||||
-s $(RISCV)/share/openocd/scripts" \
|
||||
--32 \
|
||||
$(abspath $(TOP))/scripts/RocketSim32.py \
|
||||
$(JTAG_DTM_TEST)
|
||||
date > $@
|
||||
|
||||
jtag-dtm-tests-32 : $(JTAG_DTM_32_TEST_STAMPS)
|
||||
jtag-dtm-tests-64 : $(JTAG_DTM_64_TEST_STAMPS)
|
||||
stamps/%/emulator-jtag-dtm-64-$(JTAG_DTM_TEST).stamp: stamps/%/emulator$(JTAG_STAMP_SUFFIX).stamp stamps/riscv-tests.stamp
|
||||
RISCV=$(RISCV) $(GDBSERVER) \
|
||||
--sim_cmd="$(abspath $(TOP))/emulator/emulator-$(PROJECT)-$*$(JTAG_DEBUG_SUFFIX) $(JTAG_DTM_SIM_ARGS) $(EMULATOR_JTAG_VCDPLUS_64) dummybin" \
|
||||
--server_cmd="$(RISCV)/bin/openocd $(OPENOCD_DEBUG) \
|
||||
-s $(RISCV)/share/openocd/scripts" \
|
||||
--64 \
|
||||
$(abspath $(TOP))/scripts/RocketSim64.py \
|
||||
$(JTAG_DTM_TEST)
|
||||
date > $@
|
||||
|
||||
VSIM_JTAG_DTM_32_TEST_STAMPS=$(foreach config,$(CONFIGS_32),stamps/$(config)/vsim-jtag-dtm-32-$(JTAG_DTM_TEST).stamp)
|
||||
VSIM_JTAG_DTM_64_TEST_STAMPS=$(foreach config,$(CONFIGS_64),stamps/$(config)/vsim-jtag-dtm-64-$(JTAG_DTM_TEST).stamp)
|
||||
|
||||
EMULATOR_JTAG_DTM_32_TEST_STAMPS=$(foreach config,$(CONFIGS_32),stamps/$(config)/emulator-jtag-dtm-32-$(JTAG_DTM_TEST).stamp)
|
||||
EMULATOR_JTAG_DTM_64_TEST_STAMPS=$(foreach config,$(CONFIGS_64),stamps/$(config)/emulator-jtag-dtm-64-$(JTAG_DTM_TEST).stamp)
|
||||
|
||||
vsim-jtag-dtm-tests-32 : $(VSIM_JTAG_DTM_32_TEST_STAMPS)
|
||||
vsim-jtag-dtm-tests-64 : $(VSIM_JTAG_DTM_64_TEST_STAMPS)
|
||||
|
||||
emulator-jtag-dtm-tests-32 : $(EMULATOR_JTAG_DTM_32_TEST_STAMPS)
|
||||
emulator-jtag-dtm-tests-64 : $(EMULATOR_JTAG_DTM_64_TEST_STAMPS)
|
||||
|
||||
# Targets for JTAG DTM full-chain simulation
|
||||
jtag-dtm-regression: jtag-dtm-tests-32 jtag-dtm-tests-64
|
||||
vsim-jtag-dtm-regression: vsim-jtag-dtm-tests-32 vsim-jtag-dtm-tests-64
|
||||
emulator-jtag-dtm-regression: emulator-jtag-dtm-tests-32 emulator-jtag-dtm-tests-64
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 09a1ffe5afb57673e0641a86cdb94347056c5c06
|
||||
Subproject commit 98682995dc4a1ab8777ff45ba673cf2658e54ae2
|
19
scripts/RocketSim.cfg
Normal file
19
scripts/RocketSim.cfg
Normal file
@ -0,0 +1,19 @@
|
||||
adapter_khz 10000
|
||||
|
||||
interface remote_bitbang
|
||||
remote_bitbang_host localhost
|
||||
#$::env(REMOTE_BITBANG_HOST)
|
||||
remote_bitbang_port $::env(JTAG_VPI_PORT)
|
||||
|
||||
set _CHIPNAME riscv
|
||||
jtag newtap $_CHIPNAME cpu -irlen 5
|
||||
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
target create $_TARGETNAME riscv -chain-position $_TARGETNAME -rtos riscv
|
||||
|
||||
riscv set_reset_timeout_sec 120
|
||||
riscv set_command_timeout_sec 120
|
||||
|
||||
init
|
||||
halt
|
||||
echo "Ready for Remote Connections"
|
21
scripts/RocketSim.py
Normal file
21
scripts/RocketSim.py
Normal file
@ -0,0 +1,21 @@
|
||||
import targets
|
||||
import testlib
|
||||
|
||||
class RocketSimHart(targets.Hart):
|
||||
# This isn't generically true, but it's true enough for the Default*Configs in this code for now.
|
||||
# to get these tests to pass.
|
||||
ram = 0x80000000
|
||||
ram_size = 0x4000
|
||||
instruction_hardware_breakpoint_count = 2
|
||||
pass
|
||||
|
||||
class RocketSim(targets.Target):
|
||||
harts = [RocketSimHart()]
|
||||
timeout_sec = 6000
|
||||
server_timeout_sec = 60*60
|
||||
openocd_config_path = "RocketSim.cfg"
|
||||
|
||||
def create(self):
|
||||
print "STARTING A SIMULATION"
|
||||
print self.sim_cmd
|
||||
return testlib.VcsSim(sim_cmd=self.sim_cmd, debug=False)
|
22
scripts/RocketSim32.py
Normal file
22
scripts/RocketSim32.py
Normal file
@ -0,0 +1,22 @@
|
||||
import targets
|
||||
import testlib
|
||||
|
||||
class RocketSimHart(targets.Hart):
|
||||
xlen = 32
|
||||
# This isn't generically true, but it's true enough for the Default*Configs in this code for now.
|
||||
# to get these tests to pass.
|
||||
ram = 0x80000000
|
||||
ram_size = 0x4000
|
||||
instruction_hardware_breakpoint_count = 2
|
||||
pass
|
||||
|
||||
class RocketSim(targets.Target):
|
||||
harts = [RocketSimHart()]
|
||||
timeout_sec = 6000
|
||||
server_timeout_sec = 60*60
|
||||
openocd_config_path = "RocketSim.cfg"
|
||||
|
||||
def create(self):
|
||||
print "STARTING A SIMULATION"
|
||||
print self.sim_cmd
|
||||
return testlib.VcsSim(sim_cmd=self.sim_cmd, debug=False)
|
22
scripts/RocketSim64.py
Normal file
22
scripts/RocketSim64.py
Normal file
@ -0,0 +1,22 @@
|
||||
import targets
|
||||
import testlib
|
||||
|
||||
class RocketSimHart(targets.Hart):
|
||||
# This isn't generically true, but it's true enough for the Default*Configs in this code for now.
|
||||
# to get these tests to pass.
|
||||
xlen = 64
|
||||
ram = 0x80000000
|
||||
ram_size = 0x4000
|
||||
instruction_hardware_breakpoint_count = 2
|
||||
pass
|
||||
|
||||
class RocketSim(targets.Target):
|
||||
harts = [RocketSimHart()]
|
||||
timeout_sec = 6000
|
||||
server_timeout_sec = 60*60
|
||||
openocd_config_path = "RocketSim.cfg"
|
||||
|
||||
def create(self):
|
||||
print "STARTING A SIMULATION"
|
||||
print self.sim_cmd
|
||||
return testlib.VcsSim(sim_cmd=self.sim_cmd, debug=False)
|
@ -49,7 +49,8 @@ trait HasPeripheryDebugBundle {
|
||||
val dtm = Module(new SimDTM).connect(c, r, d, out)
|
||||
}
|
||||
debug.systemjtag.foreach { sj =>
|
||||
val jtag = Module(new JTAGVPI(tckHalfPeriod = tckHalfPeriod, cmdDelay = cmdDelay)).connect(sj.jtag, sj.reset, r, out)
|
||||
//val jtag = Module(new JTAGVPI(tckHalfPeriod = tckHalfPeriod, cmdDelay = cmdDelay)).connect(sj.jtag, sj.reset, r, out)
|
||||
val jtag = Module(new SimJTAG(tickDelay=3)).connect(sj.jtag, sj.reset, c, r, out)
|
||||
sj.mfr_id := p(JtagDTMKey).idcodeManufId.U(11.W)
|
||||
}
|
||||
debug.psd.foreach { _ <> psd }
|
||||
@ -112,6 +113,36 @@ class SimDTM(implicit p: Parameters) extends BlackBox {
|
||||
}
|
||||
}
|
||||
|
||||
class SimJTAG(tickDelay: Int = 50) extends BlackBox(Map("TICK_DELAY" -> IntParam(tickDelay))) {
|
||||
val io = new Bundle {
|
||||
val clock = Clock(INPUT)
|
||||
val reset = Bool(INPUT)
|
||||
val jtag = new JTAGIO(hasTRSTn = true)
|
||||
val enable = Bool(INPUT)
|
||||
val init_done = Bool(INPUT)
|
||||
val exit = UInt(OUTPUT, 32)
|
||||
}
|
||||
|
||||
def connect(dutio: JTAGIO, jtag_reset: Bool, tbclock: Clock, tbreset: Bool, tbsuccess: Bool) = {
|
||||
dutio <> io.jtag
|
||||
jtag_reset := tbreset
|
||||
|
||||
io.clock := tbclock
|
||||
io.reset := tbreset
|
||||
|
||||
io.enable := PlusArg("jtag_rbb_enable", 0, "Enable SimJTAG for JTAG Connections. Simulation will pause until connection is made.")
|
||||
io.init_done := ~tbreset
|
||||
|
||||
// Success is determined by the gdbserver
|
||||
// which is controlling this simulation.
|
||||
tbsuccess := io.exit === UInt(1)
|
||||
when (io.exit >= UInt(2)) {
|
||||
printf("*** FAILED *** (exit code = %d)\n", io.exit >> UInt(1))
|
||||
stop(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class JTAGVPI(tckHalfPeriod: Int = 2, cmdDelay: Int = 2)(implicit val p: Parameters)
|
||||
extends BlackBox ( Map ("TCK_HALF_PERIOD" -> IntParam(tckHalfPeriod),
|
||||
"CMD_DELAY" -> IntParam(cmdDelay))) {
|
||||
|
@ -9,6 +9,8 @@ import freechips.rocketchip.coreplex._
|
||||
import freechips.rocketchip.devices.debug.{IncludeJtagDTM, JtagDTMKey}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
|
||||
class WithJtagDTMSystem extends freechips.rocketchip.coreplex.WithJtagDTM
|
||||
|
||||
class BaseConfig extends Config(new BaseCoreplexConfig().alter((site,here,up) => {
|
||||
// DTS descriptive parameters
|
||||
case DTSModel => "freechips,rocketchip-unknown"
|
||||
|
@ -16,13 +16,15 @@ sim_vsrcs = \
|
||||
$(generated_dir)/$(long_name).behav_srams.v \
|
||||
$(base_dir)/vsrc/$(TB).v \
|
||||
$(base_dir)/vsrc/SimDTM.v \
|
||||
$(base_dir)/vsrc/SimJTAG.v \
|
||||
$(bb_vsrcs)
|
||||
|
||||
# C sources
|
||||
|
||||
sim_csrcs = \
|
||||
$(base_dir)/csrc/SimDTM.cc \
|
||||
$(base_dir)/csrc/jtag_vpi.c
|
||||
$(base_dir)/csrc/SimJTAG.cc \
|
||||
$(base_dir)/csrc/remote_bitbang.cc \
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Build Verilog
|
||||
|
@ -45,21 +45,28 @@ module AsyncResetReg (
|
||||
input clk,
|
||||
input rst);
|
||||
|
||||
`ifdef RANDOMIZE
|
||||
integer initvar;
|
||||
reg [31:0] _RAND;
|
||||
initial begin
|
||||
`ifndef verilator
|
||||
#0.002 begin end
|
||||
`endif
|
||||
`ifdef RANDOMIZE_REG_INIT
|
||||
`ifdef RANDOMIZE
|
||||
integer initvar;
|
||||
reg [31:0] _RAND;
|
||||
_RAND = {1{$random}};
|
||||
if (~rst) begin
|
||||
`endif
|
||||
if (rst) begin
|
||||
`ifdef verilator
|
||||
q = 1'b0;
|
||||
`endif
|
||||
end
|
||||
`ifdef RANDOMIZE
|
||||
`ifndef verilator
|
||||
`endif
|
||||
`ifdef RANDOMIZE_REG_INIT
|
||||
else begin
|
||||
#0.002 begin end
|
||||
q = _RAND[0];
|
||||
end
|
||||
`endif
|
||||
end
|
||||
`endif
|
||||
`endif // `ifdef RANDOMIZE
|
||||
end
|
||||
|
||||
always @(posedge clk or posedge rst) begin
|
||||
|
||||
|
79
vsrc/SimJTAG.v
Normal file
79
vsrc/SimJTAG.v
Normal file
@ -0,0 +1,79 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
import "DPI-C" function int jtag_tick
|
||||
(
|
||||
output bit jtag_TCK,
|
||||
output bit jtag_TMS,
|
||||
output bit jtag_TDI,
|
||||
output bit jtag_TRSTn,
|
||||
|
||||
input bit jtag_TDO
|
||||
);
|
||||
|
||||
module SimJTAG #(
|
||||
parameter TICK_DELAY = 50
|
||||
)(
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
end else begin
|
||||
if (enable && init_done) begin
|
||||
tickCounterReg <= tickCounterNxt;
|
||||
if (tickCounterReg == 0) begin
|
||||
__exit = jtag_tick(
|
||||
__jtag_TCK,
|
||||
__jtag_TMS,
|
||||
__jtag_TDI,
|
||||
__jtag_TRSTn,
|
||||
__jtag_TDO);
|
||||
end
|
||||
end // if (enable && init_done)
|
||||
end // else: !if(reset || r_reset)
|
||||
end // always @ (posedge clock)
|
||||
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user