mirror of
				https://github.com/YosysHQ/sby.git
				synced 2025-10-30 20:42:30 +00:00 
			
		
		
		
	
						commit
						0395b8a439
					
				
					 3 changed files with 139 additions and 0 deletions
				
			
		
							
								
								
									
										30
									
								
								docs/examples/autotune/README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								docs/examples/autotune/README.md
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | ||||||
|  | # Autotune demo | ||||||
|  | 
 | ||||||
|  | This directory contains a simple sequential integer divider circuit. The | ||||||
|  | verilog implementation in [divider.sv](divider.sv) comes with assertions that | ||||||
|  | this circuit will always produce the correct result and will always finish | ||||||
|  | within a fixed number of cycles. The circuit has the divider bit-width as | ||||||
|  | parameter. | ||||||
|  | 
 | ||||||
|  | Increasing the WIDTH parameter quickly turns proving those assertions into a | ||||||
|  | very difficult proof for fully autmated solvers. This makes it a good example | ||||||
|  | for the `--autotune` option which tries different backend engines to find the | ||||||
|  | best performing engine configuration for a given verification task. | ||||||
|  | 
 | ||||||
|  | The [divider.sby](divider.sby) file defines 3 tasks named `small`, `medium` and | ||||||
|  | `large` which configure the divider with different bit-widths. To verify the | ||||||
|  | `small` divider using the default engine run: | ||||||
|  | 
 | ||||||
|  |     sby -f divider.sby small | ||||||
|  | 
 | ||||||
|  | To automatically try different backend engines using autotune, run | ||||||
|  | 
 | ||||||
|  |     sby --autotune -f divider.sby small | ||||||
|  | 
 | ||||||
|  | The `small` task should finish quickly using both the default engine and using | ||||||
|  | autotune. The `medium` and `large` tasks take significantly longer and show | ||||||
|  | greater differences between engine configurations. Note that the `large` tasks | ||||||
|  | can take many minutes to hours, depending on the machine you are using. | ||||||
|  | 
 | ||||||
|  | You can learn more about Sby's autotune feature from [Sby's | ||||||
|  | documentation](https://symbiyosys.readthedocs.io/en/latest/autotune.html). | ||||||
							
								
								
									
										24
									
								
								docs/examples/autotune/divider.sby
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								docs/examples/autotune/divider.sby
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | ||||||
|  | [tasks] | ||||||
|  | small default | ||||||
|  | medium | ||||||
|  | large | ||||||
|  | 
 | ||||||
|  | [options] | ||||||
|  | mode prove | ||||||
|  | small: depth 11 | ||||||
|  | medium: depth 15 | ||||||
|  | large: depth 19 | ||||||
|  | 
 | ||||||
|  | [engines] | ||||||
|  | smtbmc | ||||||
|  | 
 | ||||||
|  | [script] | ||||||
|  | small: read -define WIDTH=8 | ||||||
|  | medium: read -define WIDTH=12 | ||||||
|  | large: read -define WIDTH=16 | ||||||
|  | 
 | ||||||
|  | read -formal divider.sv | ||||||
|  | prep -top divider | ||||||
|  | 
 | ||||||
|  | [files] | ||||||
|  | divider.sv | ||||||
							
								
								
									
										85
									
								
								docs/examples/autotune/divider.sv
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								docs/examples/autotune/divider.sv
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,85 @@ | ||||||
|  | `ifndef WIDTH | ||||||
|  | `define WIDTH 4 | ||||||
|  | `endif | ||||||
|  | 
 | ||||||
|  | module divider #( | ||||||
|  |     parameter WIDTH=`WIDTH | ||||||
|  | ) ( | ||||||
|  |     input wire clk, | ||||||
|  |     input wire start, | ||||||
|  |     input wire [WIDTH-1:0] dividend, | ||||||
|  |     input wire [WIDTH-1:0] divisor, | ||||||
|  | 
 | ||||||
|  |     output reg done, | ||||||
|  |     output reg [WIDTH-1:0] quotient, | ||||||
|  |     output wire [WIDTH-1:0] remainder | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  |     reg [WIDTH-1:0] acc; | ||||||
|  | 
 | ||||||
|  |     reg [WIDTH*2-1:0] sub; | ||||||
|  |     reg [WIDTH-1:0] pos; | ||||||
|  | 
 | ||||||
|  |     assign remainder = acc; | ||||||
|  | 
 | ||||||
|  |     always @(posedge clk) begin | ||||||
|  |         if (start) begin | ||||||
|  |             acc <= dividend; | ||||||
|  |             quotient <= 0; | ||||||
|  |             sub <= divisor << (WIDTH - 1); | ||||||
|  |             pos <= 1 << (WIDTH - 1); | ||||||
|  |             done <= 0; | ||||||
|  |         end else if (!done) begin | ||||||
|  |             if (acc >= sub) begin | ||||||
|  |                 acc <= acc - sub[WIDTH-1:0]; | ||||||
|  |                 quotient <= quotient + pos; | ||||||
|  |             end | ||||||
|  | 
 | ||||||
|  |             sub <= sub >> 1; | ||||||
|  |             {pos, done} <= pos; | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | `ifdef FORMAL | ||||||
|  |     reg [WIDTH-1:0] start_dividend = 0; | ||||||
|  |     reg [WIDTH-1:0] start_divisor = 0; | ||||||
|  | 
 | ||||||
|  |     reg started = 0; | ||||||
|  |     reg finished = 0; | ||||||
|  |     reg [$clog2(WIDTH + 1):0] counter = 0; | ||||||
|  | 
 | ||||||
|  |     always @(posedge clk) begin | ||||||
|  |         // Bound the number of cycles until the result is ready
 | ||||||
|  |         assert (counter <= WIDTH); | ||||||
|  | 
 | ||||||
|  |         if (started) begin | ||||||
|  |             if (finished || done) begin | ||||||
|  |                 finished <= 1; | ||||||
|  |                 // Make sure result stays until we start a new division
 | ||||||
|  |                 assert (done); | ||||||
|  | 
 | ||||||
|  |                 // Check the result
 | ||||||
|  |                 if (start_divisor == 0) begin | ||||||
|  |                     assert ("ient); | ||||||
|  |                     assert (remainder == start_dividend); | ||||||
|  |                 end else begin | ||||||
|  |                     assert (quotient == start_dividend / start_divisor); | ||||||
|  |                     assert (remainder == start_dividend % start_divisor); | ||||||
|  |                 end | ||||||
|  |             end else begin | ||||||
|  |                 counter <= counter + 1'b1; | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  |         // Track the requested inputs
 | ||||||
|  |         if (start) begin | ||||||
|  |             start_divisor <= divisor; | ||||||
|  |             start_dividend <= dividend; | ||||||
|  |             started <= 1; | ||||||
|  |             counter <= 0; | ||||||
|  |             finished <= 0; | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  | `endif | ||||||
|  | endmodule | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue