From f47ac81c89a517a57fd3c0656cab7a4075334328 Mon Sep 17 00:00:00 2001 From: Guy Hutchison Date: Thu, 18 Oct 2018 18:47:06 +0000 Subject: [PATCH] Passing with custom linker file --- scripts/romload/firmware.c | 21 ++++++ scripts/romload/hex8tohex32.py | 34 +++++++++ scripts/romload/map2debug.py | 28 +++++++ scripts/romload/sections.lds | 47 ++++++++++++ scripts/romload/start.S | 86 ++++++++++++++++++++++ scripts/romload/syscalls.c | 95 ++++++++++++++++++++++++ scripts/romload/testbench.v | 131 +++++++++++++++++++++++++++++++++ 7 files changed, 442 insertions(+) create mode 100644 scripts/romload/firmware.c create mode 100644 scripts/romload/hex8tohex32.py create mode 100644 scripts/romload/map2debug.py create mode 100644 scripts/romload/sections.lds create mode 100644 scripts/romload/start.S create mode 100644 scripts/romload/syscalls.c create mode 100644 scripts/romload/testbench.v diff --git a/scripts/romload/firmware.c b/scripts/romload/firmware.c new file mode 100644 index 0000000..72bb9a1 --- /dev/null +++ b/scripts/romload/firmware.c @@ -0,0 +1,21 @@ +#include +#include + +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); +} + diff --git a/scripts/romload/hex8tohex32.py b/scripts/romload/hex8tohex32.py new file mode 100644 index 0000000..ae44101 --- /dev/null +++ b/scripts/romload/hex8tohex32.py @@ -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() + diff --git a/scripts/romload/map2debug.py b/scripts/romload/map2debug.py new file mode 100644 index 0000000..a79af05 --- /dev/null +++ b/scripts/romload/map2debug.py @@ -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)) + diff --git a/scripts/romload/sections.lds b/scripts/romload/sections.lds new file mode 100644 index 0000000..ea99ad2 --- /dev/null +++ b/scripts/romload/sections.lds @@ -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 + +} diff --git a/scripts/romload/start.S b/scripts/romload/start.S new file mode 100644 index 0000000..73e4ba3 --- /dev/null +++ b/scripts/romload/start.S @@ -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 diff --git a/scripts/romload/syscalls.c b/scripts/romload/syscalls.c new file mode 100644 index 0000000..82e633b --- /dev/null +++ b/scripts/romload/syscalls.c @@ -0,0 +1,95 @@ +// An extremely minimalist syscalls.c for newlib +// Based on riscv newlib libgloss/riscv/sys_*.c +// Written by Clifford Wolf. + +#include +#include +#include + +#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(); +} + diff --git a/scripts/romload/testbench.v b/scripts/romload/testbench.v new file mode 100644 index 0000000..1e852cc --- /dev/null +++ b/scripts/romload/testbench.v @@ -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