Compare commits
	
		
			2 commits
		
	
	
		
			6b0eea8295
			...
			57aa849615
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 57aa849615 | |||
| d477252bde | 
					 3 changed files with 140 additions and 0 deletions
				
			
		| 
						 | 
					@ -50,4 +50,5 @@ pub mod ty;
 | 
				
			||||||
pub mod util;
 | 
					pub mod util;
 | 
				
			||||||
//pub mod valueless;
 | 
					//pub mod valueless;
 | 
				
			||||||
pub mod prelude;
 | 
					pub mod prelude;
 | 
				
			||||||
 | 
					pub mod testing;
 | 
				
			||||||
pub mod wire;
 | 
					pub mod wire;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										36
									
								
								crates/fayalite/src/testing.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								crates/fayalite/src/testing.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,36 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: LGPL-3.0-or-later
 | 
				
			||||||
 | 
					// See Notices.txt for copyright information
 | 
				
			||||||
 | 
					use crate::{
 | 
				
			||||||
 | 
					    cli::{FormalArgs, FormalMode, FormalOutput, RunPhase},
 | 
				
			||||||
 | 
					    firrtl::ExportOptions,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					use clap::Parser;
 | 
				
			||||||
 | 
					use std::sync::OnceLock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn assert_formal_helper() -> FormalArgs {
 | 
				
			||||||
 | 
					    static FORMAL_ARGS: OnceLock<FormalArgs> = OnceLock::new();
 | 
				
			||||||
 | 
					    // ensure we only run parsing once, so errors from env vars don't produce overlapping output if we're called on multiple threads
 | 
				
			||||||
 | 
					    FORMAL_ARGS
 | 
				
			||||||
 | 
					        .get_or_init(|| FormalArgs::parse_from(["fayalite::testing::assert_formal"]))
 | 
				
			||||||
 | 
					        .clone()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[track_caller]
 | 
				
			||||||
 | 
					pub fn assert_formal<M>(
 | 
				
			||||||
 | 
					    module: M,
 | 
				
			||||||
 | 
					    mode: FormalMode,
 | 
				
			||||||
 | 
					    depth: u64,
 | 
				
			||||||
 | 
					    solver: Option<&str>,
 | 
				
			||||||
 | 
					    export_options: ExportOptions,
 | 
				
			||||||
 | 
					) where
 | 
				
			||||||
 | 
					    FormalArgs: RunPhase<M, Output = FormalOutput>,
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    let mut args = assert_formal_helper();
 | 
				
			||||||
 | 
					    args.verilog.firrtl.base.redirect_output_for_rust_test = true;
 | 
				
			||||||
 | 
					    args.verilog.firrtl.export_options = export_options;
 | 
				
			||||||
 | 
					    args.verilog.debug = true;
 | 
				
			||||||
 | 
					    args.mode = mode;
 | 
				
			||||||
 | 
					    args.depth = depth;
 | 
				
			||||||
 | 
					    args.solver = solver.map(String::from);
 | 
				
			||||||
 | 
					    args.run(module).expect("testing::assert_formal() failed");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -162,3 +162,106 @@ pub fn queue<T: Type>(
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(todo)]
 | 
				
			||||||
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
					mod tests {
 | 
				
			||||||
 | 
					    use super::*;
 | 
				
			||||||
 | 
					    use crate::{
 | 
				
			||||||
 | 
					        cli::FormalMode, firrtl::ExportOptions,
 | 
				
			||||||
 | 
					        module::transform::simplify_enums::SimplifyEnumsKind, testing::assert_formal,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn test_queue() {
 | 
				
			||||||
 | 
					        #[hdl_module]
 | 
				
			||||||
 | 
					        fn queue_test(capacity: NonZeroUsize, inp_ready_is_comb: bool, out_valid_is_comb: bool) {
 | 
				
			||||||
 | 
					            #[hdl]
 | 
				
			||||||
 | 
					            let clk: Clock = m.input();
 | 
				
			||||||
 | 
					            #[hdl]
 | 
				
			||||||
 | 
					            let rst: SyncReset = m.input();
 | 
				
			||||||
 | 
					            #[hdl]
 | 
				
			||||||
 | 
					            let inp_data: HdlOption<UInt<8>> = m.input();
 | 
				
			||||||
 | 
					            #[hdl]
 | 
				
			||||||
 | 
					            let out_ready: Bool = m.input();
 | 
				
			||||||
 | 
					            #[hdl]
 | 
				
			||||||
 | 
					            let cd = wire();
 | 
				
			||||||
 | 
					            connect(
 | 
				
			||||||
 | 
					                cd,
 | 
				
			||||||
 | 
					                #[hdl]
 | 
				
			||||||
 | 
					                ClockDomain {
 | 
				
			||||||
 | 
					                    clk,
 | 
				
			||||||
 | 
					                    rst: rst.to_reset(),
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            #[hdl]
 | 
				
			||||||
 | 
					            let dut = instance(queue(
 | 
				
			||||||
 | 
					                UInt[ConstUsize::<8>],
 | 
				
			||||||
 | 
					                capacity,
 | 
				
			||||||
 | 
					                inp_ready_is_comb,
 | 
				
			||||||
 | 
					                out_valid_is_comb,
 | 
				
			||||||
 | 
					            ));
 | 
				
			||||||
 | 
					            connect(dut.cd, cd);
 | 
				
			||||||
 | 
					            connect(dut.inp.data, inp_data);
 | 
				
			||||||
 | 
					            connect(dut.out.ready, out_ready);
 | 
				
			||||||
 | 
					            #[hdl]
 | 
				
			||||||
 | 
					            let count = reg_builder().clock_domain(cd).reset(0u32);
 | 
				
			||||||
 | 
					            #[hdl]
 | 
				
			||||||
 | 
					            let next_count = wire();
 | 
				
			||||||
 | 
					            connect(next_count, count);
 | 
				
			||||||
 | 
					            connect(count, next_count);
 | 
				
			||||||
 | 
					            #[hdl]
 | 
				
			||||||
 | 
					            if ReadyValid::fire(dut.inp) & !ReadyValid::fire(dut.out) {
 | 
				
			||||||
 | 
					                connect_any(next_count, count + 1u8);
 | 
				
			||||||
 | 
					            } else if !ReadyValid::fire(dut.inp) & ReadyValid::fire(dut.out) {
 | 
				
			||||||
 | 
					                connect_any(next_count, count - 1u8);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            hdl_assert(clk, count.cmp_eq(dut.count), "");
 | 
				
			||||||
 | 
					            #[hdl]
 | 
				
			||||||
 | 
					            let index = reg_builder().clock_domain(cd).reset(HdlNone::<UInt<32>>());
 | 
				
			||||||
 | 
					            #[hdl]
 | 
				
			||||||
 | 
					            let data = reg_builder().clock_domain(cd).reset(HdlNone());
 | 
				
			||||||
 | 
					            #[hdl]
 | 
				
			||||||
 | 
					            match index {
 | 
				
			||||||
 | 
					                HdlNone =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    #[hdl]
 | 
				
			||||||
 | 
					                    if ReadyValid::fire(dut.inp) {
 | 
				
			||||||
 | 
					                        connect(index, HdlSome(0u32));
 | 
				
			||||||
 | 
					                        connect(data, dut.inp.data);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                HdlSome(cur_index) =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    #[hdl]
 | 
				
			||||||
 | 
					                    if cur_index.cmp_ge(next_count) {
 | 
				
			||||||
 | 
					                        connect(index, HdlNone());
 | 
				
			||||||
 | 
					                        #[hdl]
 | 
				
			||||||
 | 
					                        if let HdlSome(data) = data {
 | 
				
			||||||
 | 
					                            #[hdl]
 | 
				
			||||||
 | 
					                            if let HdlSome(out_data) = dut.out.data {
 | 
				
			||||||
 | 
					                                hdl_assert(clk, data.cmp_eq(out_data), "");
 | 
				
			||||||
 | 
					                            } else {
 | 
				
			||||||
 | 
					                                hdl_assert(clk, false.to_expr(), "");
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            hdl_assert(clk, false.to_expr(), "");
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        connect(index, HdlSome((cur_index + 1u8).cast_to_static()));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        assert_formal(
 | 
				
			||||||
 | 
					            queue_test(NonZeroUsize::new(2).unwrap(), false, false),
 | 
				
			||||||
 | 
					            FormalMode::BMC,
 | 
				
			||||||
 | 
					            20,
 | 
				
			||||||
 | 
					            None,
 | 
				
			||||||
 | 
					            ExportOptions {
 | 
				
			||||||
 | 
					                simplify_enums: Some(SimplifyEnumsKind::ReplaceWithBundleOfUInts),
 | 
				
			||||||
 | 
					                ..ExportOptions::default()
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue