Commit 2a2d523f authored by Adam Wujek's avatar Adam Wujek

tools/spec-cl: add support of uRV/RISCV

Signed-off-by: 's avatarAdam Wujek <dev_public@wujek.eu>
parent f22fff86
/*
* A tool to program our soft-core (LM32) within the SPEC.
* A tool to program our soft-core (uRV and LM32) within the SPEC.
*/
#include <stdio.h>
......@@ -17,14 +17,25 @@ static void print_version(char *pname)
printf("%s\n", libspec_version_s);
}
enum cpu_type {
unknown = 0,
lm32,
riscv
};
int main(int argc, char **argv)
{
int bus = -1, dev_fn = -1, c;
uint32_t lm32_base = 0x80000;
uint32_t urv_csr_base = 0x80000;
uint32_t cpu_base = 0x0;
enum cpu_type cpu_type = lm32; /* make it backward compatible */
void *card;
int read_mode = 0;
size_t read_size = 0;
while ((c = getopt (argc, argv, "b:d:c:V")) != -1)
while ((c = getopt (argc, argv, "b:d:c:ilrs:V")) != -1)
{
switch(c)
{
......@@ -35,7 +46,22 @@ int main(int argc, char **argv)
sscanf(optarg, "%i", &dev_fn);
break;
case 'c':
sscanf(optarg, "%i", &lm32_base);
sscanf(optarg, "%i", &cpu_base);
break;
case 'i':
/* RISCV mode */
cpu_type = riscv;
break;
case 'l':
/* LM32 mode */
cpu_type = lm32;
break;
case 'r':
read_mode = 1;
break;
case 's':
/* read size */
sscanf(optarg, "%li", &read_size);
break;
case 'V':
print_version(argv[0]);
......@@ -43,16 +69,35 @@ int main(int argc, char **argv)
default:
fprintf(stderr,
"Use: \"%s [-V] [-b bus] [-d devfn] "
"[-c lm32 base address] <lm32_program.bin>\"\n",
"[-c <base address>] [-l|-s] "
"<program.bin>\"\n"
"-l - load into LM32 memory (default)\n"
"-i - load into uRV(RISCV)\n"
"-r - read memory from uRV(RISCV) into a file <program.bin>\n"
" NOTE: It will trigger the restart of the uRV core after the read!\n"
"-s <size>\n",
argv[0]);
fprintf(stderr,
"%s loads the binary into LM32 or uRV(RISCV) "
"memory\n"
"By default, the first available SPEC is used "
"and the LM32 is assumed at 0x%x.\n",
lm32_base);
"and the LM32 mode is assumed. The default "
"load address for the LM32 is 0x%x, for the "
"uRV CPU CSR is 0x%x.\n",
argv[0], lm32_base, urv_csr_base);
exit(1);
}
}
if (!cpu_base) {
/* Custom address not specified, use the default
* depending on the CPU type */
if (cpu_type == lm32)
cpu_base = lm32_base;
if (cpu_type == riscv)
cpu_base = urv_csr_base;
}
if (optind >= argc) {
fprintf(stderr, "%s: Expected binary name after options.\n",
argv[0]);
......@@ -68,9 +113,27 @@ int main(int argc, char **argv)
exit(1);
}
if(spec_load_lm32(card, argv[optind], lm32_base) < 0)
{
fprintf(stderr, "%s: Loader failure.\n", argv[0]);
if (read_mode) {
if (cpu_type != riscv) {
fprintf(stderr, "%s: read of memory (-r parameter) can"
" be used only for RISCV architecture. "
"Exiting...\n", argv[0]);
exit(0);
}
spec_dump_urv_mem(card, argv[optind], urv_csr_base, read_size);
exit(0);
}
if (cpu_type == lm32
&& spec_load_lm32(card, argv[optind], urv_csr_base) < 0) {
fprintf(stderr, "%s: LM32 Loader failure.\n", argv[0]);
exit(1);
}
if (cpu_type == riscv
&& spec_load_urv(card, argv[optind], urv_csr_base) < 0) {
fprintf(stderr, "%s: RISCV Loader failure.\n", argv[0]);
exit(1);
}
......
......@@ -19,6 +19,10 @@
#include "loader-ll.h"
#include "wb_uart.h"
#define WRC_CPU_CSR_RESET 0x20900
#define WRC_CPU_CSR_UADDR 0x20904
#define WRC_CPU_CSR_UDATA 0x20908
const char * const libspec_version_s = "libspec version: " GIT_VERSION;
struct spec_private {
......@@ -414,6 +418,100 @@ int spec_load_lm32(void *card, const char *filename, uint32_t base_addr)
return 0;
}
int spec_load_urv(void *card, const char *filename, uint32_t base_addr)
{
char *buf;
uint32_t *ibuf;
size_t size;
int i;
buf = load_binary_file(filename, &size);
if(!buf)
return -1;
/* Phew... we are there, finally */
spec_writel(card, 0x1deadbee, base_addr + 0x20400);
while ( ! (spec_readl(card, base_addr + 0x20400) & (1<<28)) );
spec_writel(card, 1, base_addr + WRC_CPU_CSR_RESET );
ibuf = (uint32_t *) buf;
for (i = 0; i < (size + 3) / 4; i++)
{
spec_writel(card, i, base_addr + WRC_CPU_CSR_UADDR);
spec_writel(card, htonl(ibuf[i]), base_addr + WRC_CPU_CSR_UDATA);
}
sync();
for (i = 0; i < (size + 3) / 4; i++) {
spec_writel(card, i, base_addr + WRC_CPU_CSR_UADDR);
uint32_t r = spec_readl(card, base_addr + WRC_CPU_CSR_UDATA);
if (r != htonl(ibuf[i]))
{
fprintf(stderr, "programming error at %x "
"(expected %08x, found %08x)\n", i*4,
htonl(ibuf[i]), r);
return -1;
}
}
sync();
spec_writel(card, 0x0deadbee, base_addr + 0x20400);
spec_writel(card, 0, base_addr + WRC_CPU_CSR_RESET );
return 0;
}
int spec_dump_urv_mem(void *card, const char *filename, uint32_t base_addr,
size_t size)
{
size_t def_size = 192*1024;
int i, tmp;
uint32_t r;
FILE *f;
if (!size)
size = def_size;
f = fopen(filename, "w");
if (!f) {
fprintf(stderr, "%s: %s\n", filename, strerror(errno));
return -1;
}
spec_writel(card, 0x1deadbee, base_addr + 0x20400);
while ( ! (spec_readl(card, base_addr + 0x20400) & (1<<28)) );
spec_writel(card, 1, base_addr + WRC_CPU_CSR_RESET );
for (i = 0; i < (size + 3) / 4; i++) {
spec_writel(card, i, base_addr + WRC_CPU_CSR_UADDR);
r = spec_readl(card, base_addr + WRC_CPU_CSR_UDATA);
/* Change the endianness to reflect the same byte order as
* written binary into memory */
r = ntohl(r);
tmp = fwrite(&r, 1, sizeof(r), f);
if (tmp < 0) {
fprintf(stderr, "writing %s: %s\n", filename, strerror(errno));
return -1;
}
}
sync();
spec_writel(card, 0x0deadbee, base_addr + 0x20400);
spec_writel(card, 0, base_addr + WRC_CPU_CSR_RESET );
fclose(f);
printf("0x%lx bytes written to the file %s\n", size, filename);
return 0;
}
int spec_vuart_init(void *card, uint32_t base_addr)
{
struct spec_private *p = (struct spec_private *) card;
......
......@@ -39,6 +39,13 @@ int spec_load_bitstream_buffer(void *card, void *buf, size_t size);
WARNING: using improper base address/FPGA firmware will freeze the computer. */
int spec_load_lm32(void *card, const char *filename, uint32_t base_addr);
/* Loads the WRC RISCV firmware into card [card] from file [filename]. starting at
address [base_addr]. Returns 0 on success.
WARNING: using improper base address/FPGA firmware will freeze the computer. */
int spec_load_urv(void *card, const char *filename, uint32_t base_addr);
int spec_dump_urv_mem(void *card, const char *filename, uint32_t base_addr,
size_t size);
/* Raw I/O to BAR4 (Wishbone) */
void spec_writel(void *card, uint32_t data, uint32_t addr);
uint32_t spec_readl(void *card, uint32_t addr);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment