Passing with custom linker file

This commit is contained in:
Guy Hutchison 2018-10-18 18:47:06 +00:00
parent ef386e8f17
commit f47ac81c89
7 changed files with 442 additions and 0 deletions

View File

@ -0,0 +1,21 @@
#include <stdio.h>
#include <stdlib.h>
int x1 = 1000;
int x2 = 2000;
void main()
{
int z;
x1 = 50;
x2 = 50;
printf("hello\n");
z = (x1 + x2);
if (z == 100)
printf("TEST PASSED\n");
else
printf("TEST FAILED, z=%d\n", z);
exit(0);
}

View File

@ -0,0 +1,34 @@
#!/usr/bin/env python3
import fileinput
import itertools
ptr = 0
data = []
def write_data():
if len(data) != 0:
print("@%08x" % (ptr >> 2))
while len(data) % 4 != 0:
data.append(0)
for word_bytes in zip(*([iter(data)]*4)):
print("".join(["%02x" % b for b in reversed(word_bytes)]))
for line in fileinput.input():
if line.startswith("@"):
addr = int(line[1:], 16)
if addr > ptr+4:
write_data()
ptr = addr
data = []
while ptr % 4 != 0:
data.append(0)
ptr -= 1
else:
while ptr + len(data) < addr:
data.append(0)
else:
data += [int(tok, 16) for tok in line.split()]
write_data()

View File

@ -0,0 +1,28 @@
#!/usr/bin/env python3
import re
symbol = re.compile("\s*0x([0-9a-f]+)\s+([\w_]+)\s*$")
symbol_map = {}
with open("firmware.map", "r") as fh:
for fd in fh:
sym = symbol.match(fd)
if (sym):
addr = int(sym.group(1), 16)
symbol_map[addr] = sym.group(2)
with open("firmware_dbg.v", "w") as fh:
fh.write(" task firmware_dbg;\n")
fh.write(" input [31:0] addr;\n");
fh.write(" begin\n");
fh.write(" case (addr)\n");
for k, v in symbol_map.items():
fh.write(" 32'h{0:08x} : $display(\"%t: FCALL: {1:s}\", $time);\n".format(k, v))
fh.write(" endcase\n");
fh.write(" end\n");
fh.write(" endtask\n");
with open("firmware_addr.txt", "w") as fh:
for k, v in symbol_map.items():
fh.write("{0:08x} {1:s}\n".format(k,v))

View File

@ -0,0 +1,47 @@
/*
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
*/
MEMORY {
rom(rwx) : ORIGIN = 0x00000100, LENGTH = 63k
ram(rwx) : ORIGIN = 0x00020000, LENGTH = 16k
}
C_STACK_SIZE = 512;
ENTRY(_pvstart);
SECTIONS {
.rom : {
_pvstart*(.text);
start*(.text);
. = 0x100;
. = ALIGN(4);
*(.text);
} > rom
.data : {
_data_lma = LOADADDR(.data);
_data = .;
__global_pointer$ = . ;
*(.data .data.* )
*(.sdata .sdata.*)
. = ALIGN(4);
_edata = .;
/* } >ram AT>rom */
/* } >ram */
.bss : {
_bss_start = .;
*(.bss .bss.*)
. = ALIGN(4);
_bss_end = .;
_end = .;
} >ram
}

86
scripts/romload/start.S Normal file
View File

@ -0,0 +1,86 @@
.section .text
.global _start
.global _pvstart
.global _data
.global _data_lma
_pvstart:
/* zero-initialize all registers */
addi x1, zero, 0
addi x2, zero, 0
addi x3, zero, 0
addi x4, zero, 0
addi x5, zero, 0
addi x6, zero, 0
addi x7, zero, 0
addi x8, zero, 0
addi x9, zero, 0
addi x10, zero, 0
addi x11, zero, 0
addi x12, zero, 0
addi x13, zero, 0
addi x14, zero, 0
addi x15, zero, 0
addi x16, zero, 0
addi x17, zero, 0
addi x18, zero, 0
addi x19, zero, 0
addi x20, zero, 0
addi x21, zero, 0
addi x22, zero, 0
addi x23, zero, 0
addi x24, zero, 0
addi x25, zero, 0
addi x26, zero, 0
addi x27, zero, 0
addi x28, zero, 0
addi x29, zero, 0
addi x30, zero, 0
addi x31, zero, 0
/* set stack pointer */
lui sp, %hi(4*1024*1024)
addi sp, sp, %lo(4*1024*1024)
/*
lui sp, %hi(0x100000)
addi sp, sp, %lo(0x100000)
*/
/* push zeros on the stack for argc and argv */
/* (stack is aligned to 16 bytes in riscv calling convention) */
addi sp,sp,-16
sw zero,0(sp)
sw zero,4(sp)
sw zero,8(sp)
sw zero,12(sp)
/*
// Load data section
la a0, _data_lma
la a1, _data
la a2, _edata
bgeu a1, a2, 2f
1:
lw t0, (a0)
sw t0, (a1)
addi a0, a0, 4
addi a1, a1, 4
bltu a1, a2, 1b
2:
// Clear bss section
la a0, _bss_start
la a1, _bss_end
bgeu a0, a1, 2f
1:
sw zero, (a0)
addi a0, a0, 4
bltu a0, a1, 1b
2:
*/
/* jump to libc init */
/*j _ftext
*/
j _start

View File

@ -0,0 +1,95 @@
// An extremely minimalist syscalls.c for newlib
// Based on riscv newlib libgloss/riscv/sys_*.c
// Written by Clifford Wolf.
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#define UNIMPL_FUNC(_f) ".globl " #_f "\n.type " #_f ", @function\n" #_f ":\n"
asm (
".text\n"
".align 2\n"
UNIMPL_FUNC(_open)
UNIMPL_FUNC(_openat)
UNIMPL_FUNC(_lseek)
UNIMPL_FUNC(_stat)
UNIMPL_FUNC(_lstat)
UNIMPL_FUNC(_fstatat)
UNIMPL_FUNC(_isatty)
UNIMPL_FUNC(_access)
UNIMPL_FUNC(_faccessat)
UNIMPL_FUNC(_link)
UNIMPL_FUNC(_unlink)
UNIMPL_FUNC(_execve)
UNIMPL_FUNC(_getpid)
UNIMPL_FUNC(_fork)
UNIMPL_FUNC(_kill)
UNIMPL_FUNC(_wait)
UNIMPL_FUNC(_times)
UNIMPL_FUNC(_gettimeofday)
UNIMPL_FUNC(_ftime)
UNIMPL_FUNC(_utime)
UNIMPL_FUNC(_chown)
UNIMPL_FUNC(_chmod)
UNIMPL_FUNC(_chdir)
UNIMPL_FUNC(_getcwd)
UNIMPL_FUNC(_sysconf)
"j unimplemented_syscall\n"
);
void unimplemented_syscall()
{
const char *p = "Unimplemented system call called!\n";
while (*p)
*(volatile int*)0x10000000 = *(p++);
asm volatile ("ebreak");
__builtin_unreachable();
}
ssize_t _read(int file, void *ptr, size_t len)
{
// always EOF
return 0;
}
ssize_t _write(int file, const void *ptr, size_t len)
{
const void *eptr = ptr + len;
while (ptr != eptr)
*(volatile int*)0x10000000 = *(char*)(ptr++);
return len;
}
int _close(int file)
{
// close is called before _exit()
return 0;
}
int _fstat(int file, struct stat *st)
{
// fstat is called during libc startup
errno = ENOENT;
return -1;
}
void *_sbrk(ptrdiff_t incr)
{
extern unsigned char _end[]; // Defined by linker
static unsigned long heap_end;
if (heap_end == 0)
heap_end = (long)_end;
heap_end += incr;
return (void *)(heap_end - incr);
}
void _exit(int exit_status)
{
asm volatile ("ebreak");
__builtin_unreachable();
}

131
scripts/romload/testbench.v Normal file
View File

@ -0,0 +1,131 @@
`timescale 1 ns / 1 ps
`undef VERBOSE_MEM
//`undef WRITE_VCD
`undef MEM8BIT
`define ROM_SIZE 32'h0000_0000
//`define ROM_SIZE 32'h0000_0000
module testbench;
reg clk = 1;
reg resetn = 0;
wire trap;
always #5 clk = ~clk;
initial begin
repeat (100) @(posedge clk);
resetn <= 1;
end
wire mem_valid;
wire mem_instr;
reg mem_ready;
wire [31:0] mem_addr;
wire [31:0] mem_wdata;
wire [3:0] mem_wstrb;
reg [31:0] mem_rdata;
`include "firmware_dbg.v"
picorv32 #(
.COMPRESSED_ISA(1),
.PROGADDR_RESET(32'h100),
.ENABLE_MUL(1),
.ENABLE_DIV(1)
) uut (
.clk (clk ),
.resetn (resetn ),
.trap (trap ),
.mem_valid (mem_valid ),
.mem_instr (mem_instr ),
.mem_ready (mem_ready ),
.mem_addr (mem_addr ),
.mem_wdata (mem_wdata ),
.mem_wstrb (mem_wstrb ),
.mem_rdata (mem_rdata )
);
localparam MEM_SIZE = 4*1024*1024;
`ifdef MEM8BIT
reg [7:0] memory [0:MEM_SIZE-1];
initial
$readmemh("firmware.hex", memory);
end
`else
reg [31:0] memory [0:MEM_SIZE/4-1];
integer x;
initial
begin
for (x=0; x<MEM_SIZE/4; x=x+1) memory[x] = 0;
$readmemh("firmware32.hex", memory);
end
`endif
always @(posedge clk) begin
mem_ready <= 0;
if (mem_valid && !mem_ready) begin
mem_ready <= 1;
mem_rdata <= 'bx;
case (1)
mem_addr < MEM_SIZE: begin
`ifdef MEM8BIT
if (|mem_wstrb) begin
if (mem_wstrb[0]) memory[mem_addr + 0] <= mem_wdata[ 7: 0];
if (mem_wstrb[1]) memory[mem_addr + 1] <= mem_wdata[15: 8];
if (mem_wstrb[2]) memory[mem_addr + 2] <= mem_wdata[23:16];
if (mem_wstrb[3]) memory[mem_addr + 3] <= mem_wdata[31:24];
end else begin
mem_rdata <= {memory[mem_addr+3], memory[mem_addr+2], memory[mem_addr+1], memory[mem_addr]};
end
`else
if ((|mem_wstrb) && (mem_addr >= `ROM_SIZE)) begin
if (mem_wstrb[0]) memory[mem_addr >> 2][ 7: 0] <= mem_wdata[ 7: 0];
if (mem_wstrb[1]) memory[mem_addr >> 2][15: 8] <= mem_wdata[15: 8];
if (mem_wstrb[2]) memory[mem_addr >> 2][23:16] <= mem_wdata[23:16];
if (mem_wstrb[3]) memory[mem_addr >> 2][31:24] <= mem_wdata[31:24];
end else begin
mem_rdata <= memory[mem_addr >> 2];
end
`endif
end
mem_addr == 32'h 1000_0000: begin
$write("%c", mem_wdata[7:0]);
end
endcase
end
if (mem_valid && mem_ready) begin
// firmware_dbg(mem_addr);
if ((mem_wstrb == 4'h0) && (mem_rdata === 32'bx)) $display("READ FROM UNITIALIZED ADDR=%x", mem_addr);
`ifdef VERBOSE_MEM
if (|mem_wstrb)
$display("WR: ADDR=%x DATA=%x MASK=%b", mem_addr, mem_wdata, mem_wstrb);
else
$display("RD: ADDR=%x DATA=%x%s", mem_addr, mem_rdata, mem_instr ? " INSN" : "");
`endif
if (^mem_addr === 1'bx ||
(mem_wstrb[0] && ^mem_wdata[ 7: 0] == 1'bx) ||
(mem_wstrb[1] && ^mem_wdata[15: 8] == 1'bx) ||
(mem_wstrb[2] && ^mem_wdata[23:16] == 1'bx) ||
(mem_wstrb[3] && ^mem_wdata[31:24] == 1'bx)) begin
$display("CRITICAL UNDEF MEM TRANSACTION");
$finish;
end
end
end
`ifdef WRITE_VCD
initial begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
end
`endif
always @(posedge clk) begin
if (resetn && trap) begin
repeat (10) @(posedge clk);
$display("TRAP");
$finish;
end
end
endmodule