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