Add scripts/presyn/ example

This commit is contained in:
Clifford Wolf 2017-02-09 15:15:46 +01:00
parent a2107ed4ff
commit 42b4397390
9 changed files with 237 additions and 0 deletions

7
scripts/presyn/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
firmware.bin
firmware.elf
firmware.hex
firmware.map
picorv32_presyn.v
testbench.vcd
testbench.vvp

22
scripts/presyn/Makefile Normal file
View File

@ -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

5
scripts/presyn/README Normal file
View File

@ -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

47
scripts/presyn/firmware.S Normal file
View File

@ -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

43
scripts/presyn/firmware.c Normal file
View File

@ -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);
}

View File

@ -0,0 +1,11 @@
SECTIONS {
.memory : {
. = 0x000000;
*(.init);
*(.text);
*(*);
. = ALIGN(4);
end = .;
}
}

View File

@ -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

View File

@ -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

View File

@ -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