aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2017-02-09 15:15:46 +0100
committerClifford Wolf <clifford@clifford.at>2017-02-09 15:15:46 +0100
commit42b4397390aba11ae79d761a7317ebda9da489f4 (patch)
treef12536f2e6d79ec48c28118b448e263d68ad06aa /scripts
parenta2107ed4ffa72b48a15c67459adf8fbe576cbcab (diff)
downloadpicorv32-42b4397390aba11ae79d761a7317ebda9da489f4.tar.gz
picorv32-42b4397390aba11ae79d761a7317ebda9da489f4.zip
Add scripts/presyn/ example
Diffstat (limited to 'scripts')
-rw-r--r--scripts/presyn/.gitignore7
-rw-r--r--scripts/presyn/Makefile22
-rw-r--r--scripts/presyn/README5
-rw-r--r--scripts/presyn/firmware.S47
-rw-r--r--scripts/presyn/firmware.c43
-rw-r--r--scripts/presyn/firmware.lds11
-rw-r--r--scripts/presyn/picorv32_presyn.ys5
-rw-r--r--scripts/presyn/picorv32_regs.txt16
-rw-r--r--scripts/presyn/testbench.v81
9 files changed, 237 insertions, 0 deletions
diff --git a/scripts/presyn/.gitignore b/scripts/presyn/.gitignore
new file mode 100644
index 0000000..4281b17
--- /dev/null
+++ b/scripts/presyn/.gitignore
@@ -0,0 +1,7 @@
+firmware.bin
+firmware.elf
+firmware.hex
+firmware.map
+picorv32_presyn.v
+testbench.vcd
+testbench.vvp
diff --git a/scripts/presyn/Makefile b/scripts/presyn/Makefile
new file mode 100644
index 0000000..d1c367e
--- /dev/null
+++ b/scripts/presyn/Makefile
@@ -0,0 +1,22 @@
+
+TOOLCHAIN_PREFIX = /opt/riscv32ic/bin/riscv32-unknown-elf-
+
+run: testbench.vvp firmware.hex
+ vvp -N testbench.vvp
+
+firmware.hex: firmware.S firmware.c firmware.lds
+ $(TOOLCHAIN_PREFIX)gcc -Os -ffreestanding -nostdlib -o firmware.elf firmware.S firmware.c \
+ --std=gnu99 -Wl,-Bstatic,-T,firmware.lds,-Map,firmware.map,--strip-debug -lgcc
+ $(TOOLCHAIN_PREFIX)objcopy -O binary firmware.elf firmware.bin
+ python3 ../../firmware/makehex.py firmware.bin 4096 > firmware.hex
+
+picorv32_presyn.v: picorv32_presyn.ys picorv32_regs.txt ../../picorv32.v
+ yosys -v0 picorv32_presyn.ys
+
+testbench.vvp: testbench.v picorv32_presyn.v
+ iverilog -o testbench.vvp testbench.v picorv32_presyn.v
+
+clean:
+ rm -f firmware.bin firmware.elf firmware.hex firmware.map
+ rm -f picorv32_presyn.v testbench.vvp testbench.vcd
+
diff --git a/scripts/presyn/README b/scripts/presyn/README
new file mode 100644
index 0000000..14aea33
--- /dev/null
+++ b/scripts/presyn/README
@@ -0,0 +1,5 @@
+A simple example for how to use Yosys to "pre-synthesize" PicoRV32 in
+a way that can utilize an external memory module for the register file.
+
+See also:
+https://github.com/cliffordwolf/picorv32/issues/30
diff --git a/scripts/presyn/firmware.S b/scripts/presyn/firmware.S
new file mode 100644
index 0000000..ec5caaa
--- /dev/null
+++ b/scripts/presyn/firmware.S
@@ -0,0 +1,47 @@
+.section .init
+.global main
+
+entry:
+
+/* 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(16*1024)
+addi sp, sp, %lo(16*1024)
+
+/* call main */
+jal ra, main
+
+/* break */
+ebreak
diff --git a/scripts/presyn/firmware.c b/scripts/presyn/firmware.c
new file mode 100644
index 0000000..6c62169
--- /dev/null
+++ b/scripts/presyn/firmware.c
@@ -0,0 +1,43 @@
+void putc(char c)
+{
+ *(volatile char*)0x10000000 = c;
+}
+
+void puts(const char *s)
+{
+ while (*s) putc(*s++);
+}
+
+void *memcpy(void *dest, const void *src, int n)
+{
+ while (n) {
+ n--;
+ ((char*)dest)[n] = ((char*)src)[n];
+ }
+ return dest;
+}
+
+void main()
+{
+ char message[] = "$Uryyb+Jbeyq!+Vs+lbh+pna+ernq+guvf+zrffntr+gura$gur+CvpbEI32+PCH"
+ "+frrzf+gb+or+jbexvat+whfg+svar.$$++++++++++++++++GRFG+CNFFRQ!$$";
+ for (int i = 0; message[i]; i++)
+ switch (message[i])
+ {
+ case 'a' ... 'm':
+ case 'A' ... 'M':
+ message[i] += 13;
+ break;
+ case 'n' ... 'z':
+ case 'N' ... 'Z':
+ message[i] -= 13;
+ break;
+ case '$':
+ message[i] = '\n';
+ break;
+ case '+':
+ message[i] = ' ';
+ break;
+ }
+ puts(message);
+}
diff --git a/scripts/presyn/firmware.lds b/scripts/presyn/firmware.lds
new file mode 100644
index 0000000..970000a
--- /dev/null
+++ b/scripts/presyn/firmware.lds
@@ -0,0 +1,11 @@
+SECTIONS {
+ .memory : {
+ . = 0x000000;
+ *(.init);
+ *(.text);
+ *(*);
+ . = ALIGN(4);
+ end = .;
+ }
+}
+
diff --git a/scripts/presyn/picorv32_presyn.ys b/scripts/presyn/picorv32_presyn.ys
new file mode 100644
index 0000000..5855a21
--- /dev/null
+++ b/scripts/presyn/picorv32_presyn.ys
@@ -0,0 +1,5 @@
+read_verilog ../../picorv32.v
+chparam -set COMPRESSED_ISA 1 picorv32
+prep -top picorv32
+memory_bram -rules picorv32_regs.txt
+write_verilog -noattr picorv32_presyn.v
diff --git a/scripts/presyn/picorv32_regs.txt b/scripts/presyn/picorv32_regs.txt
new file mode 100644
index 0000000..1cfbbeb
--- /dev/null
+++ b/scripts/presyn/picorv32_regs.txt
@@ -0,0 +1,16 @@
+bram picorv32_regs
+ init 0
+ abits 5
+ dbits 32
+ groups 2
+ ports 2 1
+ wrmode 0 1
+ enable 0 1
+ transp 0 0
+ clocks 1 1
+ clkpol 1 1
+endbram
+
+match picorv32_regs
+ make_transp
+endmatch
diff --git a/scripts/presyn/testbench.v b/scripts/presyn/testbench.v
new file mode 100644
index 0000000..59ff66b
--- /dev/null
+++ b/scripts/presyn/testbench.v
@@ -0,0 +1,81 @@
+module testbench;
+ reg clk = 1;
+ always #5 clk = ~clk;
+
+ reg resetn = 0;
+ always @(posedge clk) resetn <= 1;
+
+ wire trap;
+ 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;
+
+ picorv32 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)
+ );
+
+ // 4096 32bit words = 16kB memory
+ localparam MEM_SIZE = 4096;
+
+ reg [31:0] memory [0:MEM_SIZE-1];
+ initial $readmemh("firmware.hex", memory);
+
+ always @(posedge clk) begin
+ mem_ready <= 0;
+ mem_rdata <= 'bx;
+
+ if (resetn && mem_valid && !mem_ready) begin
+ mem_ready <= 1;
+ if (mem_wstrb) begin
+ if (mem_addr == 32'h1000_0000) begin
+ $write("%c", mem_wdata[7:0]);
+ $fflush;
+ end else 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
+ end else begin
+ mem_rdata <= memory[mem_addr >> 2];
+ end
+ end
+
+ if (resetn && trap) begin
+ $display("TRAP.");
+ $finish;
+ end
+ end
+
+ initial begin
+ $dumpfile("testbench.vcd");
+ $dumpvars(0, testbench);
+ end
+endmodule
+
+module picorv32_regs (
+ input [4:0] A1ADDR, A2ADDR, B1ADDR,
+ output reg [31:0] A1DATA, A2DATA,
+ input [31:0] B1DATA,
+ input B1EN, CLK1
+);
+ reg [31:0] memory [0:31];
+ always @(posedge CLK1) begin
+ A1DATA <= memory[A1ADDR];
+ A2DATA <= memory[A2ADDR];
+ if (B1EN) memory[B1ADDR] <= B1DATA;
+ end
+endmodule