Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Testing

Models can be tested using the build_model_harness! macro. This wraps a model with a simple test harness that drives and expects objects that implement the AccessMemory trait. The model harness uses the same harness DSL and generated API as build_component_harness!, but uses MemoryTxn to check objects coming out of the model.

MemoryTxn lets tests match only the memory access fields that matter for a scenario. For example, this test harness checks that a Memory model produces a read response for the expected destination address, while ignoring fields that are not specified:

#![allow(unused)]
fn main() {
mod memory_harness {
    use std::rc::Rc;

    use gwr_engine::test_helpers::start_test;
    use gwr_models::build_model_harness;
    use gwr_models::memory::memory_access::MemoryAccess;
    use gwr_models::memory::{Memory, MemoryConfig};
    use gwr_models::test_helpers::{MemoryTxn, create_default_memory_map, create_read};

    const DST_ADDR: u64 = 0x80000;
    const SRC_ADDR: u64 = 0x90000;
    const ACCESS_SIZE_BYTES: usize = 64;
    const OVERHEAD_SIZE_BYTES: usize = 8;

    build_model_harness! {
        harness MemoryHarness<T> {
            component: memory: Rc<Memory<T>>,
            rx ports: {
                Rx<T> => rx,
            },
            tx ports: {
                Tx<T> => tx,
            },
        }
    }

    #[test]
    fn model_harness_matches_selected_memory_fields() {
        let mut engine = start_test(file!());
        let clock = engine.default_clock();
        let config = MemoryConfig::new(DST_ADDR, 0x40000, 32, 1);
        let memory = Memory::<MemoryAccess>::new_and_register(
            &engine,
            &clock,
            engine.top(),
            "memory",
            config,
        )
        .unwrap();
        let memory_map = Rc::new(create_default_memory_map());
        let request = create_read(
            engine.top(),
            &memory_map,
            ACCESS_SIZE_BYTES,
            DST_ADDR,
            SRC_ADDR,
            OVERHEAD_SIZE_BYTES,
        );
        let mut harness = MemoryHarness::new(engine, memory);

        harness.run_steps([
            send_rx!(request),
            expect_tx!(MemoryTxn::read_rsp(DST_ADDR)),
        ]);
    }
}
}

Use the component harness documentation for the shared syntax and execution model.