Add scripts/presyn/ example
This commit is contained in:
parent
a2107ed4ff
commit
42b4397390
|
@ -0,0 +1,7 @@
|
||||||
|
firmware.bin
|
||||||
|
firmware.elf
|
||||||
|
firmware.hex
|
||||||
|
firmware.map
|
||||||
|
picorv32_presyn.v
|
||||||
|
testbench.vcd
|
||||||
|
testbench.vvp
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
SECTIONS {
|
||||||
|
.memory : {
|
||||||
|
. = 0x000000;
|
||||||
|
*(.init);
|
||||||
|
*(.text);
|
||||||
|
*(*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
end = .;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue