From: Luke Kenneth Casson Leighton Date: Thu, 8 Apr 2021 20:55:59 +0000 (+0100) Subject: add ls180 cxxsim test X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=71a81e1dd997444a92c6069dece7aabd61a2e2a8;p=soc-cxxrtl-sim.git add ls180 cxxsim test --- diff --git a/ls180_test/.gitignore b/ls180_test/.gitignore new file mode 100644 index 0000000..6e4bc45 --- /dev/null +++ b/ls180_test/.gitignore @@ -0,0 +1,5 @@ +add.cpp +add.v +tb +*.o +.*.sw? diff --git a/ls180_test/Makefile b/ls180_test/Makefile new file mode 100644 index 0000000..b8eed8e --- /dev/null +++ b/ls180_test/Makefile @@ -0,0 +1,30 @@ + +YOSYS = yosys +YOSYS_INCLUDE = $(shell yosys-config --datdir)/include + +all: tb + ./tb + +tb: main.cpp ls180.cpp + clang++ -g -O3 -std=c++14 -I $(YOSYS_INCLUDE) $< -o $@ + +#../../soc/src/soc/litex/florent/libresoc.v \ +#../../soc/src/soc/litex/florent/ls180.v +VERILOG_SOURCES := \ + ./SPBlock_512W64B8W.v \ + #./libresoc.v \ + #./ls180.v + +ls180.cpp: $(VERILOG_SOURCES) + # create dummy memory files + yes 0 | head -128 > mem.init + yes 0 | head -32 > mem_1.init + echo $< + $(YOSYS) -p "read_verilog $?; write_cxxrtl $@" + +# build verilog from nmigen +ls180.v: ls180.py + python3 ls180.py + +clean: + \rm -f ls180.cpp tb ls180.v diff --git a/ls180_test/README.txt b/ls180_test/README.txt new file mode 100644 index 0000000..4af047c --- /dev/null +++ b/ls180_test/README.txt @@ -0,0 +1,3 @@ +This experiment uses the litex verilog code for LibreSOC and allows +doing a JTAG cxxrtl openocd "jtagremote" interface + diff --git a/ls180_test/SPBlock_512W64B8W.v b/ls180_test/SPBlock_512W64B8W.v new file mode 100644 index 0000000..2188fd4 --- /dev/null +++ b/ls180_test/SPBlock_512W64B8W.v @@ -0,0 +1,35 @@ +// SPBlock_512W64B8W simulation mode +module SPBlock_512W64B8W( + input clk, + input [8:0] a, + input [63:0] d, + output [63:0] q, + // Width of WE determines the write granularity + input [7:0] we +); + +genvar i; + +reg [63:0] ram [511:0]; +wire[7:0] d_split [7:0]; +reg [8:0] a_hold; + +always @(posedge clk) begin + a_hold <= a; +end + +assign q = ram[a_hold]; + +generate + for (i = 0; i < 8; i = i + 1) begin + assign d_split[i] = d[((i + 1)*8 - 1):i*8]; + + always @(posedge clk) begin + if (we[i]) begin + ram[a][((i + 1)*8 - 1):i*8] = d_split[i]; + end + end + end +endgenerate + +endmodule diff --git a/ls180_test/cxxscript.y b/ls180_test/cxxscript.y new file mode 100644 index 0000000..d185c69 --- /dev/null +++ b/ls180_test/cxxscript.y @@ -0,0 +1,5 @@ +read_verilog ls180.v libresoc.v SPBlock_512W64B8W.v +hierarchy -check -top ls180 +proc +memory +write_cxxrtl ls180.cpp diff --git a/ls180_test/idcode.svf b/ls180_test/idcode.svf new file mode 100644 index 0000000..994e9c8 --- /dev/null +++ b/ls180_test/idcode.svf @@ -0,0 +1,4 @@ +!Loading device with 'idcode' instruction. +SIR 4 TDI (1); +SDR 32 TDI (00000000) TDO (000018FF) ; + diff --git a/ls180_test/idcode_test2.svf b/ls180_test/idcode_test2.svf new file mode 100644 index 0000000..a7545e0 --- /dev/null +++ b/ls180_test/idcode_test2.svf @@ -0,0 +1,46 @@ +STATE RESET IDLE; +TIR 0 ; +HIR 5 TDI (1f) SMASK (1f) ; +//HDR 1 TDI (00) SMASK (01) ; +TDR 0 ; +//Loading device with 'idcode' instruction. +SIR 4 TDI (1) SMASK (f) ; +//SDR 32 TDI (00000000) SMASK (ffffffff) TDO (00000c7f) SMASK (ffffffff) ; +SDR 32 TDI (00000000) SMASK (ffffffff) TDO (000018ff) MASK (ffffffff) ; +// + +// set to DMI "address" +SIR 4 TDI (8) SMASK (f) ; +// set DMI "ctrl" address (0) +SDR 8 TDI (0) SMASK (ff) ; +// set to DMI "data read" +SIR 4 TDI (9) SMASK (f) ; +// read 64 bit +SDR 64 TDI (0000000000000000) SMASK (0000000000000000) TDO (0000000000000004) MASK (ffffffffffffffff) ; + +// set to DMI "address" +SIR 4 TDI (8) SMASK (f) ; +// set DMI "ctrl" address (0) +SDR 8 TDI (0) SMASK (ff) ; +// set to DMI "data write-read" +SIR 4 TDI (a) SMASK (f) ; +// write-read 64 bit +SDR 64 TDI (0000000000000002) SMASK (ffffffffffffffff) TDO (0000000000000004) MASK (ffffffffffffffff) ; + +// set to DMI "address" +SIR 4 TDI (8) SMASK (f) ; +// set DMI "ctrl" address (0) +SDR 8 TDI (0) SMASK (ff) ; +// set to DMI "data read" +SIR 4 TDI (9) SMASK (f) ; +// read 64 bit +SDR 64 TDI (0000000000000000) SMASK (0000000000000000) TDO (0000000000000002) MASK (ffffffffffffffff) ; + +// set to DMI "address" +SIR 4 TDI (8) SMASK (f) ; +// set DMI "MSR" address (3) +SDR 8 TDI (3) SMASK (ff) ; +// set to DMI "data read" +SIR 4 TDI (9) SMASK (f) ; +// read 64 bit +SDR 64 TDI (0000000000000000) SMASK (0000000000000000) TDO (00000000deadbeef) MASK (ffffffffffffffff) ; diff --git a/ls180_test/main.cpp b/ls180_test/main.cpp new file mode 100644 index 0000000..c46e4d1 --- /dev/null +++ b/ls180_test/main.cpp @@ -0,0 +1,211 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ls180.cpp" + +#define VCD + +#ifdef VCD +#include +#endif + +using namespace std; + +extern "C" { + +/* nothing sophisticated: set up a listening socket + */ +int setup_socket() +{ + int listenfd = 0; + struct sockaddr_in serv_addr; + + listenfd = socket(AF_INET, SOCK_STREAM, 0); + memset(&serv_addr, '0', sizeof(serv_addr)); + + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(44853); + + bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); + listen(listenfd, 1); + + return listenfd; +} + +/* sees if there is an incoming connection (non-blocking). if so, + accept it and return it + */ +int get_connection(int listenfd) +{ + int connfd = 0; + int flag = 1; + int status; + fd_set active_fd_set; + + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = 1; + + /* Initialize the set of active sockets. */ + FD_ZERO (&active_fd_set); + FD_SET (listenfd, &active_fd_set); + + /* Block until input arrives on one or more active sockets. */ + status = select (FD_SETSIZE, &active_fd_set, NULL, NULL, &tv); + switch (status) + { + case -1: + printf("Error listening on socket\n"); + exit(status); // error + return -1; + case 0: + return -1; // timeout (nothing read) + default: + // return accepted socket + connfd = accept(listenfd, (struct sockaddr*)NULL, NULL); + setsockopt(connfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, + sizeof(int)); + return connfd; + } +} + +/* reads from a socket if it is ready (a single byte) and returns 1 if success + */ +int read_handler(int fdread, char *buffer) +{ + ssize_t read_len; + fd_set read_fds; + FD_ZERO(&read_fds); + FD_SET(fdread, &read_fds); + int status; + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = 1; + + status = select(fdread+1, &read_fds, NULL, NULL, &tv); + switch (status) + { + case -1: + printf("Error reading on socket\n"); + exit(status); // error + return 0; + case 0: + return 0; // timeout (nothing read) + default: + status = read(fdread, buffer, 1); + if (status == -1) { + printf("Error reading on socket\n"); + close(fdread); + } + return status; + } +} + +} // extern "C" + +/* main function which polls the socket and talks openocd jtagremote protocol. + dead simple: incoming number 0-7 sets TCK, TMS and TDK. request "R" + indicates that receiver wants to know the status of TDO. + "Q" means "quit socket". +*/ +int read_openocd_jtagremote(cxxrtl_design::p_ls180 &top, int sock) +{ + char c; + if (read_handler(sock, &c) != 1) { + return sock; + } + printf ("read %c\n", c); + if ((c >= '0') && (c <= '7')) + { + top.p_jtag__tck.set(((c - '0') >> 2) & 1); + top.p_jtag__tms.set(((c - '0') >> 1) & 1); + top.p_jtag__tdi.set((c - '0') & 1); + } + if (c == 'R') + { + uint8_t val = top.p_jtag__tdo.get() + '0'; + if(-1 == write(sock, &val, 1)) + { + printf("Error writing on socket\n"); + close(sock); + sock = -1; + } + } + if (c == 'Q') { + printf("disconnect request\n"); + close(sock); + sock = -1; + } + return sock; +} + +int main() +{ + cxxrtl_design::p_ls180 top; + int steps = 0; + +#ifdef VCD + // Load the debug items of the top down the whole design hierarchy + cxxrtl::debug_items all_debug_items; + top.debug_info(all_debug_items); + + // set up vcdwriter with 1ns resu + cxxrtl::vcd_writer vcd; + vcd.timescale(1, "us"); +#endif + + int listenfd = setup_socket(); + int sock = -1; + +#ifdef VCD + //vcd.add_without_memories(all_debug_items); + vcd.add(all_debug_items); + std::ofstream waves("waves.vcd"); +#endif + + top.step(); +#ifdef VCD + vcd.sample(0); +#endif + while (true) { + + top.p_sys__clk.set(false); + top.step(); +#ifdef VCD + vcd.sample(steps*2 + 0); +#endif + top.p_sys__clk.set(true); + top.step(); +#ifdef VCD + vcd.sample(steps*2 + 1); +#endif + steps++; + + // if no current connection see if there is one + if (sock == -1) { + sock = get_connection(listenfd); + } + /* read and process incoming jtag. sock set to -1 if disconnected */ + sock = read_openocd_jtagremote(top, sock); + + waves << vcd.buffer; + vcd.buffer.clear(); + } +} + diff --git a/ls180_test/openocd.cfg b/ls180_test/openocd.cfg new file mode 100644 index 0000000..a3c7084 --- /dev/null +++ b/ls180_test/openocd.cfg @@ -0,0 +1,15 @@ + +interface remote_bitbang +remote_bitbang_port 44853 +remote_bitbang_host localhost + +# this should be irlen=4 +jtag newtap libresoc tap -irlen 4 -irmask 0xf -ircapture 0xf -expected-id 0x000018ff + +#set _TARGETNAME libresoc.tap +#target create $_TARGETNAME.0 ppc64 -chain-position $_TARGETNAME -rtos hwthread + +# Configure work area in on-chip SRAM +#$_TARGETNAME.0 configure -work-area-phys 0x80000000 \ +# -work-area-size 1000 -work-area-backup 0 + diff --git a/ls180_test/openocd_test.sh b/ls180_test/openocd_test.sh new file mode 100755 index 0000000..dcad497 --- /dev/null +++ b/ls180_test/openocd_test.sh @@ -0,0 +1,6 @@ +#!/bin/sh +# run make followed by ./tb then run this script. + +openocd -f openocd.cfg -c init \ + -c 'svf idcode.svf' \ + -c shutdown