Half-precision floats handling
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

622 lines
16 KiB

// SPDX-License-Identifier: BSD-Source-Code
#include <stdio.h>
#include <stdlib.h>
#include <memtest.h>
#include <generated/csr.h>
#include <generated/mem.h>
#include "../command.h"
#include "../helpers.h"
/**
* Command "mr"
*
* Memory read
*
*/
static void mr(int nb_params, char **params)
{
char *c;
unsigned int *addr;
unsigned int length;
if (nb_params < 1) {
printf("mr <address> [length]");
return;
}
addr = (unsigned int *)strtoul(params[0], &c, 0);
if (*c != 0) {
printf("Incorrect address");
return;
}
if (nb_params == 1) {
length = 4;
} else {
length = strtoul(params[1], &c, 0);
if(*c != 0) {
printf("\nIncorrect length");
return;
}
}
dump_bytes(addr, length, (unsigned long)addr);
}
define_command(mr, mr, "Read address space", MEM_CMDS);
/**
* Command "mw"
*
* Memory write
*
*/
static void mw(int nb_params, char **params)
{
char *c;
unsigned int *addr;
unsigned int value;
unsigned int count;
unsigned int i;
if (nb_params < 2) {
printf("mw <address> <value> [count]");
return;
}
addr = (unsigned int *)strtoul(params[0], &c, 0);
if (*c != 0) {
printf("Incorrect address");
return;
}
value = strtoul(params[1], &c, 0);
if(*c != 0) {
printf("Incorrect value");
return;
}
if (nb_params == 2) {
count = 1;
} else {
count = strtoul(params[2], &c, 0);
if(*c != 0) {
printf("Incorrect count");
return;
}
}
for (i = 0; i < count; i++)
*addr++ = value;
}
define_command(mw, mw, "Write address space", MEM_CMDS);
/**
* Command "mc"
*
* Memory copy
*
*/
static void mc(int nb_params, char **params)
{
char *c;
unsigned int *dstaddr;
unsigned int *srcaddr;
unsigned int count;
unsigned int i;
if (nb_params < 2) {
printf("mc <dst> <src> [count]");
return;
}
dstaddr = (unsigned int *)strtoul(params[0], &c, 0);
if (*c != 0) {
printf("Incorrect destination address");
return;
}
srcaddr = (unsigned int *)strtoul(params[1], &c, 0);
if (*c != 0) {
printf("Incorrect source address");
return;
}
if (nb_params == 2) {
count = 1;
} else {
count = strtoul(params[2], &c, 0);
if (*c != 0) {
printf("Incorrect count");
return;
}
}
for (i = 0; i < count; i++)
*dstaddr++ = *srcaddr++;
}
define_command(mc, mc, "Copy address space", MEM_CMDS);
/**
* Command "memtest"
*
* Run a memory test
*
*/
static void memtest_handler(int nb_params, char **params)
{
char *c;
unsigned int *addr;
unsigned long maxsize = ~0uL;
if (nb_params < 1) {
printf("memtest <addr> [<maxsize>]");
return;
}
addr = (unsigned int *)strtoul(params[0], &c, 0);
if (*c != 0) {
printf("Incorrect address");
return;
}
if (nb_params >= 2) {
maxsize = strtoul(params[1], &c, 0);
if (*c != 0) {
printf("Incorrect max size");
return;
}
}
memtest(addr, maxsize);
}
define_command(memtest, memtest_handler, "Run a memory test", MEM_CMDS);
/**
* Command "memspeed"
*
* Run a memory speed test
*
*/
static void memspeed_handler(int nb_params, char **params)
{
char *c;
unsigned int *addr;
unsigned long size;
bool read_only = false;
if (nb_params < 1) {
printf("memspeed <addr> <size> [<readonly>]");
return;
}
addr = (unsigned int *)strtoul(params[0], &c, 0);
if (*c != 0) {
printf("Incorrect address");
return;
}
size = strtoul(params[1], &c, 0);
if (*c != 0) {
printf("Incorrect size");
return;
}
if (nb_params >= 3) {
read_only = (bool) strtoul(params[2], &c, 0);
if (*c != 0) {
printf("Incorrect readonly value");
return;
}
}
memspeed(addr, size, read_only);
}
define_command(memspeed, memspeed_handler, "Run a memory speed test", MEM_CMDS);
#ifdef CSR_DEBUG_PRINTER
/**
* Command "csrprint"
*
* Print CSR values
*
*/
static void csrprint(int nb_params, char **params)
{
print_csrs();
}
define_command(csrprint, csrprint, "Print CSR values", MEM_CMDS);
#endif
#ifdef CSR_WB_SOFTCONTROL_BASE
static void wbr(int nb_params, char **params)
{
char *c;
unsigned int *addr;
unsigned int length;
unsigned int i;
if (nb_params < 1) {
printf("mr <address> [length]");
return;
}
addr = (unsigned int *)strtoul(params[0], &c, 0);
if (*c != 0) {
printf("Incorrect address");
return;
}
if (nb_params == 1) {
length = 4;
} else {
length = strtoul(params[1], &c, 0);
if(*c != 0) {
printf("\nIncorrect length");
return;
}
}
for (i = 0; i < length; ++i) {
wb_softcontrol_adr_write((unsigned long)(addr + i));
wb_softcontrol_read_write(1);
printf("0x%08x: 0x%08x\n", (unsigned long)(addr + i), wb_softcontrol_data_read());
}
}
define_command(wbr, wbr, "Read using softcontrol wishbone controller", MEM_CMDS);
static void wbw(int nb_params, char **params)
{
char *c;
unsigned int *addr;
unsigned int value;
unsigned int count;
unsigned int i;
if (nb_params < 2) {
printf("mw <address> <value> [count]");
return;
}
addr = (unsigned int *)strtoul(params[0], &c, 0);
if (*c != 0) {
printf("Incorrect address");
return;
}
value = strtoul(params[1], &c, 0);
if(*c != 0) {
printf("Incorrect value");
return;
}
if (nb_params == 2) {
count = 1;
} else {
count = strtoul(params[2], &c, 0);
if(*c != 0) {
printf("Incorrect count");
return;
}
}
wb_softcontrol_data_write(value);
for (i = 0; i < count; i++) {
wb_softcontrol_adr_write((unsigned long)(addr + i));
wb_softcontrol_write_write(1);
}
}
define_command(wbw, wbw, "Write using softcontrol wishbone controller", MEM_CMDS);
#endif
/*
* Command "mx"
*
* Memory execute
*/
#ifdef CMD_MEM_MX
static void mx(int nb_params, char **params)
{
char *c;
unsigned int *addr,i;
unsigned int length;
if (nb_params < 1) {
// Hunt for 12h 34h 56h 78h 87h 65h 43h 21h ...
// Subtract 10h & jump ...
c = (char *)0x40000000; //MAIN_RAM_BASE;
for(i=0;i < (0x400000-8);i++) //MAIN_RAM_LENGTH;i++)
{
if( (*(c + i) == 0x12)
&& (*(c+i+1) == 0x34)
&& (*(c+i+2) == 0x56)
&& (*(c+i+3) == 0x78)
&& (*(c+i+4) == 0x87)
&& (*(c+i+5) == 0x65)
&& (*(c+i+6) == 0x43)
&& (*(c+i+7) == 0x21)
)
{
c = c + i - 0x10;
printf("Signature match @%08Xh\n", c);
addr = (unsigned int *)c;
break;
}
}
if(i >= 0x400000-32)
{
printf("Signature not found?!\n");
return;
}
}
else {
addr = (unsigned int *)strtoul(params[0], &c, 0);
if (*c != 0) {
printf("Incorrect address");
return;
}
}
//printf("Executing from ...\n");
//length = 32;
//dump_bytes(addr, length, (unsigned long)addr);
//serial output requires delay ?!
extern void busy_wait(unsigned int ms); // Worx!
busy_wait(2000);
void (*fptr)(void);
fptr = (void (*))addr;
(fptr)();
//printf("Returned from execution.\n");
}
define_command(mx, mx, "Execute in RAM, optional: @address / signature hunt otherwise", MEM_CMDS);
#endif
/*
* Command "mhsig"
*
* Memory hunt signature
*/
#ifdef CMD_MEM_MHSIG
static void mhsig(int nb_params, char **params)
{
char *c;
unsigned int *addr,i;
unsigned int length;
if (nb_params < 1) {
// Hunt for 12h 34h 56h 78h 87h 65h 43h 21h ...
// Subtract 10h & jump ...
c = (char *)0x40000000; //MAIN_RAM_BASE;
for(i=0;i < (0x400000-8);i++) //MAIN_RAM_LENGTH;i++)
{
if( (*(c + i) == 0x12)
&& (*(c+i+1) == 0x34)
&& (*(c+i+2) == 0x56)
&& (*(c+i+3) == 0x78)
&& (*(c+i+4) == 0x87)
&& (*(c+i+5) == 0x65)
&& (*(c+i+6) == 0x43)
&& (*(c+i+7) == 0x21)
)
{
c = c + i - 0x10;
printf("Signature match @%08Xh\n", c);
addr = (unsigned int *)c;
break;
}
}
if(i >= 0x400000-32)
{
printf("Signature not found?!\n");
return;
}
}
}
define_command(mhsig, mhsig, "RAM signature hunt", MEM_CMDS);
#endif
/*
* Command "dumpregs"
*
* Dump registers
*/
#define CMD_MEM_DUMPREGS 1
#ifdef CMD_MEM_DUMPREGS
// Register x
// versus ABI
#define REG_ZERO 0 // Fixed zero
#define REG_ra 1 // Return adress
#define REG_sp 2 // Stack pointer
#define REG_gp 3 // Global pointer
#define REG_tp 4 // Thread pointer
#define REG_t0 5 // Temporary
#define REG_t1 6 // Temporary
#define REG_t2 7 // Temporary
#define REG_fp_s0 8 // Frame pointer (or saved register)
#define REG_s1 9 // Saved register
#define REG_a0 10 // Function argument / return value
#define REG_a1 11 // Function argument / return value
#define REG_a2 12 // Function argument / return value
#define REG_a3 13 // Function argument / return value
#define REG_a4 14 // Function argument / return value
#define REG_a5 15 // Function argument / return value
#define REG_a6 16 // Function argument / return value
#define REG_a7 17 // Function argument / return value
#define REG_s2 18 // Saved register
#define REG_s3 19 // Saved register
#define REG_s4 20 // Saved register
#define REG_s5 21 // Saved register
#define REG_s6 22 // Saved register
#define REG_s7 23 // Saved register
#define REG_s8 24 // Saved register
#define REG_s9 25 // Saved register
#define REG_s10 26 // Saved register
#define REG_s11 27 // Saved register
#define REG_t3 28 // Temporary
#define REG_t4 29 // Temporary
#define REG_t5 30 // Temporary
#define REG_t6 31 // Temporary
#define REG_oldpc 32 // --- No register!
#define CSR_mstatus 33 // Control & status register
#define CSR_mip 34
#define CSR_mie 35
#define CSR_mcause 36
#define CSR_mtvec 37
#define CSR_mtval 38
#define CSR_mepc 39
#define CSR_mscratch 40
#define CSR_misa 41 // ID regs.
#define CSR_mvendorid 42
#define CSR_marchid 43
#define CSR_mimpid 44
#define CSR_mhartid 45
int32_t regs[32+1+8+5]; // Only standard regs avail. + PC + machine mode CSR + CSR ID regs.
static void dumpregs(int nb_params, char **params)
{
__asm__ __volatile__ ("\
nop \n\
lui t0,%hi(regs) # Load t0 w/ high adress of regs[] \n\
addi t0,t0,%lo(regs) # Add immediate t0=t0+ low adress regs[] \n\
# t0 now loaded with 64-bit pointer to regs[0] \n\
lw t1,60(sp) # Load stored return address (pc!) (64 bit) \n\
sw t1,0(t0) # Store to - unusable - zero (regs[REG_ZERO]) \n\
sw ra,4(t0) # Current return adress -> regs[REG_ra] \n\
sw sp,8(t0) # Stack pointer \n\
sw gp,12(t0) # Global pointer \n\
sw tp,16(t0) # Thread pointer \n\
sw t0,20(t0) # Temporary / alternate link register \n\
sw t1,24(t0) # Temporary \n\
sw t2,28(t0) # Temporary \n\
sw fp,32(t0) # Frame pointer / saved register 0 \n\
sw s1,36(t0) # Saved register \n\
sw a0,40(t0) # Function argument / return value \n\
sw a1,44(t0) # Function argument / return value \n\
sw a2,48(t0) # Function argument \n\
sw a3,52(t0) # Function argument \n\
sw a4,56(t0) # Function argument \n\
sw a5,60(t0) # Function argument \n\
sw a6,64(t0) # Function argument \n\
sw a7,68(t0) # Function argument \n\
sw s2,72(t0) # Saved register \n\
sw s3,76(t0) # Saved register \n\
sw s4,80(t0) # Saved register \n\
sw s5,84(t0) # Saved register \n\
sw s6,88(t0) # Saved register \n\
sw s7,92(t0) # Saved register \n\
sw s8,96(t0) # Saved register \n\
sw s9,100(t0) # Saved register \n\
sw s10,104(t0) # Saved register \n\
sw s11,108(t0) # Saved register \n\
sw t3,112(t0) # Temporary \n\
sw t4,116(t0) # Temporary \n\
sw t5,120(t0) # Temporary \n\
sw t6,124(t0) # Temporary \n\
auipc t1,0 # Load current pc \n\
sw t1,128(t0) # Store current PC \n\
# Machine mode (level 3) registers \n\
csrr t1,mstatus # Interrupt enable & stati \n\
sw t1,132(t0) # Store mstatus \n\
csrr t1,mip # Machine interrupt pending \n\
sw t1,136(t0) # Store mip \n\
csrr t1,mie # Machine interrupt enable \n\
sw t1,140(t0) # Store mie \n\
csrr t1,mcause # Machine exception cause \n\
sw t1,144(t0) # Store mcause \n\
csrr t1,mtvec # Machine trap vector \n\
sw t1,148(t0) # Store mtvec \n\
csrr t1,mtval # Machine trap value \n\
sw t1,152(t0) # Store mtval \n\
csrr t1,mepc # Machine exception pc \n\
sw t1,156(t0) # Store mepc \n\
csrr t1,mscratch # Machine scratch \n\
sw t1,160(t0) # Store mscratch \n\
# Identification registers \n\
csrr t1,misa # Machine ISA \n\
sw t1,164(t0) # Store misa \n\
csrr t1,mvendorid # Machine vendor ID \n\
sw t1,168(t0) # Store mvendorid \n\
csrr t1,marchid # Machine base microarchitecture \n\
sw t1,172(t0) # Store marchid \n\
csrr t1,mimpid # Machine base microarchitecture version \n\
sw t1,176(t0) # Store mimpid \n\
csrr t1,mhartid # Machine hardware thread ('core') ID \n\
sw t1,180(t0) # Store mhartid \n\
nop \n\
");
printf("---- RISC-V (ABI: RV32I) ---- \n");
printf("Specials: pc=%08Xh zero=00000000h (frame[ra]):%08Xh)\n", regs[REG_oldpc], regs[REG_ZERO]);
printf("Pointers: ra=%08Xh sp=%08Xh gp=%08Xh tp=%08Xh fp=%08Xh\n", regs[REG_ra], regs[REG_sp], regs[REG_gp], regs[REG_tp], regs[REG_fp_s0]);
printf("Temporaries: t0=%08Xh t1=%08Xh t2=%08Xh t3=%08Xh t4=%08Xh t5=%08Xh t6=%08Xh\n",
regs[REG_t0], regs[REG_t1], regs[REG_t2], regs[REG_t3], regs[REG_t4], regs[REG_t5], regs[REG_t6]);
printf("Saved: s1=%08Xh s2=%08Xh s3=%08Xh s4=%08Xh s5=%08Xh s6=%08Xh s7=%08Xh s8=%08Xh s9=%08Xh s10=%08Xh s11=%08Xh\n",
regs[REG_s1], regs[REG_s2], regs[REG_s3], regs[REG_s4], regs[REG_s5], regs[REG_s6],
regs[REG_s7], regs[REG_s8], regs[REG_s9], regs[REG_s10], regs[REG_s11]);
printf("Arg./Ret.: a0=%08Xh a1=%08Xh a2=%08Xh a3=%08Xh a4=%08Xh a5=%08Xh a6=%08Xh a7=%08Xh\n",
regs[REG_a0], regs[REG_a1], regs[REG_a2], regs[REG_a3], regs[REG_a4], regs[REG_a5], regs[REG_a6], regs[REG_a7]);
printf("-- Machine mode --\n");
printf("CSR: mstatus=%08Xh mip=%08Xh mie=%08Xh mcause=%08Xh mtvec=%08Xh mtval=%08Xh mepc=%08Xh mscratch=%08Xh\n",
regs[CSR_mstatus], regs[CSR_mip], regs[CSR_mie], regs[CSR_mcause],
regs[CSR_mtvec], regs[CSR_mtval], regs[CSR_mepc], regs[CSR_mscratch]);
printf("-- Identification CSRs --\n");
printf("CSR: misa=%08Xh mvendorid=%08Xh marchid=%08Xh mimpid=%08Xh mhartid=%08Xh\n",
regs[CSR_misa], regs[CSR_mvendorid], regs[CSR_marchid], regs[CSR_mimpid], regs[CSR_mhartid]);
}
define_command(dumpregs, dumpregs, "Dump processor registers", MEM_CMDS);
#endif
/*
* Command "ramboot"
*
* Try to boot from RAM
*/
#define CMD_MEM_RAMBOOT 1
#ifdef CMD_MEM_RAMBOOT
int32_t cpc; // Current PC storage
static void ramboot(int nb_params, char **params)
{
extern void doRAMboot(int ramno);
int ramno;
char *c;
// Verify where we're executing (within RAM) ...
__asm__ __volatile__ ("\
lui t0,%hi(cpc) # Load t0 w/ high adress of cpc \n\
addi t0,t0,%lo(cpc) # Add immediate t0=t0 + low adress cpc \n\
# t0 now loaded with pointer to cpc \n\
auipc t1,0 # Load current pc \n\
sw t1,0(t0) # Store current PC \n\
");
// Executing in RAM bank #1?
if((cpc >= MAIN_RAM_BASE) && (cpc < (MAIN_RAM_BASE + (MAIN_RAM_SIZE / 2)))) {
ramno = 2; // Boot RAM[2] hence!
//printf("\e[1mExecuting within RAM bank #1 -> Booting RAM banking #2 ...\e[0m\n");
c = (char *)(MAIN_RAM_BASE + (MAIN_RAM_SIZE / 2)); //0x40200000
}
else { // Nope, in RAM bank #2 assumed ...
ramno = 1; // Boot RAM[1]
c = (char *)MAIN_RAM_BASE; //0x40000000
}
if( (*(c + 0) == 0xff)
&& (*(c + 1) == 0xff)
&& (*(c + 2) == 0xff)
&& (*(c + 3) == 0xff)
&& (*(c + 4) == 0xff)
&& (*(c + 5) == 0xff)
&& (*(c + 6) == 0xff)
&& (*(c + 7) == 0xff)
)
{
printf("No program loaded to RAM bank #%d?!\n", ramno);
return;
}
doRAMboot(ramno); // Try to boot ...
}
define_command(ramboot, ramboot, "Boot from RAM", MEM_CMDS);
#endif