diff --git a/.gitignore b/.gitignore index a27c3f24..a3b4ff2b 100755 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,8 @@ log/ /test_apps/**/.session rls/ .pytest_cache +.cline_storage/ + # pyenv .python-version diff --git a/python/origen/origen/producer.py b/python/origen/origen/producer.py index c4e1abc9..1f832803 100644 --- a/python/origen/origen/producer.py +++ b/python/origen/origen/producer.py @@ -159,6 +159,9 @@ def Flow(self, **kwargs): flow_refs = _origen_metal.prog_gen.start_new_flow(flow.name, **options) origen.interface.top_level_options = kwargs + if "namespace" in kwargs: + _origen_metal.prog_gen.set_namespace(kwargs["namespace"]) + #origen.tester.reset() #origen.target.reload() #origen.tester.clear_dut_dependencies(ast_name=flow.name) diff --git a/rust/origen/src/core/tester.rs b/rust/origen/src/core/tester.rs index 0d2fa58e..a74d5561 100644 --- a/rust/origen/src/core/tester.rs +++ b/rust/origen/src/core/tester.rs @@ -23,6 +23,7 @@ use std::collections::HashSet; use std::env; use std::io::Write; use std::path::{Path, PathBuf}; +use std::process::Command; #[macro_export] macro_rules! push_pin_actions { @@ -31,6 +32,40 @@ macro_rules! push_pin_actions { }}; } +/// When running on GitHub Actions, this function runs a diff command +/// to show the differences in the CI log. Does nothing otherwise. +fn display_diff_on_ci(old_path: &Path, new_path: &Path) { + if env::var("GITHUB_ACTIONS").map(|v| v == "true").unwrap_or(false) { + println!("Running diff for GitHub Actions CI:"); + match Command::new("diff") + .arg("-u") + .arg(old_path) + .arg(new_path) + .output() + { + Ok(output) => { + if !output.stdout.is_empty() { + println!("--- Diff Output ---"); + if let Ok(stdout) = String::from_utf8(output.stdout) { + for line in stdout.lines() { + println!("{}", line); + } + } + println!("--- End Diff ---"); + } + if !output.stderr.is_empty() { + if let Ok(stderr) = String::from_utf8(output.stderr) { + eprintln!("Diff stderr: {}", stderr); + } + } + } + Err(e) => { + eprintln!("Failed to run diff command: {}", e); + } + } + } +} + #[macro_export] macro_rules! text { ($txt:expr) => {{ @@ -523,6 +558,7 @@ impl Tester { } self.stats.changed_pattern_files += 1; display_redln!("Diffs found"); + display_diff_on_ci(&ref_pat, &path); let old = to_relative_path(&ref_pat, None) .unwrap_or(ref_pat); let new = to_relative_path(&path, None) @@ -620,6 +656,7 @@ impl Tester { } self.stats.changed_program_files += 1; display_redln!("Diffs found"); + display_diff_on_ci(&ref_pat, &path); let old = to_relative_path(&ref_pat, None) .unwrap_or(ref_pat); let new = to_relative_path(&path, None) @@ -689,46 +726,52 @@ impl Tester { display!("Created: {}", list.display()); } if let Some(ref_dir) = crate::STATUS.reference_dir() { - let ref_list = ref_dir.join("referenced.list"); - display!(" - "); - if ref_list.exists() { - let mut differ = ASCIIDiffer::new(&ref_list, &list); - differ.ignore_comments("#")?; - if differ.has_diffs()? { - if let Err(e) = reference_files::create_changed_ref( - Path::new("referenced.list"), - &list, - &ref_list, - ) { - log_error!("{}", e); + match list.strip_prefix(crate::STATUS.output_dir()) { + Err(e) => log_error!("{}", e), + Ok(stem) => { + let ref_list = ref_dir.join(&stem); + display!(" - "); + if ref_list.exists() { + let mut differ = ASCIIDiffer::new(&ref_list, &list); + differ.ignore_comments("#")?; + if differ.has_diffs()? { + if let Err(e) = reference_files::create_changed_ref( + Path::new("referenced.list"), + &list, + &ref_list, + ) { + log_error!("{}", e); + } + self.stats.changed_program_files += 1; + display_redln!("Diffs found"); + display_diff_on_ci(&ref_list, &list); + let old = to_relative_path(&ref_list, None).unwrap_or(ref_list); + let new = to_relative_path(&list, None).unwrap_or(list.to_owned()); + let diff_tool = std::env::var("ORIGEN_DIFF_TOOL") + .unwrap_or("tkdiff".to_string()); + displayln!( + " {} {} {} &", + &diff_tool, + old.display(), + new.display() + ); + display!(" origen save_ref referenced.list"); + } else { + display_green!("No diffs"); + } + } else { + self.stats.new_program_files += 1; + if let Err(e) = reference_files::create_new_ref( + Path::new("referenced.list"), + &list, + &ref_list, + ) { + log_error!("{}", e); + } + display_cyanln!("New file"); + display!(" origen save_ref referenced.list"); } - self.stats.changed_program_files += 1; - display_redln!("Diffs found"); - let old = to_relative_path(&ref_list, None).unwrap_or(ref_list); - let new = to_relative_path(&list, None).unwrap_or(list.to_owned()); - let diff_tool = std::env::var("ORIGEN_DIFF_TOOL") - .unwrap_or("tkdiff".to_string()); - displayln!( - " {} {} {} &", - &diff_tool, - old.display(), - new.display() - ); - display!(" origen save_ref referenced.list"); - } else { - display_green!("No diffs"); - } - } else { - self.stats.new_program_files += 1; - if let Err(e) = reference_files::create_new_ref( - Path::new("referenced.list"), - &list, - &ref_list, - ) { - log_error!("{}", e); } - display_cyanln!("New file"); - display!(" origen save_ref referenced.list"); } } displayln!(""); diff --git a/rust/origen/src/testers/mod.rs b/rust/origen/src/testers/mod.rs index abcd559b..f3a4bdc7 100644 --- a/rust/origen/src/testers/mod.rs +++ b/rust/origen/src/testers/mod.rs @@ -20,6 +20,7 @@ pub fn instantiate_tester(g: &SupportedTester) -> Result Ok(Box::new(smt::V93K_SMT7::default())), + SupportedTester::V93KSMT8 => Ok(Box::new(smt::V93K_SMT8::default())), SupportedTester::SIMULATOR => Ok(Box::new(simulator::Renderer::default())), SupportedTester::ULTRAFLEX => Ok(Box::new(igxl::UltraFlex::default())), SupportedTester::J750 => Ok(Box::new(igxl::j750::J750::default())), diff --git a/rust/origen/src/testers/smt/mod.rs b/rust/origen/src/testers/smt/mod.rs index afb693dc..69393156 100644 --- a/rust/origen/src/testers/smt/mod.rs +++ b/rust/origen/src/testers/smt/mod.rs @@ -1,3 +1,4 @@ pub mod v93k; pub use v93k::smt7::SMT7 as V93K_SMT7; +pub use v93k::smt8::SMT8 as V93K_SMT8; diff --git a/rust/origen/src/testers/smt/v93k/smt8/mod.rs b/rust/origen/src/testers/smt/v93k/smt8/mod.rs index 8b137891..b58bf54f 100644 --- a/rust/origen/src/testers/smt/v93k/smt8/mod.rs +++ b/rust/origen/src/testers/smt/v93k/smt8/mod.rs @@ -1 +1,106 @@ +use crate::core::tester::{Interceptor, TesterID}; +use crate::generator::PAT; +use crate::testers::vector_based::pattern_renderer::Renderer; +use crate::testers::vector_based::VectorBased; +use crate::testers::SupportedTester; +use origen_metal::prog_gen::SupportedTester as ProgGenSupportedTester; +use crate::{Result, DUT}; +use origen_metal::ast::{Node, Return}; + +#[derive(Debug, Clone)] +pub struct SMT8 {} + +impl Default for SMT8 { + fn default() -> Self { + Self {} + } +} + +impl TesterID for SMT8 { + fn id(&self) -> SupportedTester { + SupportedTester::V93KSMT8 + } + + fn id_prog_gen(&self) -> ProgGenSupportedTester { + ProgGenSupportedTester::V93KSMT8 + } +} + +// TODO: This has just been copied from the SMT7 impl to get program generation underway, it needs to be +// properly implemented for SMT8 pattern generation +impl VectorBased for SMT8 { + fn comment_str(&self) -> &str { + "#" + } + + fn file_ext(&self) -> &str { + "avc" + } + + fn print_vector( + &self, + renderer: &mut Renderer, + repeat: u32, + _compressable: bool, + ) -> Option> { + Some(Ok(format!( + "R{} {} {} # ;", + repeat, + { + match renderer.timeset_name() { + Ok(s) => s, + Err(e) => return Some(Err(e)), + } + }, + // The pin states should have been previously updated from the PinAction node, or just has default values + { + match renderer.render_states() { + Ok(s) => s, + Err(e) => return Some(Err(e)), + } + } + ))) + } + + fn print_pinlist(&self, renderer: &mut Renderer) -> Option> { + let dut = DUT.lock().unwrap(); + let pins = renderer.states(&dut).names().join(" "); + Some(Ok(format!("FORMAT {};", pins))) + } + + fn print_pattern_end(&self, _renderer: &mut Renderer) -> Option> { + Some(Ok("SQPG STOP;".to_string())) + } + + fn override_node( + &self, + renderer: &mut Renderer, + node: &Node, + ) -> Option>> { + match &node.attrs { + PAT::Capture(capture, _metadata) => { + if let Ok(ids) = capture.enabled_capture_pins() { + for pin in ids.iter() { + if let Some(_) = capture.symbol.as_ref() { + renderer + .capturing + .insert(Some(*pin), capture.symbol.clone()); + } else { + renderer.capturing.insert( + Some(*pin), + Some(crate::standards::actions::CAPTURE.to_string()), + ); + } + } + Some(Ok(Return::Unmodified)) + } else { + None + } + } + _ => None, + } + } +} + +impl Interceptor for SMT8 {} diff --git a/rust/origen_metal/.github/copilot-instructions.md b/rust/origen_metal/.github/copilot-instructions.md new file mode 100644 index 00000000..2102fc58 --- /dev/null +++ b/rust/origen_metal/.github/copilot-instructions.md @@ -0,0 +1,195 @@ +# Origen Metal - AI Agent Instructions + +## Project Overview + +**Origen Metal** is a bare-metal Rust library providing core APIs for semiconductor test program generation and STIL (Standard Test Interface Language) processing. It's designed as the foundation for the Origen SDK, supporting both pure Rust usage and optional Python bindings via PyO3. + +**Key Purpose**: Transform abstract test flow specifications into concrete test programs for multiple ATE (Automatic Test Equipment) platforms through AST-based processing pipelines. + +## Architecture + +### Core Design Pattern: AST Processing Pipeline + +The project centers on a powerful AST (Abstract Syntax Tree) processing system located in `src/ast/`: + +- **Node**: Generic tree structure where `T` implements the `Attrs` trait (auto-implemented for types that are Clone + PartialEq + Serialize + Display + Debug) +- **AST**: Builder API for constructing node trees with `push()`, `push_and_open()`, `close()` methods +- **Processor**: Trait defining transformation passes that return `Return` enum variants: + - `None`: Delete node + - `Unmodified`: Keep as-is (clone node and children without processing) + - `ProcessChildren`: Clone node, process children recursively + - `Replace(Node)`: Substitute entire node + - `Unwrap`: Flatten node, keeping children + - `Inline(Vec>)`: Replace with multiple nodes + - `InlineBoxed(Vec>>)`: Same but with boxed nodes + - `UnwrapWithProcessedChildren`: Unwrap and process children + - `InlineWithProcessedChildren(Vec>)`: Add nodes then process original children + - `ReplaceChildren(Vec>)`: Keep node, replace children + +**Example Pattern** (from `src/prog_gen/processors/flag_optimizer.rs`): +```rust +impl Processor for FlagOptimizer { + fn on_node(&mut self, node: &Node) -> Result> { + Ok(match &node.attrs { + PGM::SetFlag(flag, _, auto_generated) => { + // Transformation logic here + Return::None // Or other Return variant + } + _ => Return::ProcessChildren, + }) + } +} +``` + +### Program Generation (`src/prog_gen/`) + +Converts test flow ASTs into tester-specific outputs: + +- **PGM enum** (`nodes.rs`): Node attribute types for test flows (Flow, Test, Bin, Condition, etc.) +- **FlowManager** (`flow_manager.rs`): Thread-safe RWLock wrapper managing flow ASTs + - Access via global `FLOW` static: `FLOW.push(node)`, `FLOW.with_flow(|ast| ...)` +- **Model** (`model/model.rs`): Extracted data structure from AST (tests, patterns, bins, variables) +- **Processor Chain**: Multi-pass transformations (flag optimization, condition nesting, tester-specific codegen) +- **Tester Targets**: `advantest/` (SMT7, SMT8) and `teradyne/` (J750, UltraFlex) implementations + +### Global State via lazy_static + +Key singletons in `src/lib.rs`: +```rust +lazy_static! { + pub static ref FLOW: FlowManager = FlowManager::new(); + pub static ref LOGGER: Logger = Logger::default(); + pub static ref USERS: RwLock = RwLock::new(Users::default()); + pub static ref SESSIONS: Mutex = Mutex::new(Sessions::new()); + pub static ref FRONTEND: RwLock = RwLock::new(Frontend::new()); +} +``` + +**Access Pattern**: Use `with_*` functions to safely interact with locked globals: +- `with_frontend(|f| f.method())` +- `with_current_user(|u| u.dataset())` +- `FLOW.with_flow(|ast| ast.push(node))` + +### STIL Processing (`src/stil/`) + +Parses and processes Standard Test Interface Language files: +- Parser built with Pest grammar (`stil.pest`) +- Includer processor resolves file dependencies +- Time expression processor for timing calculations + +### Framework Services (`src/framework/`) + +Supporting infrastructure: +- **Users**: Multi-user session management with dataset hierarchies, LDAP integration +- **Sessions**: Persistent key-value storage across runs +- **Logger**: Centralized logging via `LOGGER` global +- **TypedValue**: Heterogeneous value storage (String, Int, Vec, Map) + +### Frontend Abstraction (`src/frontend/`) + +Optional trait-based interface allowing higher-level frameworks to inject functionality: +```rust +pub trait FrontendAPI { + fn method(&self) -> Result; +} +``` +Set via `set_frontend(Box)`, access via `with_frontend()`. + +## Development Workflow + +### Building +```bash +cargo build # Pure Rust build +cargo build --features python # With Python bindings +``` + +The `build.rs` script generates `test_templates.rs` at compile time, embedding template files as a `phf::Map` for zero-cost template access. + +### Testing +```bash +cargo test # Run unit tests +cargo test --features origen_skip_frontend_tests # Skip frontend-dependent tests +``` + +Tests are colocated with code in `#[cfg(test)]` modules. See `src/utils/encryption.rs` and `src/utils/version.rs` for examples. + +### Key Macros + +- **`node!()`** (`src/macros.rs`): Ergonomic AST node construction with multiple forms: + ```rust + node!(PGM::Test, id, name) // Basic node with attrs + node!(PGM::Test, id, name => child1, child2) // With children + node!(PGM::Flow, name ; meta) // With metadata + node!(PGM::Nil) // No-arg variants + ``` +- **`bail!()`**: Early return with `Error` - expands to `return Err(error!(...))`. Use instead of `return Err(Error::new(...))` +- **`error!()`**: Construct `Error` from string/format args - `error!("msg")` or `error!("msg: {}", val)` +- **`trace!()`**: Wrap Results with AST node context for better error messages - used in `prog_gen` module +- **`display!()` / `displayln!()`**: Log output via `LOGGER` global - thread-safe display without println! + +## Critical Conventions + +1. **Error Handling**: Use `crate::Result` (alias for `std::result::Result`). Custom `Error` type in `src/error.rs` with conversions for git2, io, regex, PyO3 errors. + +2. **AST Modification**: Never directly manipulate `node.children` - always use the Processor API's `Return` variants. + +3. **Node Transformation Helpers**: Use these methods when implementing processors: + - `node.process_and_box_children(processor)` - Process children, returns `Vec>>` + - `node.updated(attrs, children, meta)` - Create modified copy with optional replacements (use `None` to keep existing) + - `node.without_children()` - Clone node without children for rebuilding + - Pattern: `Return::Replace(node.updated(None, Some(new_children), None))` + +4. **Template System**: Test templates loaded via `src/prog_gen/model/template_loader.rs` from embedded `TEST_TEMPLATES` map (generated by build script). + +5. **Tester-Specific Code**: Isolate in `advantest/` or `teradyne/` subdirectories. Common processors in `prog_gen/processors/`. + +6. **Feature Flag**: `#[cfg(feature = "python")]` gates PyO3 code. Library is Rust-first, Python-optional. + +7. **Indexmap Over HashMap**: Use `indexmap::IndexMap` for insertion-order preservation (critical for test flow ordering). + +8. **Processor Lifecycle**: Processors can implement three hooks: + - `on_node()` - Called before processing children (required, default: `ProcessChildren`) + - `on_end_of_block()` - Called after all children processed (optional, legacy) + - `on_processed_node()` - Called after children processed (optional, preferred over `on_end_of_block`) + +## Common Tasks + +**Add a new PGM node type**: +1. Extend `PGM` enum in `src/prog_gen/nodes.rs` +2. Update relevant processors to handle new variant +3. Add to tester-specific generators + +**Create a new processor**: +1. Define struct implementing `Processor` trait +2. Implement `on_node()` and optionally `on_processed_node()` (preferred) or `on_end_of_block()` (legacy) +3. Call via `node.process(&mut processor)?` + +**Access test flow**: +```rust +FLOW.with_flow(|ast| { + ast.push(node!(PGM::Test, id, name)); + Ok(()) +})?; +``` + +**Add global state**: +Use `lazy_static!` + RwLock/Mutex pattern, provide `with_*` accessor functions following existing conventions. + +**Build and test**: +```bash +cargo build # Pure Rust build +cargo build --features python # With Python bindings +cargo test # Run unit tests +cargo test --features origen_skip_frontend_tests # Skip frontend-dependent tests +``` + +## Project-Specific Knowledge + +- **FlowID**: Unique identifier for nodes that can be referenced (tests, groups). Used for on_passed/on_failed relationships. +- **ResourcesType**: Controls where tests appear (flow vs. resources-only sheets) +- **UniquenessOption**: Test name disambiguation strategies (Signature, Flowname, custom string) +- **Multi-pass Processing**: Processors often run 2+ times (count references, then optimize) - see `flag_optimizer.rs` + +## Dependencies Note + +Uses Rust 1.71.0 (2021 edition). Key crates: pest (parsing), pyo3 (Python), indexmap (ordered maps), lazy_static (globals), serde (serialization), tera/minijinja (templating). diff --git a/rust/origen_metal/src/ast/ast.rs b/rust/origen_metal/src/ast/ast.rs index 44e48f66..7f9e4a23 100644 --- a/rust/origen_metal/src/ast/ast.rs +++ b/rust/origen_metal/src/ast/ast.rs @@ -238,6 +238,11 @@ impl AST { } } + /// Writes the AST to the given file to allow it to be reviewed for debugging purposes + pub fn to_file>(&self, path: P) -> Result<()> { + self.to_node().to_file(path) + } + /// Clones the current state of the AST into a Node, leaving the AST unmodified pub fn to_node(&self) -> Node { let mut node = self.nodes.last().unwrap().clone(); diff --git a/rust/origen_metal/src/ast/node.rs b/rust/origen_metal/src/ast/node.rs index 287b7b4f..624ce340 100644 --- a/rust/origen_metal/src/ast/node.rs +++ b/rust/origen_metal/src/ast/node.rs @@ -4,6 +4,7 @@ use super::processors::ToString; use crate::ast::processor::{Processor, Return}; use crate::Result; use std::fmt::{self, Debug, Display}; +use std::io::Write; pub trait Attrs: Clone + std::cmp::PartialEq + serde::Serialize + Display + Debug {} impl Attrs for T {} @@ -316,6 +317,13 @@ impl Node { serde_pickle::to_vec(self, true).unwrap() } + /// Writes the AST to the given file to allow it to be reviewed for debugging purposes + pub fn to_file>(&self, path: P) -> Result<()> { + let mut f = std::fs::File::create(path)?; + writeln!(&mut f, "{:#?}", self)?; + Ok(()) + } + pub fn add_child(&mut self, node: Node) { self.children.push(Box::new(node)); } diff --git a/rust/origen_metal/src/prog_gen/advantest/smt7/processors/flow_generator.rs b/rust/origen_metal/src/prog_gen/advantest/smt7/processors/flow_generator.rs index 29d8148a..75471d47 100644 --- a/rust/origen_metal/src/prog_gen/advantest/smt7/processors/flow_generator.rs +++ b/rust/origen_metal/src/prog_gen/advantest/smt7/processors/flow_generator.rs @@ -1,3 +1,4 @@ +use crate::prog_gen::config::SMT7Config; use crate::prog_gen::{BinType, FlowCondition, GroupType, Model, ParamType, Test, PGM}; use crate::Result; use crate::ast::{Node, Processor, Return}; @@ -29,6 +30,7 @@ pub struct FlowGenerator { on_fails: Vec>, on_passes: Vec>, resources_block: bool, + options: SMT7Config } pub fn run(ast: &Node, output_dir: &Path, model: Model) -> Result<(Model, Vec)> { @@ -54,6 +56,7 @@ pub fn run(ast: &Node, output_dir: &Path, model: Model) -> Result<(Model, V on_fails: vec![], on_passes: vec![], resources_block: false, + options: crate::PROG_GEN_CONFIG.smt7_options(), }; let mut i = 0; @@ -267,9 +270,19 @@ impl Processor for FlowGenerator { writeln!(&mut f, "")?; for (name, id) in &self.test_methods { writeln!(&mut f, "{}:", name)?; - for (name, kind, value) in self.model.tests.get(id).unwrap().sorted_params() + let test = self.model.tests.get(id).unwrap(); + for (name, kind, value) in test.sorted_params() { if let Some(v) = value { + if !self.options.render_default_tmparams { + // Skip this if the value is the same as the default value for this parameter, to reduce clutter in the output file + let default_value = test.default_values.get(name); + if let Some(default_value) = default_value { + if default_value == v { + continue; + } + } + } match kind { ParamType::Voltage => { writeln!(&mut f, r#" "{}" = "{}[V]";"#, name, v)? @@ -627,7 +640,7 @@ impl Processor for FlowGenerator { } Return::ProcessChildren } - PGM::TestStr(name, _flow_id) => { + PGM::TestStr(name, _flow_id, _bin, _softbin, _number) => { if node .children .iter() diff --git a/rust/origen_metal/src/prog_gen/advantest/smt8/mod.rs b/rust/origen_metal/src/prog_gen/advantest/smt8/mod.rs index 8b137891..3f94710d 100644 --- a/rust/origen_metal/src/prog_gen/advantest/smt8/mod.rs +++ b/rust/origen_metal/src/prog_gen/advantest/smt8/mod.rs @@ -1 +1,37 @@ +pub(crate) mod processors; +use crate::prog_gen::supported_testers::SupportedTester; +use crate::prog_gen::{Model, process_flow}; +use crate::{Result, FLOW}; +use std::path::{Path, PathBuf}; + +/// Main entry point to render the current test program, paths to all files generated are returned +pub fn render(output_dir: &Path) -> Result<(Vec, Model)> { + let mut files = vec![]; + + let testflow_dir = output_dir.join("flows"); + if !testflow_dir.exists() { + std::fs::create_dir_all(&testflow_dir)?; + } + + let model = FLOW.with_all_flows(|flows| { + let mut model = Model::new(SupportedTester::V93KSMT8); + + for (name, flow) in flows { + log_debug!("Preparing flow '{}' for V93k SMT8", name); + let (ast, m) = process_flow(flow, model, SupportedTester::V93KSMT8, true)?; + + //////////////////////////////////////////////////////////////////////////////////////////////////////// + // Generate the flow and limits files + //////////////////////////////////////////////////////////////////////////////////////////////////////// + log_debug!("Rendering the main flow file '{}' for V93k SMT8", name); + let (m, mut new_files) = processors::flow_generator::run(&ast, &testflow_dir, m)?; + model = m; + files.append(&mut new_files); + } + + Ok(model) + })?; + + Ok((files, model)) +} \ No newline at end of file diff --git a/rust/origen_metal/src/prog_gen/advantest/smt8/processors/create_flow_data.rs b/rust/origen_metal/src/prog_gen/advantest/smt8/processors/create_flow_data.rs new file mode 100644 index 00000000..25da6280 --- /dev/null +++ b/rust/origen_metal/src/prog_gen/advantest/smt8/processors/create_flow_data.rs @@ -0,0 +1,308 @@ +//! Creates a flow data structure for each flow/subflow which summarizes its variable +//! usage (input and output variables) +use std::collections::HashSet; + +use crate::prog_gen::FlowCondition; +use crate::prog_gen::GroupType; +use crate::prog_gen::PGM; +use crate::ast::*; +use crate::Result; + +pub fn run(node: &Node) -> Result> { + let mut p = Collector { + ..Default::default() + }; + let mut node = node.process(&mut p)?.unwrap(); + + let mut p2 = PassthroughCollector { + ..Default::default() + }; + node = node.process(&mut p2)?.unwrap(); + + Ok(node) +} + +#[derive(Default, Serialize, Clone, Debug, PartialEq)] +pub struct FlowData { + pub references_job: bool, + pub referenced_flags: HashSet, + pub referenced_enables: HashSet, + pub input_job: bool, + pub input_flags: HashSet, + pub output_flags: HashSet, + pub input_enables: HashSet, + pub modified_flags: HashSet, + pub auto_flags: HashSet, + pub downstream_flags: HashSet, +} + +impl FlowData { + pub fn sorted_output_flags(&self) -> Vec { + let mut flags: Vec<_> = self.output_flags.iter().cloned().collect(); + flags.sort(); + flags + } + + pub fn sorted_input_flags(&self) -> Vec { + let mut flags: Vec<_> = self.input_flags.iter().cloned().collect(); + flags.sort(); + flags + } + + /// Returns a sorted list of all output and modified flags + pub fn sorted_modified_flags(&self) -> Vec { + let mut flags: HashSet = HashSet::new(); + for f in &self.output_flags { + flags.insert(f.to_string()); + } + for f in &self.modified_flags { + flags.insert(f.to_string()); + } + for f in &self.downstream_flags { + flags.insert(f.to_string()); + } + let mut flags_vec: Vec<_> = flags.into_iter().collect(); + flags_vec.sort(); + flags_vec + } + + /// Returns a sorted list of all input variables, including enables, flags, and job + pub fn sorted_input_vars(&self) -> Vec { + let mut vars: HashSet = HashSet::new(); + if self.input_job { + vars.insert("JOB".to_string()); + } + for f in &self.input_enables { + vars.insert(f.to_string()); + } + for f in &self.input_flags { + vars.insert(f.to_string()); + } + let mut vars_vec: Vec<_> = vars.into_iter().collect(); + vars_vec.sort(); + vars_vec + } +} + +#[derive(Default)] +pub struct Collector { + flows: Vec, + processing_subflow: bool, +} + +impl Processor for Collector { + fn on_node(&mut self, node: &Node) -> Result> { + match &node.attrs { + PGM::Flow(_) | PGM::SubFlow(_, _) => { + self.flows.push(FlowData { + ..Default::default() + }); + let orig = self.processing_subflow; + self.processing_subflow = true; + let n = node.process_and_update_children(self)?; + self.processing_subflow = orig; + return Ok(Return::Replace(n)); + } + PGM::Group(_, _, kind, _) => { + if kind == &GroupType::Flow { + self.flows.push(FlowData { + ..Default::default() + }); + } + let orig = self.processing_subflow; + self.processing_subflow = true; + let n = node.process_and_update_children(self)?; + self.processing_subflow = orig; + return Ok(Return::Replace(n)); + } + PGM::Test(_, _) | PGM::TestStr(_, _, _, _, _) => { + let orig = self.processing_subflow; + self.processing_subflow = false; + let n = node.process_and_update_children(self)?; + self.processing_subflow = orig; + return Ok(Return::Replace(n)); + } + PGM::OnFailed(_) | PGM::OnPassed(_) => { + // In this case, the contents of a flow-level on-passed/failed are actually implemented by the parent + // flow after executing it, so any flags set/referenced here should be applied to the parent flow + if self.processing_subflow { + let f = self.flows.pop().unwrap(); + let n = node.process_and_update_children(self)?; + self.flows.push(f); + return Ok(Return::Replace(n)); + } + } + PGM::SetFlag(flag, _state, is_auto_generated) => { + let flag = flag.to_uppercase(); + let current_flow = self.flows.last_mut().unwrap(); + if *is_auto_generated { + current_flow.auto_flags.insert(flag.clone()); + } + current_flow.modified_flags.insert(flag); + } + PGM::Condition(cond) => match cond { + FlowCondition::IfJob(_jobs) | FlowCondition::UnlessJob(_jobs) => { + self.flows.last_mut().unwrap().references_job = true; + } + FlowCondition::IfEnable(flags) | FlowCondition::UnlessEnable(flags) => { + for f in flags { + let flag = f.to_uppercase(); + self.flows.last_mut().unwrap().referenced_enables.insert(flag); + } + } + FlowCondition::IfFlag(flags) | FlowCondition::UnlessFlag(flags) => { + for f in flags { + let flag = f.to_uppercase(); + self.flows.last_mut().unwrap().referenced_flags.insert(flag); + } + } + _ => {} + }, + // For all other nodes + _ => {} + } + Ok(Return::ProcessChildren) + } + + fn on_processed_node(&mut self, node: &Node) -> Result> { + match &node.attrs { + PGM::Flow(_) | PGM::SubFlow(_, _) => { + let fdata = self.flows.pop().unwrap(); + let mut children = vec![Box::new(node!(PGM::FlowData, fdata))]; + children.extend(node.children.clone()); + Ok(Return::Replace(node.updated(None, Some(children), None))) + } + PGM::Group(_, _, kind, _) => { + if kind == &GroupType::Flow { + let fdata = self.flows.pop().unwrap(); + let mut children = vec![Box::new(node!(PGM::FlowData, fdata))]; + children.extend(node.children.clone()); + Ok(Return::Replace(node.updated(None, Some(children), None))) + } else { + Ok(Return::Unmodified) + } + } + _ => { + Ok(Return::Unmodified) + } + } + } +} + +#[derive(Default)] +pub struct PassthroughCollector { + flow_stack: Vec, +} + +impl Processor for PassthroughCollector { + fn on_node(&mut self, node: &Node) -> Result> { + match &node.attrs { + PGM::Flow(_) | PGM::SubFlow(_, _) => { + if let Some(first_child) = node.children.first() { + if let PGM::FlowData(fdata) = &first_child.attrs { + self.flow_stack.push(fdata.clone()); + } + } + } + PGM::Group(_, _, kind, _) => { + if kind == &GroupType::Flow { + if let Some(first_child) = node.children.first() { + if let PGM::FlowData(fdata) = &first_child.attrs { + self.flow_stack.push(fdata.clone()); + } + } + } + } + _ => {} + } + Ok(Return::ProcessChildren) + } + + fn on_processed_node(&mut self, node: &Node) -> Result> { + match &node.attrs { + PGM::Flow(_) | PGM::SubFlow(_, _) => { + let flow_data = self.finalize_flow_data(); + + let mut children = node.children.clone(); + children.remove(0); + children.insert(0, Box::new(node!(PGM::FlowData, flow_data))); + Ok(Return::Replace(node.updated(None, Some(children), None))) + } + PGM::Group(_, _, kind, _) => { + if kind == &GroupType::Flow { + let flow_data = self.finalize_flow_data(); + + let mut children = node.children.clone(); + children.remove(0); + children.insert(0, Box::new(node!(PGM::FlowData, flow_data))); + Ok(Return::Replace(node.updated(None, Some(children), None))) + } else { + Ok(Return::Unmodified) + } + } + _ => Ok(Return::Unmodified) + } + } +} + +impl PassthroughCollector { + fn finalize_flow_data(&mut self) -> FlowData{ + // Extract the FlowData from the first child + let mut flow_data = self.flow_stack.pop().unwrap(); + + if flow_data.references_job { + // Ensure every flow in the stack passses through job + flow_data.input_job = true; + for f in &mut self.flow_stack { + f.input_job = true; + } + } + for en in &flow_data.referenced_enables { + flow_data.input_enables.insert(en.to_string()); + // Ensure every flow in the stack passses through referenced enables + for f in &mut self.flow_stack { + f.input_enables.insert(en.to_string()); + } + } + // Make sure that all referenced flags that originate from an upstream flow are input + for fl in &flow_data.referenced_flags { + if flow_data.modified_flags.contains(fl) || flow_data.output_flags.contains(fl) || flow_data.downstream_flags.contains(fl) { + continue; + } + flow_data.input_flags.insert(fl.to_string()); + // Need to get it from upstream, work backwards up the stack until we find a flow that sets it, + // otherwise we need to pass it all the way through + for f in self.flow_stack.iter_mut().rev() { + f.input_flags.insert(fl.to_string()); + if f.modified_flags.contains(fl) { + break; + } + } + } + // Make sure that any modified flags that are referenced later by an upstream flow are output + for fl in &flow_data.modified_flags { + let mut passthrough = false; + for f in &mut self.flow_stack { + if !passthrough && f.referenced_flags.contains(fl) { + passthrough = true; + f.downstream_flags.insert(fl.to_string()); + flow_data.output_flags.insert(fl.to_string()); + } else if passthrough { + flow_data.output_flags.insert(fl.to_string()); + f.output_flags.insert(fl.to_string()); + } + } + } + // Also output any manually set flags (maybe this should be opted-in in the future, e.g. via extern=True) + for fl in &flow_data.modified_flags { + if flow_data.auto_flags.contains(fl) { + continue; + } + flow_data.output_flags.insert(fl.to_string()); + for f in &mut self.flow_stack { + f.output_flags.insert(fl.to_string()); + } + } + flow_data + } +} \ No newline at end of file diff --git a/rust/origen_metal/src/prog_gen/advantest/smt8/processors/flow_generator.rs b/rust/origen_metal/src/prog_gen/advantest/smt8/processors/flow_generator.rs new file mode 100644 index 00000000..e65fb470 --- /dev/null +++ b/rust/origen_metal/src/prog_gen/advantest/smt8/processors/flow_generator.rs @@ -0,0 +1,845 @@ +use crate::prog_gen::advantest::smt8::processors::create_flow_data::FlowData; +use crate::prog_gen::config::SMT8Config; +use crate::prog_gen::{BinType, FlowCondition, GroupType, Model, PGM, ParamValue}; +use crate::Result; +use crate::ast::{Node, Processor, Return}; +use std::collections::{BTreeMap, HashMap}; +use std::io::Write; +use std::path::{Path, PathBuf}; + +/// Does the final writing of the flow AST to a SMT7 flow file +struct FlowGenerator { + #[allow(dead_code)] + name: String, + description: Option, + name_override: Option, + sub_flow_open: bool, + bypass_sub_flows: bool, + output_dir: PathBuf, + generated_files: Vec, + model: Model, + test_methods: BTreeMap, + test_suites: BTreeMap, + test_method_names: HashMap, + resources_block: bool, + flow_stack: Vec, + limits_file: Option, + namespaces: Vec, + options: SMT8Config, +} + +/// Contains the data for a .flow file +#[derive(Default)] +struct FlowFile { + name: String, + path: PathBuf, + indent: usize, + execute_lines: Vec, + execute_lines_buffer: Vec, + buffer_execute_lines: bool, + render_bins: bool, + test_ids: Vec<(String, usize)>, + existing_test_counter: HashMap, + existing_flow_counter: HashMap, + sub_flows: Vec, + flow_data: FlowData +} + +impl FlowFile { + /// Adds a line to the execute section of the flow file, automatically + /// indenting it appropriately + fn execute_line(&mut self, line: String) { + let indent = " ".repeat(self.indent); + if self.buffer_execute_lines { + self.execute_lines_buffer.push(format!("{}{}", indent, line)); + } else { + self.execute_lines.push(format!("{}{}", indent, line)); + } + } + + /// Flushes any buffered execute lines to the main execute lines + /// section + fn flush_buffered_execute_lines(&mut self, indent: usize) { + for line in &self.execute_lines_buffer { + self.execute_lines.push(format!("{}{}", " ".repeat(indent), line)); + } + self.execute_lines_buffer.clear(); + } +} + +pub fn run(ast: &Node, output_dir: &Path, model: Model) -> Result<(Model, Vec)> { + // For debugging + //ast.to_file("smt8_flow.txt")?; + + let mut p = FlowGenerator { + name: "".to_string(), + description: None, + name_override: None, + sub_flow_open: false, + bypass_sub_flows: false, + output_dir: output_dir.to_owned(), + generated_files: vec![], + model: model, + test_methods: BTreeMap::new(), + test_suites: BTreeMap::new(), + test_method_names: HashMap::new(), + resources_block: false, + flow_stack: vec![], + limits_file: None, + namespaces: vec![], + options: crate::PROG_GEN_CONFIG.smt8_options(), + }; + + let mut i = 0; + for (_, t) in &p.model.tests { + let name = format!("tm_{}", i + 1); + p.test_method_names.insert(t.id, name.clone()); + p.test_methods.insert(name, t.id); + i += 1; + } + + for (_, t) in &p.model.test_invocations { + p.test_suites + .insert(t.get("name")?.unwrap().to_string(), t.id); + } + ast.process(&mut p)?; + Ok((p.model, p.generated_files)) +} + +impl FlowGenerator { + fn current_flow_path(&self) -> Option { + if self.flow_stack.is_empty() || self.flow_stack.len() == 1 { + None + } else { + let mut p = "".to_string(); + for f in &self.flow_stack[1..self.flow_stack.len()] { + if p.is_empty() { + p = f.name.to_string(); + } else { + p = format!("{}.{}", p, f.name); + } + } + Some(p) + } + } + + fn open_flow_file(&mut self, name: &str, flow_data: FlowData) -> Result<()> { + // Create a clean name where all spaces are underscores and lowercase and any multiple underscores + // are reduced to single underscores + let mut name = name.replace(" ", "_").to_uppercase(); + while name.contains("__") { + name = name.replace("__", "_"); + } + if let Some(current_flow) = self.flow_stack.last_mut() { + if current_flow.existing_flow_counter.contains_key(&name) { + let count = current_flow.existing_flow_counter.get(&name).unwrap() + 1; + current_flow.existing_flow_counter.insert(name.to_owned(), count); + name = format!("{}_{}", name, count); + } else { + current_flow.existing_flow_counter.insert(name.to_owned(), 0); + } + } + let flow_path = match self.flow_stack.last() { + Some(f) => { + let d = f.path.parent().unwrap().join(f.name.to_lowercase()); + if !d.exists() { + std::fs::create_dir_all(&d)?; + } + d.join(format!("{}.flow", name)) + } + None => self.output_dir.join(format!("{}.flow", name)), + }; + self.flow_stack.push(FlowFile { + name: name.to_string(), + path: flow_path, + render_bins: true, + flow_data, + ..Default::default() + }); + Ok(()) + } + + fn close_flow_file(&mut self, namespace: Option) -> Result { + let flow_file = self.flow_stack.pop().unwrap(); + let namespace = { + match namespace { + Some(n) => format!("{}.", n), + None => "".to_string(), + } + }; + let mut f = std::fs::File::create(&flow_file.path)?; + self.generated_files.push(flow_file.path.clone()); + + writeln!(&mut f, "flow {} {{", flow_file.name)?; + // Remove any vars from input_vars that are also in output_vars + let sorted_input_vars = flow_file.flow_data.sorted_input_vars(); + for v in &sorted_input_vars { + // Maybe typing is needed here later? + if v == "JOB" { + writeln!(&mut f, " in {} = \"\";", v)?; + } else { + writeln!(&mut f, " in {} = -1;", v)?; + } + } + if !sorted_input_vars.is_empty() { + writeln!(&mut f, "")?; + } + //// If not the top-level flow itself + //if !self.flow_stack.is_empty() { + for v in flow_file.flow_data.sorted_output_flags() { + writeln!(&mut f, " out {} = -1;", v)?; + } + if !flow_file.flow_data.output_flags.is_empty() { + writeln!(&mut f, "")?; + } + //} + writeln!(&mut f, " setup {{")?; + // sort the test suites by the name to ensure consistent ordering in the setup section + let mut sorted_test_ids = flow_file.test_ids.clone(); + sorted_test_ids.sort_by_key(|(test_name, _)| test_name.clone()); + for (test_name, tid) in &sorted_test_ids { + let test_invocation = &self.model.test_invocations[tid]; + //if flow_file.name == "ERASE_VFY" { + // dbg!(test_invocation); + //} + if let Some(test) = test_invocation.test(&self.model) { + //if flow_file.name == "ERASE_VFY" { + // dbg!(test); + //} + writeln!(&mut f, " suite {} calls {} {{", test_name, test.class_name.as_ref().unwrap())?; + if let Some(pattern) = test_invocation.get("pattern")?.map(|p| p.to_string()) { + writeln!(&mut f, " measurement.pattern = setupRef({}patterns.{});", &namespace, pattern)?; + } + if let Some(spec) = test_invocation.get("spec")?.map(|p| p.to_string()) { + writeln!(&mut f, " measurement.specification = setupRef({}specs.{});", &namespace, spec)?; + } + let sorted_param_keys = { + let mut keys: Vec<&String> = test.values.keys().collect(); + keys.sort(); + keys + }; + + for param in sorted_param_keys { + let value = test.values.get(param).unwrap(); + if !self.options.render_default_tmparams { + let default_value = test.default_values.get(param); + if let Some(default_value) = default_value { + if default_value == value { + continue; + } + } + } + match value { + ParamValue::String(v) | ParamValue::Any(v) => { + writeln!(&mut f, " {} = \"{}\";", param, v)?; + } + ParamValue::Int(v) => { + writeln!(&mut f, " {} = {};", param, v)?; + } + ParamValue::UInt(v) => { + writeln!(&mut f, " {} = {};", param, v)?; + } + ParamValue::Float(v) => { + writeln!(&mut f, " {} = {};", param, v)?; + } + ParamValue::Current(v) => { + writeln!(&mut f, " {} = \"{}[A]\";", param, v)?; + } + ParamValue::Voltage(v) => { + writeln!(&mut f, " {} = \"{}[V]\";", param, v)?; + } + ParamValue::Time(v) => { + writeln!(&mut f, " {} = \"{}[s]\";", param, v)?; + } + ParamValue::Frequency(v) => { + writeln!(&mut f, " {} = \"{}[Hz]\";", param, v)?; + } + ParamValue::Bool(v) => { + if *v { + writeln!(&mut f, " {} = true;", param)?; + } else { + writeln!(&mut f, " {} = false;", param)?; + } + } + } + } + writeln!(&mut f, " }}")?; + } + writeln!(&mut f, "")?; + } + for sub_flow in &flow_file.sub_flows { + let relative_path = flow_file.path.strip_prefix(&self.output_dir).unwrap().parent().unwrap().join(flow_file.name.to_lowercase()); + writeln!(&mut f, " flow {} calls {}flows.{}.{} {{ }}", sub_flow, &namespace, relative_path.to_str().unwrap().replace("\\", ".").replace("/", "."), sub_flow)?; + } + writeln!(&mut f, " }}")?; + writeln!(&mut f, "")?; + writeln!(&mut f, " execute {{")?; + for v in flow_file.flow_data.sorted_modified_flags() { + writeln!(&mut f, " {} = -1;", v)?; + } + if !flow_file.flow_data.output_flags.is_empty() { + writeln!(&mut f, "")?; + } + for line in &flow_file.execute_lines { + writeln!(&mut f, " {}", line)?; + } + writeln!(&mut f, " }}")?; + writeln!(&mut f, "}}")?; + Ok(flow_file) + } +} + +impl Processor for FlowGenerator { + fn on_node(&mut self, node: &Node) -> crate::Result> { + let result = match &node.attrs { + PGM::ResourcesFilename(name, kind) => { + self.model.set_resources_filename(name.to_owned(), kind); + Return::Unmodified + } + PGM::Namespace(namespace) => { + self.namespaces.push(namespace.to_owned()); + Return::None + } + PGM::Flow(name) => { + log_debug!("Rendering flow '{}' for V93k SMT8", name); + + if self.options.create_limits_file { + let limits_dir = self.output_dir.parent().unwrap().join("limits"); + if !limits_dir.exists() { + std::fs::create_dir_all(&limits_dir)?; + } + let limits_file = limits_dir.join(format!( + "Main.{}_Tests.csv", + name.replace(" ", "_").to_uppercase() + )); + + let mut f = std::fs::File::create(&limits_file)?; + self.generated_files.push(limits_file.clone()); + writeln!(&mut f, "Test Suite,Test,Test Number,Test Text,Low Limit,High Limit,Unit,Soft Bin")?; + writeln!(&mut f, ",,,,default,default")?; + self.limits_file = Some(f); + } + + self.name = name.to_owned(); + self.model.select_flow(name)?; + let flow_data = if let PGM::FlowData(fdata) = &node.children[0].attrs { + fdata.clone() + } else { + FlowData::default() + }; + self.open_flow_file(name, flow_data)?; + node.process_children(self)?; + self.close_flow_file(self.namespaces.last().cloned())?; + + Return::None + } + PGM::BypassSubFlows => { + let orig = self.bypass_sub_flows; + self.bypass_sub_flows = true; + node.process_children(self)?; + self.bypass_sub_flows = orig; + Return::None + } + PGM::FlowDescription(desc) => { + if self.flow_stack.len() == 1 { + self.description = Some(desc.to_owned()); + } + Return::None + } + PGM::FlowNameOverride(name) => { + if self.flow_stack.len() == 1 { + self.name_override = Some(name.to_owned()); + } + Return::None + } + PGM::SubFlow(name, _fid) => { + log_debug!("Rendering sub-flow '{}'", name); + let flow_data = if let PGM::FlowData(fdata) = &node.children[0].attrs { + fdata.clone() + } else { + FlowData::default() + }; + self.open_flow_file(name, flow_data)?; + let orig = self.sub_flow_open; + self.sub_flow_open = true; + node.process_children(self)?; + self.sub_flow_open = orig; + let flow = self.close_flow_file(self.namespaces.last().cloned())?; + let current_flow = self.flow_stack.last_mut().unwrap(); + for v in flow.flow_data.sorted_input_vars() { + current_flow.execute_line(format!("{}.{} = {};", flow.name, v, v)); + } + current_flow.execute_line(format!("{}.execute();", flow.name)); + current_flow.sub_flows.push(flow.name.clone()); + for v in flow.flow_data.sorted_output_flags() { + if current_flow.flow_data.output_flags.contains(&v) || current_flow.flow_data.referenced_flags.contains(&v) { + current_flow.execute_line(format!("{} = {}.{};", v, flow.name, v)); + } + } + Return::None + } + PGM::Group(name, _, kind, _) => { + if kind == &GroupType::Flow { + log_debug!("Rendering group '{}'", name); + let flow_data = if let PGM::FlowData(fdata) = &node.children[0].attrs { + fdata.clone() + } else { + FlowData::default() + }; + self.open_flow_file(name, flow_data)?; + node.process_children(self)?; + let flow = self.close_flow_file(self.namespaces.last().cloned())?; + let current_flow = self.flow_stack.last_mut().unwrap(); + for v in flow.flow_data.sorted_input_vars() { + current_flow.execute_line(format!("{}.{} = {};", flow.name, v, v)); + } + current_flow.execute_line(format!("{}.execute();", flow.name)); + current_flow.sub_flows.push(flow.name.clone()); + for v in flow.flow_data.sorted_output_flags() { + if current_flow.flow_data.output_flags.contains(&v) || current_flow.flow_data.referenced_flags.contains(&v) { + current_flow.execute_line(format!("{} = {}.{};", v, flow.name, v)); + } + } + if node + .children + .iter() + .any(|n| matches!(n.attrs, PGM::OnFailed(_) | PGM::OnPassed(_))) + { + for n in &node.children { + if matches!(n.attrs, PGM::OnPassed(_)) { + self.flow_stack.last_mut().unwrap().buffer_execute_lines = true; + n.process_children(self)?; + { + let current_flow = self.flow_stack.last_mut().unwrap(); + current_flow.buffer_execute_lines = false; + if !current_flow.execute_lines_buffer.is_empty() { + current_flow.execute_line(format!("if ({}.pass) {{", flow.name)); + current_flow.flush_buffered_execute_lines(1); + current_flow.execute_line("}".to_string()); + } + } + } + if matches!(n.attrs, PGM::OnFailed(_)) { + self.flow_stack.last_mut().unwrap().buffer_execute_lines = true; + n.process_children(self)?; + { + let current_flow = self.flow_stack.last_mut().unwrap(); + current_flow.buffer_execute_lines = false; + if !current_flow.execute_lines_buffer.is_empty() { + current_flow.execute_line(format!("if (!{}.pass) {{", flow.name)); + current_flow.flush_buffered_execute_lines(1); + current_flow.execute_line("}".to_string()); + } + } + } + } + } + } else { + node.process_children(self)?; + } + Return::None + } + PGM::Log(msg) => { + self.flow_stack.last_mut().unwrap().execute_line(format!("println(\"{}\");", msg)); + Return::None + } + PGM::Test(id, _flow_id) => { + let mut test_number = "".to_string(); + let mut lo_limit = "".to_string(); + let mut hi_limit = "".to_string(); + let (bin, softbin) = extract_bin(&node.children); + let (test_name, pattern, tname) = { + let test_invocation = &self.model.test_invocations[id]; + let mut test_name = test_invocation.get("name")?.unwrap().to_string(); + { + let current_flow = self.flow_stack.last_mut().unwrap(); + if current_flow.existing_test_counter.contains_key(&test_name) { + let orig_test_name = test_name.clone(); + test_name = format!( + "{}_{}", + test_name, + current_flow.existing_test_counter.get(&orig_test_name).unwrap() + ); + let count = current_flow.existing_test_counter.get(&orig_test_name).unwrap() + 1; + current_flow + .existing_test_counter + .insert(orig_test_name, count); + } else { + current_flow + .existing_test_counter + .insert(test_name.to_owned(), 1); + } + current_flow.test_ids.push((test_name.clone(), *id)); + if let Some(tn) = test_invocation.number { + test_number = format!("{}", tn); + } + if let Some(l) = &test_invocation.lo_limit { + lo_limit = format!("{}{}", l.value, l.unit_str()); + } + if let Some(h) = &test_invocation.hi_limit { + hi_limit = format!("{}{}", h.value, h.unit_str()); + } + //if *id == 6 { + // dbg!(&test_invocation); + // let test = test_invocation.test(&self.model).unwrap(); + // dbg!(test); + //} + ( + test_name, + test_invocation.get("pattern")?.map(|p| p.to_string()), + test_invocation.tname.clone() + ) + } + + }; + if !self.resources_block && self.options.create_limits_file { + let test_path = match self.current_flow_path() { + Some(p) => format!("{}.{}", p, &test_name), + None => test_name.clone(), + }; + let b = if let Some(softbin) = softbin { + softbin.to_string() + } else if let Some(bin) = bin { + bin.to_string() + } else { + "".to_string() + }; + // Test Suite,Test,Test Number,Test Text,Low Limit,High Limit,Unit,Soft Bin" + let test_text = if let Some(test_name_alt) = &tname { + format!("{}.{}", test_name, test_name_alt) + } else { + test_name.clone() + }; + writeln!( + self.limits_file.as_mut().unwrap(), + "{},{},{},{},{},{},,{}", + test_path, + &tname.as_ref().unwrap_or(&test_name), + test_number, + &test_text, + &lo_limit, + &hi_limit, + b + )?; + } + // Record any pattern reference made by this test in the model + if let Some(pattern) = pattern { + self.model.record_pattern_reference(pattern, None, None); + } + if !self.resources_block { + self.flow_stack.last_mut().unwrap().execute_line(format!("{}.execute();", &test_name)); + if node + .children + .iter() + .any(|n| matches!(n.attrs, PGM::OnFailed(_) | PGM::OnPassed(_))) + { + for n in &node.children { + if matches!(n.attrs, PGM::OnPassed(_)) { + self.flow_stack.last_mut().unwrap().buffer_execute_lines = true; + self.flow_stack.last_mut().unwrap().render_bins = false; + n.process_children(self)?; + { + let current_flow = self.flow_stack.last_mut().unwrap(); + current_flow.buffer_execute_lines = false; + current_flow.render_bins = true; + if !current_flow.execute_lines_buffer.is_empty() { + current_flow.execute_line(format!("if ({}.pass) {{", &test_name)); + current_flow.flush_buffered_execute_lines(1); + current_flow.execute_line("}".to_string()); + } + } + } + if matches!(n.attrs, PGM::OnFailed(_)) { + self.flow_stack.last_mut().unwrap().buffer_execute_lines = true; + self.flow_stack.last_mut().unwrap().render_bins = false; + n.process_children(self)?; + { + let current_flow = self.flow_stack.last_mut().unwrap(); + current_flow.buffer_execute_lines = false; + current_flow.render_bins = true; + if !current_flow.execute_lines_buffer.is_empty() { + current_flow.execute_line(format!("if (!{}.pass) {{", &test_name)); + current_flow.flush_buffered_execute_lines(1); + current_flow.execute_line("}".to_string()); + } + } + } + } + } + } + Return::ProcessChildren + } + PGM::TestStr(name, _flow_id, _bin, softbin, number) => { + if !self.resources_block && self.options.create_limits_file { + let test_path = match self.current_flow_path() { + Some(p) => format!("{}.{}", p, &name), + None => name.clone(), + }; + writeln!( + self.limits_file.as_mut().unwrap(), + "{},{},{},{},0,0,,{}", + test_path, + &name, + number.as_ref().map(|n| n.to_string()).unwrap_or_default(), + &name, + softbin.as_ref().map(|b| b.to_string()).unwrap_or_default() + )?; + } + self.flow_stack.last_mut().unwrap().execute_line(format!("{}.execute();", name)); + if node + .children + .iter() + .any(|n| matches!(n.attrs, PGM::OnFailed(_) | PGM::OnPassed(_))) + { + for n in &node.children { + if matches!(n.attrs, PGM::OnPassed(_)) { + self.flow_stack.last_mut().unwrap().buffer_execute_lines = true; + self.flow_stack.last_mut().unwrap().render_bins = false; + n.process_children(self)?; + { + let current_flow = self.flow_stack.last_mut().unwrap(); + current_flow.buffer_execute_lines = false; + current_flow.render_bins = true; + if !current_flow.execute_lines_buffer.is_empty() { + current_flow.execute_line(format!("if ({}.pass) {{", name)); + current_flow.flush_buffered_execute_lines(1); + current_flow.execute_line("}".to_string()); + } + } + } + if matches!(n.attrs, PGM::OnFailed(_)) { + self.flow_stack.last_mut().unwrap().buffer_execute_lines = true; + self.flow_stack.last_mut().unwrap().render_bins = false; + n.process_children(self)?; + { + let current_flow = self.flow_stack.last_mut().unwrap(); + current_flow.buffer_execute_lines = false; + current_flow.render_bins = true; + if !current_flow.execute_lines_buffer.is_empty() { + current_flow.execute_line(format!("if (!{}.pass) {{", name)); + current_flow.flush_buffered_execute_lines(1); + current_flow.execute_line("}".to_string()); + } + } + } + } + } + Return::ProcessChildren + } + PGM::OnFailed(_) => Return::None, // Handled within the PGMTest handler + PGM::OnPassed(_) => Return::None, // Handled within the PGMTest handler + PGM::Else => Return::None, // Handled by its parent + PGM::Condition(cond) => match cond { + FlowCondition::IfJob(jobs) | FlowCondition::UnlessJob(jobs) => { + let else_node = node.children.iter().find(|n| matches!(n.attrs, PGM::Else)); + { + let current_flow = self.flow_stack.last_mut().unwrap(); + current_flow.execute_line(format!( + "if ({}) {{", + jobs + .iter() + .map(|j| { + if jobs.len() > 1 { + format!("(JOB == \"{}\")", j.to_uppercase()) + } else { + format!("JOB == \"{}\"", j.to_uppercase()) + } + }) + .collect::>() + .join(" || ") + )); + current_flow.indent += 1; + } + if matches!(cond, FlowCondition::IfJob(_)) { + node.process_children(self)?; + } else { + if let Some(else_node) = else_node { + else_node.process_children(self)?; + } + } + { + let current_flow = self.flow_stack.last_mut().unwrap(); + current_flow.indent -= 1; + current_flow.execute_line("} else {".to_string()); + current_flow.indent += 1; + } + if matches!(cond, FlowCondition::UnlessJob(_)) { + node.process_children(self)?; + } else { + if let Some(else_node) = else_node { + else_node.process_children(self)?; + } + } + let current_flow = self.flow_stack.last_mut().unwrap(); + current_flow.indent -= 1; + current_flow.execute_line("}".to_string()); + Return::None + } + FlowCondition::IfEnable(flags) | FlowCondition::UnlessEnable(flags) => { + let else_node = node.children.iter().find(|n| matches!(n.attrs, PGM::Else)); + { + let current_flow = self.flow_stack.last_mut().unwrap(); + current_flow.execute_line(format!( + "if ({}) {{", + flags + .iter() + .map(|f| { + if flags.len() > 1 { + format!("({} == 1)", f.to_uppercase()) + } else { + format!("{} == 1", f.to_uppercase()) + } + }) + .collect::>() + .join(" || ") + )); + current_flow.indent += 1; + } + if matches!(cond, FlowCondition::IfEnable(_)) { + node.process_children(self)?; + } else { + if let Some(else_node) = else_node { + else_node.process_children(self)?; + } + } + { + let current_flow = self.flow_stack.last_mut().unwrap(); + current_flow.indent -= 1; + current_flow.execute_line("} else {".to_string()); + current_flow.indent += 1; + } + if matches!(cond, FlowCondition::UnlessEnable(_)) { + node.process_children(self)?; + } else { + if let Some(else_node) = else_node { + else_node.process_children(self)?; + } + } + let current_flow = self.flow_stack.last_mut().unwrap(); + current_flow.indent -= 1; + current_flow.execute_line("}".to_string()); + Return::None + } + FlowCondition::IfFlag(flags) | FlowCondition::UnlessFlag(flags) => { + let else_node = node.children.iter().find(|n| matches!(n.attrs, PGM::Else)); + { + let current_flow = self.flow_stack.last_mut().unwrap(); + current_flow.execute_line(format!( + "if ({}) {{", + flags + .iter() + .map(|f| { + if flags.len() > 1 { + format!("({} == 1)", f.to_uppercase()) + } else { + format!("{} == 1", f.to_uppercase()) + } + }) + .collect::>() + .join(" || ") + )); + current_flow.indent += 1; + } + if matches!(cond, FlowCondition::IfFlag(_)) { + node.process_children(self)?; + } else { + if let Some(else_node) = else_node { + else_node.process_children(self)?; + } + } + { + let current_flow = self.flow_stack.last_mut().unwrap(); + current_flow.indent -= 1; + current_flow.execute_line("} else {".to_string()); + current_flow.indent += 1; + } + if matches!(cond, FlowCondition::UnlessFlag(_)) { + node.process_children(self)?; + } else { + if let Some(else_node) = else_node { + else_node.process_children(self)?; + } + } + let current_flow = self.flow_stack.last_mut().unwrap(); + current_flow.indent -= 1; + current_flow.execute_line("}".to_string()); + Return::None + } + _ => Return::ProcessChildren, + }, + PGM::SetFlag(flag, state, _is_auto_generated) => { + let flag = flag.to_uppercase(); + let current_flow = self.flow_stack.last_mut().unwrap(); + if *state { + current_flow.execute_line(format!("{} = 1;", &flag)); + } else { + current_flow.execute_line(format!("{} = 0;", &flag)); + } + Return::None + } + PGM::Bin(bin, softbin, kind) => { + let current_flow = self.flow_stack.last_mut().unwrap(); + // Currently only rendering pass bins or those not associated with a test (should come from the bin + // table if its associated with a test) (same as O1) + match kind { + BinType::Bad => { + if current_flow.render_bins { + current_flow.execute_line(format!( + "addBin({});", + softbin.unwrap_or(*bin) + )); + } + + }, + BinType::Good => { + current_flow.execute_line(format!( + "addBin({});", + softbin.unwrap_or(*bin) + )); + } + }; + Return::None + } + //PGM::Render(text) => { + // self.push_body(&format!(r#"{}"#, text)); + // Return::None + //} + PGM::Resources => { + let orig = self.resources_block; + self.resources_block = true; + node.process_children(self)?; + self.resources_block = orig; + Return::None + } + _ => Return::ProcessChildren, + }; + Ok(result) + } + + fn on_processed_node(&mut self, node: &Node) -> Result> { + match &node.attrs { + PGM::Namespace(_) => { + self.namespaces.pop(); + } + _ => {} + } + Ok(Return::Unmodified) + } +} + + +fn extract_bin(nodes: &Vec>>) -> (Option, Option) { + for n in nodes { + match &n.attrs { + PGM::OnFailed(_) => { + for n in &n.children { + if let PGM::Bin(bin, softbin, _) = n.attrs { + return (Some(bin), softbin); + } + } + } + _ => {} + } + } + (None, None) +} \ No newline at end of file diff --git a/rust/origen_metal/src/prog_gen/advantest/smt8/processors/mod.rs b/rust/origen_metal/src/prog_gen/advantest/smt8/processors/mod.rs new file mode 100644 index 00000000..72799287 --- /dev/null +++ b/rust/origen_metal/src/prog_gen/advantest/smt8/processors/mod.rs @@ -0,0 +1,2 @@ +pub mod flow_generator; +pub mod create_flow_data; \ No newline at end of file diff --git a/rust/origen_metal/src/prog_gen/config.rs b/rust/origen_metal/src/prog_gen/config.rs index b77ae856..938c2344 100644 --- a/rust/origen_metal/src/prog_gen/config.rs +++ b/rust/origen_metal/src/prog_gen/config.rs @@ -10,7 +10,20 @@ pub struct Config { debug_enabled: RwLock, src_files: RwLock>, test_template_load_path: RwLock>, - uniquess_option: RwLock>, + uniqueness_option: RwLock>, + smt7: RwLock, + smt8: RwLock, +} + +#[derive(Debug, Clone)] +pub struct SMT8Config { + pub create_limits_file: bool, + pub render_default_tmparams: bool, +} + +#[derive(Debug, Clone)] +pub struct SMT7Config { + pub render_default_tmparams: bool, } impl Default for Config { @@ -21,7 +34,14 @@ impl Default for Config { debug_enabled: RwLock::new(false), src_files: RwLock::new(vec![]), test_template_load_path: RwLock::new(vec![]), - uniquess_option: RwLock::new(None), + uniqueness_option: RwLock::new(None), + smt7: RwLock::new(SMT7Config { + render_default_tmparams: true, + }), + smt8: RwLock::new(SMT8Config { + create_limits_file: true, + render_default_tmparams: true, + }), } } } @@ -77,10 +97,31 @@ impl Config { } pub fn set_uniqueness_option(&self, option: UniquenessOption) { - *self.uniquess_option.write().unwrap() = Some(option); + *self.uniqueness_option.write().unwrap() = Some(option); } pub fn uniqueness_option(&self) -> Option { - self.uniquess_option.read().unwrap().clone() + self.uniqueness_option.read().unwrap().clone() + } + + pub fn set_smt7_options(&self, render_default_tmparams: bool) { + *self.smt7.write().unwrap() = SMT7Config { + render_default_tmparams, + }; + } + + pub fn smt7_options(&self) -> SMT7Config { + self.smt7.read().unwrap().clone() + } + + pub fn set_smt8_options(&self, create_limits_file: bool, render_default_tmparams: bool) { + *self.smt8.write().unwrap() = SMT8Config { + create_limits_file, + render_default_tmparams, + }; + } + + pub fn smt8_options(&self) -> SMT8Config { + self.smt8.read().unwrap().clone() } } diff --git a/rust/origen_metal/src/prog_gen/flow_api.rs b/rust/origen_metal/src/prog_gen/flow_api.rs index 70ef94f3..2c5e035a 100644 --- a/rust/origen_metal/src/prog_gen/flow_api.rs +++ b/rust/origen_metal/src/prog_gen/flow_api.rs @@ -98,8 +98,8 @@ pub fn execute_test(id: usize, flow_id: FlowID, meta: Option) -> Result<() /// Execute the given test (or invocation) from the current flow, where the test is a string that /// will be rendered verbatim to the flow - no linkage to an actual test object will be checked or /// inserted by Origen -pub fn execute_test_str(name: String, flow_id: FlowID, meta: Option) -> Result<()> { - let n = node!(PGM::TestStr, name, flow_id; meta); +pub fn execute_test_str(name: String, flow_id: FlowID, bin: Option, softbin: Option, number: Option, meta: Option) -> Result<()> { + let n = node!(PGM::TestStr, name, flow_id, bin, softbin, number; meta); FLOW.push(n) } @@ -232,6 +232,11 @@ pub fn set_default_flag_state(name: String, state: bool, meta: Option) -> FLOW.push(n) } +pub fn set_namespace(namespace: String, meta: Option) -> Result<()> { + let n = node!(PGM::Namespace, namespace; meta); + FLOW.push(n) +} + pub fn continue_on_fail(meta: Option) -> Result<()> { let n = node!(PGM::Continue; meta); FLOW.push(n) diff --git a/rust/origen_metal/src/prog_gen/mod.rs b/rust/origen_metal/src/prog_gen/mod.rs index 1dc42f32..d0e80354 100644 --- a/rust/origen_metal/src/prog_gen/mod.rs +++ b/rust/origen_metal/src/prog_gen/mod.rs @@ -117,6 +117,7 @@ pub fn trace_error(node: &Node, error: crate::Error) -> crate::Resu pub fn render_program(tester: SupportedTester, output_dir: &Path) -> crate::Result<(Vec, Model)> { match tester { SupportedTester::V93KSMT7 => advantest::smt7::render(output_dir), + SupportedTester::V93KSMT8 => advantest::smt8::render(output_dir), _ => Ok((vec![], Model::new(tester))), } } @@ -125,7 +126,7 @@ pub fn render_program(tester: SupportedTester, output_dir: &Path) -> crate::Resu /// would return a list of all test suite attributes pub fn test_invocation_options(tester: SupportedTester) -> crate::Result> { match tester { - SupportedTester::V93KSMT7 => { + SupportedTester::V93KSMT7 | SupportedTester::V93KSMT8 => { let t = load_test_from_lib( &tester, "_internal", @@ -167,26 +168,34 @@ pub fn test_invocation_options(tester: SupportedTester) -> crate::Result, model: Model, tester: SupportedTester, validate: bool) -> crate::Result<(Node, Model)> { + log_debug!("Screening flow for tester {:?}", tester); + //flow.to_file("unprocessed_ast.txt")?; let mut ast = flow.process(&mut |n| { processors::target_tester::run(n, tester) })?; if validate { + log_debug!("Validating flow for tester {:?}", tester); validators::duplicate_ids::run(&ast)?; validators::missing_ids::run(&ast)?; validators::jobs::run(&ast)?; validators::flags::run(&ast)?; + log_debug!("Flow validation completed successfully"); } // This should be run at the very start after the AST has been validated, it removes all define test // and attribute nodes let mut m; + log_debug!("Extracting initial model from flow for tester {:?}", tester); + //ast.to_file("pre_initial_model_extract_ast.txt")?; (ast, m) = processors::initial_model_extract::run( &ast, tester, model, )?; + //ast.to_file("unprocesed_ast.txt")?; + log_debug!("Processing flow for tester {:?}", tester); ast = processors::clean_resources::run(&ast)?; ast = processors::nest_on_result_nodes::run(&ast)?; ast = processors::relationship::run(&ast)?; @@ -200,9 +209,14 @@ pub fn process_flow(flow: &AST, model: Model, tester: SupportedTester, vali SupportedTester::V93KSMT7 => { (ast, m) = advantest::smt7::processors::clean_names_and_add_sig::run(&ast, m)?; } + SupportedTester::V93KSMT8 => { + ast = advantest::smt8::processors::create_flow_data::run(&ast)?; + } _ => { } } + //ast.to_file("ast.txt")?; + // Do a final model extract for things which may have been optimized away if done earlier, e.g. flag variables Ok(processors::final_model_extract::run(&ast, m)?) } \ No newline at end of file diff --git a/rust/origen_metal/src/prog_gen/model/model.rs b/rust/origen_metal/src/prog_gen/model/model.rs index 1113dffb..1a6c0066 100644 --- a/rust/origen_metal/src/prog_gen/model/model.rs +++ b/rust/origen_metal/src/prog_gen/model/model.rs @@ -3,6 +3,7 @@ use super::{ Flow, ParamValue, Pattern, PatternReferenceType, PatternType, ResourcesType, SubTest, Test, Variable, VariableOperation, VariableType, }; +use crate::prog_gen::model::test::TEST_NUMBER_ALIASES; use crate::prog_gen::supported_testers::SupportedTester; use crate::Result; use indexmap::IndexMap; @@ -384,7 +385,40 @@ impl Model { ) -> Result<()> { if self.test_invocations.contains_key(&id) { let inv = self.test_invocations.get_mut(&id).unwrap(); - if inv.has_param(name) { + if name.to_lowercase().as_str() == "tname" { + inv.tname = value.as_ref().and_then(|v| match v { + ParamValue::String(s) => Some(s.to_owned()), + _ => None, + }); + } else if TEST_NUMBER_ALIASES.contains(&name.to_lowercase().as_str()) { + + // Special case for test number aliases + match value { + Some(ParamValue::Int(n)) => { + inv.number = Some(n as usize); + } + Some(ParamValue::UInt(n)) => { + inv.number = Some(n as usize); + } + Some(ParamValue::String(s)) => { + let parsed = s.parse::(); + match parsed { + Ok(n) => { + inv.number = Some(n); + } + Err(_) => { + bail!("Invalid value '{}' for test number attribute, must be an integer", s); + } + } + } + None => { + inv.number = None; + } + _ => { + bail!("Invalid value for test number attribute, must be an integer or string representing an integer"); + } + } + } else if inv.has_param(name) { inv.set(name, value, true)?; } else { if let Some(tid) = inv.test_id { diff --git a/rust/origen_metal/src/prog_gen/model/test.rs b/rust/origen_metal/src/prog_gen/model/test.rs index 49e77123..9438e24f 100644 --- a/rust/origen_metal/src/prog_gen/model/test.rs +++ b/rust/origen_metal/src/prog_gen/model/test.rs @@ -6,6 +6,8 @@ use crate::Result; use indexmap::IndexMap; use std::str::FromStr; +pub const TEST_NUMBER_ALIASES: [&str; 6] = ["testnumber", "test_number", "number", "testnum", "test_num", "tnum"]; + /// This is an abstract data object which is used to model test instances on Teradyne platforms /// and both test methods and test suites on Advantest platforms. /// A test template is modelled as a Test where indirect = true, which means that it will never be @@ -17,6 +19,7 @@ use std::str::FromStr; pub struct Test { pub id: usize, pub name: String, + pub tname: Option, // Secondary test name, if applicable pub indirect: bool, /// Defines the names of parameters and their types. Child class can override the type of a parameter /// inherited from a parent by adding a parameter of the same name to their params map. Then can also @@ -24,6 +27,7 @@ pub struct Test { /// from a parent Test. pub params: IndexMap, pub values: IndexMap, + pub default_values: IndexMap, pub aliases: IndexMap, pub constraints: IndexMap>, pub tester: SupportedTester, @@ -81,9 +85,11 @@ impl Test { let mut t = Test { id: id, name: name.to_string(), + tname: None, indirect: false, params: IndexMap::new(), values: IndexMap::new(), + default_values: IndexMap::new(), aliases: IndexMap::new(), constraints: IndexMap::new(), tester: tester, @@ -139,7 +145,8 @@ impl Test { } if let Some(value) = ¶m.value { let v = self.import_value(&kind, name, value)?; - self.values.insert(name.to_owned(), v); + self.values.insert(name.to_owned(), v.clone()); + self.default_values.insert(name.to_owned(), v); } if let Some(accepted_values) = ¶m.accepted_values { let mut values: Vec = vec![]; diff --git a/rust/origen_metal/src/prog_gen/nodes.rs b/rust/origen_metal/src/prog_gen/nodes.rs index 0b898565..a577163f 100644 --- a/rust/origen_metal/src/prog_gen/nodes.rs +++ b/rust/origen_metal/src/prog_gen/nodes.rs @@ -3,6 +3,7 @@ use crate::prog_gen::{ ResourcesType, UniquenessOption, }; use crate::prog_gen::supported_testers::SupportedTester; +use crate::prog_gen::advantest::smt8::processors::create_flow_data::FlowData; #[derive(Clone, Debug, PartialEq, Serialize)] pub enum PGM { @@ -42,7 +43,8 @@ pub enum PGM { Test(usize, FlowID), /// Execute a test (or invocation) from the flow, where the test is simply a string to be inserted /// into the flow - TestStr(String, FlowID), + /// Bin Softbin Number + TestStr(String, FlowID, Option, Option, Option), /// Defines a new pattern group, also used to model IG-XL pattern sets PatternGroup(usize, String, SupportedTester, Option), /// Push a pattern to the given pattern group ID @@ -91,10 +93,13 @@ pub enum PGM { BypassSubFlows, FlowDescription(String), FlowNameOverride(String), + Namespace(String), /// Apply the given uniqueness option to all contained test names, etc. Uniqueness(UniquenessOption), IGXLSetWaitFlags(usize, Vec), + + FlowData(FlowData) } impl std::fmt::Display for PGM { diff --git a/rust/origen_metal/src/prog_gen/processors/clean_resources.rs b/rust/origen_metal/src/prog_gen/processors/clean_resources.rs index a37d3d29..e75f68a0 100644 --- a/rust/origen_metal/src/prog_gen/processors/clean_resources.rs +++ b/rust/origen_metal/src/prog_gen/processors/clean_resources.rs @@ -30,7 +30,7 @@ impl Processor for CleanResources { _ => { if self.in_resources { // Throw away everything except those with a handler defined above - Ok(Return::None) + Ok(Return::UnwrapWithProcessedChildren) } else { Ok(Return::ProcessChildren) } diff --git a/rust/origen_metal/src/prog_gen/processors/final_model_extract.rs b/rust/origen_metal/src/prog_gen/processors/final_model_extract.rs index 56ad9e0e..8917b7e3 100644 --- a/rust/origen_metal/src/prog_gen/processors/final_model_extract.rs +++ b/rust/origen_metal/src/prog_gen/processors/final_model_extract.rs @@ -1,5 +1,5 @@ use crate::prog_gen::{ - Bin, BinType, FlowCondition, LimitSelector, Model, VariableOperation, VariableType, PGM, + Bin, BinType, FlowCondition, Model, VariableOperation, VariableType, PGM, }; use crate::Result; use crate::ast::{Node, Processor, Return}; @@ -66,24 +66,6 @@ impl Processor for ExtractToModel { ); Return::ProcessChildren } - PGM::SetLimit(test_id, inv_id, selector, value) => { - let t = { - if let Some(id) = test_id { - self.model.tests.get_mut(id) - } else if let Some(id) = inv_id { - self.model.test_invocations.get_mut(id) - } else { - None - } - }; - if let Some(t) = t { - match selector { - LimitSelector::Hi => t.hi_limit = value.to_owned(), - LimitSelector::Lo => t.lo_limit = value.to_owned(), - } - } - Return::None - } //PGM::PatternGroup(id, name, _, kind) => Ok(Return::None), //PGM::PushPattern(id, name, start_label) => Ok(Return::None), // These will be left in the AST for later consumption by the flow, but they also function diff --git a/rust/origen_metal/src/prog_gen/processors/flag_optimizer.rs b/rust/origen_metal/src/prog_gen/processors/flag_optimizer.rs index 9b5095e6..661ea131 100644 --- a/rust/origen_metal/src/prog_gen/processors/flag_optimizer.rs +++ b/rust/origen_metal/src/prog_gen/processors/flag_optimizer.rs @@ -27,6 +27,7 @@ pub struct FlagOptimizer { } pub fn run(node: &Node, optimize_when_continue: Option) -> Result> { + //node.to_file("pre_flag_optimization.txt")?; let optimize_when_continue = match optimize_when_continue { Some(x) => x, None => true, @@ -44,7 +45,7 @@ pub fn run(node: &Node, optimize_when_continue: Option) -> Result for ExtractToModel { trace!(self.model.set_test_attr(*id, name, value.to_owned(), *allow_missing), node); Return::None } + PGM::SetLimit(test_id, inv_id, selector, value) => { + let t = { + if let Some(id) = test_id { + self.model.tests.get_mut(id) + } else if let Some(id) = inv_id { + self.model.test_invocations.get_mut(id) + } else { + None + } + }; + if let Some(t) = t { + match selector { + LimitSelector::Hi => t.hi_limit = value.to_owned(), + LimitSelector::Lo => t.lo_limit = value.to_owned(), + } + } + Return::None + } _ => Return::ProcessChildren, }) } diff --git a/rust/origen_metal/src/prog_gen/processors/nest_on_result_nodes.rs b/rust/origen_metal/src/prog_gen/processors/nest_on_result_nodes.rs index 95f028b2..31ecc609 100644 --- a/rust/origen_metal/src/prog_gen/processors/nest_on_result_nodes.rs +++ b/rust/origen_metal/src/prog_gen/processors/nest_on_result_nodes.rs @@ -50,7 +50,7 @@ impl Processor for NestOnResultNodes { Ok(Return::ProcessChildren) } } - PGM::Test(_, fid) | PGM::TestStr(_, fid) | PGM::Cz(_, _, fid) => { + PGM::Test(_, fid) | PGM::TestStr(_, fid, _, _, _) | PGM::Cz(_, _, fid) => { if self.pass == 1 && self.nodes.contains_key(fid) { let n = { self.nodes.remove(fid).unwrap() }; let mut nodes = vec![n.process_and_update_children(self)?]; diff --git a/rust/origen_metal/src/prog_gen/processors/relationship.rs b/rust/origen_metal/src/prog_gen/processors/relationship.rs index 6e313b1a..7968c71e 100644 --- a/rust/origen_metal/src/prog_gen/processors/relationship.rs +++ b/rust/origen_metal/src/prog_gen/processors/relationship.rs @@ -141,7 +141,7 @@ fn process_test_results( match &node.attrs { // For a test, set a flag immediately after the referenced test has executed // but don't change its pass/fail handling - PGM::Test(_, _) | PGM::TestStr(_, _) => { + PGM::Test(_, _) | PGM::TestStr(_, _, _, _, _) => { return Ok(Return::Inline(vec![node, set_flag])); } // For a group, set a flag immediately upon entry to the group to signal that @@ -168,7 +168,7 @@ fn ids_to_flags(ids: &Vec, name: &str) -> Vec { impl Processor for Relationship { fn on_node(&mut self, node: &Node) -> crate::Result> { Ok(match &node.attrs { - PGM::Test(_, fid) | PGM::TestStr(_, fid) => { + PGM::Test(_, fid) | PGM::TestStr(_, fid, _, _, _) => { let node = node.process_and_update_children(self)?; process_test_results(fid, node, &self)? } diff --git a/rust/origen_metal/src/prog_gen/test_ids/bin_array.rs b/rust/origen_metal/src/prog_gen/test_ids/bin_array.rs index 898e56cb..9e859d40 100644 --- a/rust/origen_metal/src/prog_gen/test_ids/bin_array.rs +++ b/rust/origen_metal/src/prog_gen/test_ids/bin_array.rs @@ -186,17 +186,31 @@ impl BinArray { } pub fn min(&self) -> Option { - self.store.iter().next().map(|b| match b { - Bin::Single(x) => *x, - Bin::Range(start, _) => *start, - }) + let mut min = None; + for b in &self.store { + let val = match b { + Bin::Single(x) => *x, + Bin::Range(start, _) => *start, + }; + if min.is_none() || val < min.unwrap() { + min = Some(val); + } + } + min } pub fn max(&self) -> Option { - self.store.iter().next_back().map(|b| match b { - Bin::Single(x) => *x, - Bin::Range(_, end) => *end, - }) + let mut max = None; + for b in &self.store { + let val = match b { + Bin::Single(x) => *x, + Bin::Range(_, end) => *end, + }; + if max.is_none() || val > max.unwrap() { + max = Some(val); + } + } + max } } @@ -269,7 +283,6 @@ mod tests { } #[test] - #[ignore] fn test_min_and_max() { let mut b = BinArray::new(); b.push(100); diff --git a/rust/origen_metal/src/prog_gen/test_templates/v93ksmt8/_internal/test_suite.json b/rust/origen_metal/src/prog_gen/test_templates/v93ksmt8/_internal/test_suite.json new file mode 100644 index 00000000..32aa3a13 --- /dev/null +++ b/rust/origen_metal/src/prog_gen/test_templates/v93ksmt8/_internal/test_suite.json @@ -0,0 +1,56 @@ +{ + "parameter_list": { + "name": "String", + "spec": "String", + "comment": "String", + "pattern": "String", + "context": "String", + "test_type": "String", + "test_method": "String", + "test_number": "String", + "test_level": "String", + "bypass": "Bool", + "set_pass": "Bool", + "set_fail": "Bool", + "hold": "Bool", + "hold_on_fail": "Bool", + "output_on_pass": "Bool", + "output_on_fail": "Bool", + "pass_value": "Bool", + "fail_value": "Bool", + "per_pin_on_pass": "Bool", + "per_pin_on_fail": "Bool", + "log_mixed_signal_waveform": "Bool", + "fail_per_label": "Bool", + "ffc_enable": "Bool", + "log_first": "Bool", + "ffv_enable": "Bool", + "frg_enable": "Bool", + "hardware_dsp_disable": "Bool", + "site_control": "String", + "site_match": "Int", + "force_serial": "Bool" + }, + + "aliases": { + "test_num": "test_number", + "test_function": "test_method", + "value_on_pass": "pass_value", + "value_on_fail": "fail_value", + "seqlbl": "pattern", + "mx_waves_enable": "log_mixed_signal_waveform", + "hw_dsp_disable": "hardware_dsp_disable", + "ffc_on_fail": "log_first" + }, + + "values": { + "output_on_pass": true, + "output_on_fail": true, + "pass_value": true, + "fail_value": true, + "per_pin_on_pass": true, + "per_pin_on_fail": true, + "site_control": "parallel:", + "site_match": 2 + } +} diff --git a/rust/origen_metal/src/prog_gen/validators/duplicate_ids.rs b/rust/origen_metal/src/prog_gen/validators/duplicate_ids.rs index f9522aaf..cdd10b9b 100644 --- a/rust/origen_metal/src/prog_gen/validators/duplicate_ids.rs +++ b/rust/origen_metal/src/prog_gen/validators/duplicate_ids.rs @@ -44,7 +44,7 @@ impl DuplicateIDs { impl Processor for DuplicateIDs { fn on_node(&mut self, node: &Node) -> crate::Result> { Ok(match &node.attrs { - PGM::Test(_, id) | PGM::TestStr(_, id) | PGM::Cz(_, _, id) => { + PGM::Test(_, id) | PGM::TestStr(_, id, _, _, _) | PGM::Cz(_, _, id) => { self.validate_id(id, node)?; Return::ProcessChildren } diff --git a/rust/origen_metal/src/prog_gen/validators/missing_ids.rs b/rust/origen_metal/src/prog_gen/validators/missing_ids.rs index a796e07f..90db4904 100644 --- a/rust/origen_metal/src/prog_gen/validators/missing_ids.rs +++ b/rust/origen_metal/src/prog_gen/validators/missing_ids.rs @@ -64,7 +64,7 @@ pub fn run(node: &Node) -> Result<()> { impl Processor for MissingIDs { fn on_node(&mut self, node: &Node) -> crate::Result> { Ok(match &node.attrs { - PGM::Test(_, id) | PGM::TestStr(_, id) | PGM::Cz(_, _, id) => { + PGM::Test(_, id) | PGM::TestStr(_, id, _, _, _) | PGM::Cz(_, _, id) => { self.ids.insert(id.to_owned(), node.without_children()); Return::ProcessChildren } diff --git a/rust/pyapi/Cargo.lock b/rust/pyapi/Cargo.lock index ae4509a6..32ecea11 100644 --- a/rust/pyapi/Cargo.lock +++ b/rust/pyapi/Cargo.lock @@ -2608,7 +2608,7 @@ dependencies = [ [[package]] name = "origen-metal" -version = "1.0.1" +version = "1.1.0" dependencies = [ "built", "curl-sys", diff --git a/rust/pyapi/src/macros.rs b/rust/pyapi/src/macros.rs index c9db5b44..927e01e9 100644 --- a/rust/pyapi/src/macros.rs +++ b/rust/pyapi/src/macros.rs @@ -4,6 +4,7 @@ macro_rules! _origen { }; } +#[allow(unused_macros)] macro_rules! origen { ($py: expr) => { pyo3::types::PyModule::import($py, "origen")? diff --git a/rust/pyapi_metal/Cargo.lock b/rust/pyapi_metal/Cargo.lock index 40bb6b0c..d2ed55e8 100644 --- a/rust/pyapi_metal/Cargo.lock +++ b/rust/pyapi_metal/Cargo.lock @@ -2045,7 +2045,7 @@ dependencies = [ [[package]] name = "origen-metal" -version = "1.0.2" +version = "1.1.0" dependencies = [ "built", "curl-sys", diff --git a/rust/pyapi_metal/src/prog_gen/flow_options.rs b/rust/pyapi_metal/src/prog_gen/flow_options.rs index b0d945c6..39def162 100644 --- a/rust/pyapi_metal/src/prog_gen/flow_options.rs +++ b/rust/pyapi_metal/src/prog_gen/flow_options.rs @@ -219,6 +219,22 @@ pub fn get_softbin(kwargs: Option<&PyDict>) -> Result> { Ok(None) } +pub fn get_number(kwargs: Option<&PyDict>) -> Result> { + if let Some(kwargs) = kwargs { + if let Some(n) = kwargs.get_item("number") { + if let Ok(v) = n.extract::() { + return Ok(Some(v)); + } else { + bail!( + "Illegal 'number' value, expected an Integer, got: '{}'", + n + ); + } + } + } + Ok(None) +} + pub fn on_fail(fid: &FlowID, kwargs: Option<&PyDict>) -> Result<()> { if let Some(kwargs) = kwargs { let cont = diff --git a/rust/pyapi_metal/src/prog_gen/interface.rs b/rust/pyapi_metal/src/prog_gen/interface.rs index 3648f861..059218ea 100644 --- a/rust/pyapi_metal/src/prog_gen/interface.rs +++ b/rust/pyapi_metal/src/prog_gen/interface.rs @@ -75,6 +75,7 @@ impl PyInterface { let id = flow_options::get_flow_id(kwargs)?; let bin = flow_options::get_bin(kwargs)?; let softbin = flow_options::get_softbin(kwargs)?; + let number = flow_options::get_number(kwargs)?; Ok(flow_options::wrap_in_conditions(kwargs, false, || { if let Ok(t) = test_obj.extract::() { @@ -100,7 +101,7 @@ impl PyInterface { } } } else if let Ok(t) = test_obj.extract::() { - flow_api::execute_test_str(t, id.clone(), src_caller_meta())?; + flow_api::execute_test_str(t, id.clone(), bin, softbin, number, src_caller_meta())?; } else { bail!( "add_test must be given a valid test object, or a String, this is neither: {:?}", diff --git a/rust/pyapi_metal/src/prog_gen/mod.rs b/rust/pyapi_metal/src/prog_gen/mod.rs index 854c7bcf..a2b5aa3b 100644 --- a/rust/pyapi_metal/src/prog_gen/mod.rs +++ b/rust/pyapi_metal/src/prog_gen/mod.rs @@ -76,6 +76,9 @@ pub fn define(py: Python, m: &PyModule) -> PyResult<()> { subm.add_wrapped(wrap_pyfunction!(ast_str))?; subm.add_wrapped(wrap_pyfunction!(set_test_template_load_path))?; subm.add_wrapped(wrap_pyfunction!(set_uniqueness_option))?; + subm.add_wrapped(wrap_pyfunction!(set_namespace))?; + subm.add_wrapped(wrap_pyfunction!(set_smt7_options))?; + subm.add_wrapped(wrap_pyfunction!(set_smt8_options))?; m.add_submodule(subm)?; Ok(()) } @@ -102,6 +105,18 @@ fn set_uniqueness_option(option: String) -> PyResult<()> { Ok(()) } +#[pyfunction] +fn set_smt7_options(render_default_tm_params: bool) -> PyResult<()> { + origen_metal::PROG_GEN_CONFIG.set_smt7_options(render_default_tm_params); + Ok(()) +} + +#[pyfunction] +fn set_smt8_options(create_limits_file: bool, render_default_tm_params: bool) -> PyResult<()> { + origen_metal::PROG_GEN_CONFIG.set_smt8_options(create_limits_file, render_default_tm_params); + Ok(()) +} + #[pyfunction] fn set_debugging(value: bool) -> PyResult<()> { origen_metal::PROG_GEN_CONFIG.set_debug_enabled(value); @@ -213,6 +228,12 @@ fn start_new_flow( Ok(refs) } +#[pyfunction] +fn set_namespace(namespace: String) -> PyResult<()> { + flow_api::set_namespace(namespace, None)?; + Ok(()) +} + #[pyfunction] fn end_flow(ref_ids: Vec) -> PyResult<()> { for ref_id in ref_ids { diff --git a/rust/pyapi_metal/src/prog_gen/test_invocation.rs b/rust/pyapi_metal/src/prog_gen/test_invocation.rs index f8c2579e..5f9f4b13 100644 --- a/rust/pyapi_metal/src/prog_gen/test_invocation.rs +++ b/rust/pyapi_metal/src/prog_gen/test_invocation.rs @@ -33,7 +33,6 @@ impl TestInvocation { Ok(()) } - #[setter] pub fn set_lo_limit(&self, value: &PyAny) -> PyResult<()> { let value = match to_param_value(value)? { None => None, @@ -53,7 +52,6 @@ impl TestInvocation { Ok(()) } - #[setter] pub fn set_hi_limit(&self, value: &PyAny) -> PyResult<()> { let value = match to_param_value(value)? { None => None, diff --git a/rust/pyapi_metal/src/prog_gen/tester_apis/v93k.rs b/rust/pyapi_metal/src/prog_gen/tester_apis/v93k.rs index c2a8ca48..e7fab667 100644 --- a/rust/pyapi_metal/src/prog_gen/tester_apis/v93k.rs +++ b/rust/pyapi_metal/src/prog_gen/tester_apis/v93k.rs @@ -1,4 +1,4 @@ -use crate::prog_gen::{Test, TestInvocation}; +use crate::prog_gen::{Test, TestInvocation, to_param_value}; use origen_metal::prog_gen::{ParamValue, SupportedTester}; use pyo3::{exceptions, prelude::*}; use pyo3::types::PyDict; @@ -50,6 +50,18 @@ impl V93K { ) -> PyResult { let t = TestInvocation::new(name.clone(), self.tester.to_owned(), allow_missing, kwargs)?; t.set_attr("name", Some(ParamValue::String(name.to_owned())), allow_missing)?; + if let Some(kwargs) = kwargs { + for (k, v) in kwargs { + if let Ok(name) = k.extract::() { + t.set_attr(&name, to_param_value(v)?, allow_missing)?; + } else { + return Err(PyErr::new::(format!( + "Illegal attribute name type '{}', should be a String", + k + ))); + } + } + } Ok(t) } } diff --git a/test_apps/python_app/approved/v93ksmt7/test_program/prb1.aiv b/test_apps/python_app/approved/v93ksmt7/test_program/prb1.aiv index d29f7fe4..67f00bf7 100644 --- a/test_apps/python_app/approved/v93ksmt7/test_program/prb1.aiv +++ b/test_apps/python_app/approved/v93ksmt7/test_program/prb1.aiv @@ -10,6 +10,10 @@ AI_V2B_OPTIONS -ALT -c .vbc -k -z PS800 PATTERNS name tmf_file v2b_options another_not_p1_or_p2_test .tmf +bitcell_iv_0 .tmf +bitcell_iv_1 .tmf +bitcell_iv_2 .tmf +bitmap_all0 .tmf cc_test_0 .tmf cc_test_1 .tmf cc_test_2 .tmf @@ -21,6 +25,7 @@ margin_read1_all1 .tmf margin_read1_ckbd .tmf meas_read_pump .tmf mixed_flag_check .tmf +normal_read_ckbd .tmf not_p1_or_p2_test .tmf not_p1_test .tmf p1_only_test .tmf diff --git a/test_apps/python_app/approved/referenced.list b/test_apps/python_app/approved/v93ksmt7/test_program/referenced.list similarity index 85% rename from test_apps/python_app/approved/referenced.list rename to test_apps/python_app/approved/v93ksmt7/test_program/referenced.list index 67e40b2c..21cff991 100644 --- a/test_apps/python_app/approved/referenced.list +++ b/test_apps/python_app/approved/v93ksmt7/test_program/referenced.list @@ -1,4 +1,8 @@ another_not_p1_or_p2_test +bitcell_iv_0 +bitcell_iv_1 +bitcell_iv_2 +bitmap_all0 cc_test_0 cc_test_1 cc_test_2 @@ -11,6 +15,7 @@ margin_read1_ckbd meas_read_pump mixed_flag_check mrd_ckbd +normal_read_ckbd not_p1_or_p2_test not_p1_test p1_only_test diff --git a/test_apps/python_app/approved/v93ksmt7/test_program/testflow/prb1.tf b/test_apps/python_app/approved/v93ksmt7/test_program/testflow/prb1.tf index 53327c1d..5586f23f 100644 --- a/test_apps/python_app/approved/v93ksmt7/test_program/testflow/prb1.tf +++ b/test_apps/python_app/approved/v93ksmt7/test_program/testflow/prb1.tf @@ -1275,6 +1275,13 @@ erase_all_40_864CE8F: override_testf = tm_86; site_control = "parallel:"; site_match = 2; +erase_all_41_864CE8F: + local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; + override = 1; + override_seqlbl = "erase_all"; + override_testf = tm_119; + site_control = "parallel:"; + site_match = 2; erase_all_4_864CE8F: local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; override = 1; @@ -1307,7 +1314,7 @@ erase_all_864CE8F: local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; override = 1; override_seqlbl = "erase_all"; - override_testf = tm_119; + override_testf = tm_4; site_control = "parallel:"; site_match = 2; erase_all_8_864CE8F: @@ -1338,13 +1345,20 @@ force_serial_true_test_864CE8F: override_testf = tm_99; site_control = "parallel:"; site_match = 2; -margin_read0_ckbd_864CE8F: +margin_read0_ckbd_1_864CE8F: local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; override = 1; override_seqlbl = "margin_read0_ckbd"; override_testf = tm_118; site_control = "parallel:"; site_match = 2; +margin_read0_ckbd_864CE8F: + local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; + override = 1; + override_seqlbl = "margin_read0_ckbd"; + override_testf = tm_3; + site_control = "parallel:"; + site_match = 2; margin_read1_all1_10_864CE8F: local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; override = 1; @@ -1493,13 +1507,20 @@ margin_read1_all1_9_864CE8F: override_testf = tm_62; site_control = "parallel:"; site_match = 2; -margin_read1_ckbd_864CE8F: +margin_read1_ckbd_1_864CE8F: local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; override = 1; override_seqlbl = "margin_read1_ckbd"; override_testf = tm_116; site_control = "parallel:"; site_match = 2; +margin_read1_ckbd_864CE8F: + local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; + override = 1; + override_seqlbl = "margin_read1_ckbd"; + override_testf = tm_2; + site_control = "parallel:"; + site_match = 2; meas_read_pump_1_864CE8F: local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; override = 1; @@ -1668,6 +1689,13 @@ program_ckbd_16_864CE8F: override_testf = tm_26; site_control = "parallel:"; site_match = 2; +program_ckbd_17_864CE8F: + local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; + override = 1; + override_seqlbl = "program_ckbd"; + override_testf = tm_111; + site_control = "parallel:"; + site_match = 2; program_ckbd_1_864CE8F: local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; override = 1; @@ -1721,7 +1749,7 @@ program_ckbd_864CE8F: local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; override = 1; override_seqlbl = "program_ckbd"; - override_testf = tm_111; + override_testf = tm_1; site_control = "parallel:"; site_match = 2; program_ckbd_8_864CE8F: diff --git a/test_apps/python_app/approved/v93ksmt7/test_program/testflow/prb2.tf b/test_apps/python_app/approved/v93ksmt7/test_program/testflow/prb2.tf index f5178cda..b91acd33 100644 --- a/test_apps/python_app/approved/v93ksmt7/test_program/testflow/prb2.tf +++ b/test_apps/python_app/approved/v93ksmt7/test_program/testflow/prb2.tf @@ -1366,6 +1366,13 @@ erase_all_40_864CE8F: override_testf = tm_86; site_control = "parallel:"; site_match = 2; +erase_all_41_864CE8F: + local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; + override = 1; + override_seqlbl = "erase_all"; + override_testf = tm_119; + site_control = "parallel:"; + site_match = 2; erase_all_4_864CE8F: local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; override = 1; @@ -1405,7 +1412,7 @@ erase_all_864CE8F: local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; override = 1; override_seqlbl = "erase_all"; - override_testf = tm_119; + override_testf = tm_4; site_control = "parallel:"; site_match = 2; erase_all_8_864CE8F: @@ -1436,13 +1443,20 @@ force_serial_true_test_864CE8F: override_testf = tm_99; site_control = "parallel:"; site_match = 2; -margin_read0_ckbd_864CE8F: +margin_read0_ckbd_1_864CE8F: local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; override = 1; override_seqlbl = "margin_read0_ckbd"; override_testf = tm_118; site_control = "parallel:"; site_match = 2; +margin_read0_ckbd_864CE8F: + local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; + override = 1; + override_seqlbl = "margin_read0_ckbd"; + override_testf = tm_3; + site_control = "parallel:"; + site_match = 2; margin_read1_all1_10_864CE8F: local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; override = 1; @@ -1619,13 +1633,20 @@ margin_read1_all1_9_864CE8F: override_testf = tm_62; site_control = "parallel:"; site_match = 2; -margin_read1_ckbd_864CE8F: +margin_read1_ckbd_1_864CE8F: local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; override = 1; override_seqlbl = "margin_read1_ckbd"; override_testf = tm_116; site_control = "parallel:"; site_match = 2; +margin_read1_ckbd_864CE8F: + local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; + override = 1; + override_seqlbl = "margin_read1_ckbd"; + override_testf = tm_2; + site_control = "parallel:"; + site_match = 2; meas_read_pump_1_864CE8F: local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; override = 1; @@ -1822,6 +1843,13 @@ program_ckbd_16_864CE8F: override_testf = tm_26; site_control = "parallel:"; site_match = 2; +program_ckbd_17_864CE8F: + local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; + override = 1; + override_seqlbl = "program_ckbd"; + override_testf = tm_111; + site_control = "parallel:"; + site_match = 2; program_ckbd_1_864CE8F: local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; override = 1; @@ -1875,7 +1903,7 @@ program_ckbd_864CE8F: local_flags = output_on_pass, output_on_fail, value_on_pass, value_on_fail, per_pin_on_pass, per_pin_on_fail; override = 1; override_seqlbl = "program_ckbd"; - override_testf = tm_111; + override_testf = tm_1; site_control = "parallel:"; site_match = 2; program_ckbd_8_864CE8F: diff --git a/test_apps/python_app/approved/v93ksmt7/test_program/vectors/prb1.pmfl b/test_apps/python_app/approved/v93ksmt7/test_program/vectors/prb1.pmfl index 0034fcb1..ea43595b 100644 --- a/test_apps/python_app/approved/v93ksmt7/test_program/vectors/prb1.pmfl +++ b/test_apps/python_app/approved/v93ksmt7/test_program/vectors/prb1.pmfl @@ -5,6 +5,10 @@ path: files: another_not_p1_or_p2_test.binl.gz +bitcell_iv_0.binl.gz +bitcell_iv_1.binl.gz +bitcell_iv_2.binl.gz +bitmap_all0.binl.gz cc_test_0.binl.gz cc_test_1.binl.gz cc_test_2.binl.gz @@ -16,6 +20,7 @@ margin_read1_all1.binl.gz margin_read1_ckbd.binl.gz meas_read_pump.binl.gz mixed_flag_check.binl.gz +normal_read_ckbd.binl.gz not_p1_or_p2_test.binl.gz not_p1_test.binl.gz p1_only_test.binl.gz diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/PRB1.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/PRB1.flow new file mode 100644 index 00000000..651bb684 --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/PRB1.flow @@ -0,0 +1,101 @@ +flow PRB1 { + in ADDITIONAL_ERASE = -1; + in ALARM = -1; + in ALARMENABLED = -1; + in DO_ERASE = -1; + in JOB = ""; + in NO_EXTRA_ERASE = -1; + in USB_XCVR_CZ = -1; + + out ERS_VFY_FAILED = -1; + + setup { + suite bitcell_iv_0 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.bitcell_iv_0); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite bitcell_iv_1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.bitcell_iv_1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite bitcell_iv_2 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.bitcell_iv_2); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite bitmap_all0 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.bitmap_all0); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read0_ckbd calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read0_ckbd); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_ckbd calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_ckbd); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite normal_read_ckbd calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.normal_read_ckbd); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite program_ckbd calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + flow PRB1_MAIN calls OrigenTesters.flows.prb1.PRB1_MAIN { } + flow TEST calls OrigenTesters.flows.prb1.TEST { } + } + + execute { + DEEP_TEST_FAILED = -1; + ERS_VFY_FAILED = -1; + + PRB1_MAIN.ADDITIONAL_ERASE = ADDITIONAL_ERASE; + PRB1_MAIN.ALARM = ALARM; + PRB1_MAIN.ALARMENABLED = ALARMENABLED; + PRB1_MAIN.DO_ERASE = DO_ERASE; + PRB1_MAIN.JOB = JOB; + PRB1_MAIN.NO_EXTRA_ERASE = NO_EXTRA_ERASE; + PRB1_MAIN.USB_XCVR_CZ = USB_XCVR_CZ; + PRB1_MAIN.execute(); + DEEP_TEST_FAILED = PRB1_MAIN.DEEP_TEST_FAILED; + ERS_VFY_FAILED = PRB1_MAIN.ERS_VFY_FAILED; + TEST.execute(); + if (DEEP_TEST_FAILED == 1) { + on_deep_1.execute(); + } else { + } + addBin(1); + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/PRB2.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/PRB2.flow new file mode 100644 index 00000000..8922ec4d --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/PRB2.flow @@ -0,0 +1,76 @@ +flow PRB2 { + in EXTRA_TESTS = -1; + in PRB2_ENABLE = -1; + + setup { + suite erase_all calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_2 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_2 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_3 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + flow PRB2_MAIN calls OrigenTesters.flows.prb2.PRB2_MAIN { } + flow PRB2_MAIN_1 calls OrigenTesters.flows.prb2.PRB2_MAIN_1 { } + } + + execute { + if (PRB2_ENABLE == 1) { + erase_all.execute(); + margin_read1_all1.execute(); + erase_all_1.execute(); + margin_read1_all1_1.execute(); + PRB2_MAIN.execute(); + erase_all_2.execute(); + margin_read1_all1_2.execute(); + if (EXTRA_TESTS == 1) { + PRB2_MAIN_1.execute(); + } else { + } + margin_read1_all1_3.execute(); + } else { + } + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/DEFAULT_NO_GROUP_IMPORT.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/DEFAULT_NO_GROUP_IMPORT.flow new file mode 100644 index 00000000..92f8dd98 --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/DEFAULT_NO_GROUP_IMPORT.flow @@ -0,0 +1,10 @@ +flow DEFAULT_NO_GROUP_IMPORT { + + + setup { + } + + execute { + grouped_flow_create_option_override.execute(); + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/PRB1_MAIN.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/PRB1_MAIN.flow new file mode 100644 index 00000000..b9c4f8cc --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/PRB1_MAIN.flow @@ -0,0 +1,764 @@ +flow PRB1_MAIN { + in ADDITIONAL_ERASE = -1; + in ALARM = -1; + in ALARMENABLED = -1; + in DO_ERASE = -1; + in JOB = ""; + in NO_EXTRA_ERASE = -1; + in USB_XCVR_CZ = -1; + + out DEEP_TEST_FAILED = -1; + out ERS_VFY_FAILED = -1; + + setup { + suite another_not_p1_or_p2_test calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.another_not_p1_or_p2_test); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite cc_test_0 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.cc_test_0); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite cc_test_1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.cc_test_1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite cc_test_2 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.cc_test_2); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_10 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_11 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_12 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_13 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_14 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_15 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_16 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_17 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_18 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_19 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_2 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_20 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_21 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_22 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_23 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_24 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_25 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_26 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_27 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_28 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_3 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_4 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_5 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_6 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_7 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_8 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_9 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read0_ckbd calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read0_ckbd); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_10 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_11 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_12 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_13 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_14 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_15 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_16 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_17 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_18 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.cz); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_2 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_3 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_4 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_5 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_6 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_7 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_8 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_all1_9 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite margin_read1_ckbd calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_ckbd); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite not_p1_or_p2_test calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.not_p1_or_p2_test); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite not_p1_test calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.not_p1_test); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite p1_only_test calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.p1_only_test); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite p1_or_p2_only_test calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.p1_or_p2_only_test); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite por_ins calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.por_ins); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite program_ckbd calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite program_ckbd_1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite program_ckbd_2 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite program_ckbd_3 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite program_ckbd_4 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite some_func_test calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.some_func_test); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite xcvr_fs_vilvih calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.xcvr_fs_vilvih); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite xcvr_fs_vilvih_1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.xcvr_fs_vilvih); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite xcvr_fs_vilvih_2 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.xcvr_fs_vilvih); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite xcvr_fs_vilvih_3 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.xcvr_fs_vilvih); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + flow ERASE calls OrigenTesters.flows.prb1.prb1_main.ERASE { } + flow PROGRAM_CKBD calls OrigenTesters.flows.prb1.prb1_main.PROGRAM_CKBD { } + flow PROGRAM_CKBD_1 calls OrigenTesters.flows.prb1.prb1_main.PROGRAM_CKBD_1 { } + flow PROGRAM_CKBD_2 calls OrigenTesters.flows.prb1.prb1_main.PROGRAM_CKBD_2 { } + flow PROGRAM_CKBD_3 calls OrigenTesters.flows.prb1.prb1_main.PROGRAM_CKBD_3 { } + flow ERASE_1 calls OrigenTesters.flows.prb1.prb1_main.ERASE_1 { } + flow ADDITIONAL_ERASE calls OrigenTesters.flows.prb1.prb1_main.ADDITIONAL_ERASE { } + flow ADDITIONAL_ERASE_1 calls OrigenTesters.flows.prb1.prb1_main.ADDITIONAL_ERASE_1 { } + flow 200MHZ_TESTS calls OrigenTesters.flows.prb1.prb1_main.200MHZ_TESTS { } + flow 100MHZ_TESTS calls OrigenTesters.flows.prb1.prb1_main.100MHZ_TESTS { } + flow DEEP_NESTED calls OrigenTesters.flows.prb1.prb1_main.DEEP_NESTED { } + } + + execute { + DEEP_TEST_FAILED = -1; + ERASE_FAILED_1_FAILED = -1; + ERASE_FAILED_2_FAILED = -1; + ERASE_FAILED_3_PASSED = -1; + ERASE_FAILED_4_PASSED = -1; + ERASE_PASSED_1_PASSED = -1; + ERASE_PASSED_2_PASSED = -1; + ERASE_PASSED_3_FAILED = -1; + ERASE_PASSED_4_FAILED = -1; + ERASE_RAN_1_RAN = -1; + ERASE_RAN_2_RAN = -1; + ERASE_RAN_3_RAN = -1; + ERASE_RAN_4_RAN = -1; + ERS_VFY_FAILED = -1; + G100_RAN = -1; + G200_FAILED = -1; + + program_ckbd.execute(); + margin_read1_ckbd.execute(); + margin_read0_ckbd.execute(); + ERASE.execute(); + ERS_VFY_FAILED = ERASE.ERS_VFY_FAILED; + println("Should be v1"); + program_ckbd_1.execute(); + println("Should be v2"); + program_ckbd_2.execute(); + println("Should be v1"); + program_ckbd_3.execute(); + println("Should be v2"); + program_ckbd_4.execute(); + println("Should be a v1 test instance group"); + PROGRAM_CKBD.execute(); + println("Should be a v2 test instance group"); + PROGRAM_CKBD_1.execute(); + println("Should be a v1 test instance group"); + PROGRAM_CKBD_2.execute(); + println("Should be a v2 test instance group"); + PROGRAM_CKBD_3.execute(); + if (JOB == "P1") { + p1_only_test.execute(); + } else { + } + if ((JOB == "P1") || (JOB == "P2")) { + p1_or_p2_only_test.execute(); + } else { + } + if (JOB == "P1") { + } else { + not_p1_test.execute(); + } + if ((JOB == "P1") || (JOB == "P2")) { + } else { + not_p1_or_p2_test.execute(); + another_not_p1_or_p2_test.execute(); + } + println("Verify that a test with an external instance works"); + por_ins.execute(); + println("Verify that a request to use the current context works"); + if (JOB == "P1") { + erase_all.execute(); + erase_all_1.execute(); + erase_all_2.execute(); + } else { + } + if (JOB == "P2") { + } else { + erase_all_3.execute(); + } + erase_all_4.execute(); + margin_read1_all1.execute(); + if (!margin_read1_all1.pass) { + erase_all_5.execute(); + } + margin_read1_all1_1.execute(); + if (!margin_read1_all1_1.pass) { + erase_all_6.execute(); + } + margin_read1_all1_2.execute(); + if (!margin_read1_all1_2.pass) { + erase_all_7.execute(); + } + margin_read1_all1_3.execute(); + if (!margin_read1_all1_3.pass) { + erase_all_8.execute(); + } + margin_read1_all1_4.execute(); + if (!margin_read1_all1_4.pass) { + erase_all_9.execute(); + } + margin_read1_all1_5.execute(); + println("Test if enable"); + if (DO_ERASE == 1) { + erase_all_10.execute(); + erase_all_11.execute(); + } else { + } + println("Test unless enable"); + if (NO_EXTRA_ERASE == 1) { + } else { + erase_all_12.execute(); + erase_all_13.execute(); + erase_all_14.execute(); + } + erase_all_15.execute(); + erase_all_16.execute(); + println("Test if_passed"); + erase_all_17.execute(); + if (erase_all_17.pass) { + ERASE_PASSED_1_PASSED = 1; + } + erase_all_18.execute(); + if (erase_all_18.pass) { + ERASE_PASSED_2_PASSED = 1; + } + if (ERASE_PASSED_1_PASSED == 1) { + margin_read1_all1_6.execute(); + } else { + } + if (ERASE_PASSED_2_PASSED == 1) { + margin_read1_all1_7.execute(); + } else { + } + println("Test unless_passed"); + erase_all_19.execute(); + if (!erase_all_19.pass) { + ERASE_PASSED_3_FAILED = 1; + } + erase_all_20.execute(); + if (!erase_all_20.pass) { + ERASE_PASSED_4_FAILED = 1; + } + if (ERASE_PASSED_3_FAILED == 1) { + margin_read1_all1_8.execute(); + } else { + } + if (ERASE_PASSED_4_FAILED == 1) { + margin_read1_all1_9.execute(); + } else { + } + println("Test if_failed"); + erase_all_21.execute(); + if (!erase_all_21.pass) { + ERASE_FAILED_1_FAILED = 1; + } + erase_all_22.execute(); + if (!erase_all_22.pass) { + ERASE_FAILED_2_FAILED = 1; + } + if (ERASE_FAILED_1_FAILED == 1) { + margin_read1_all1_10.execute(); + } else { + } + if (ERASE_FAILED_2_FAILED == 1) { + margin_read1_all1_11.execute(); + } else { + } + println("Test unless_failed"); + erase_all_23.execute(); + if (erase_all_23.pass) { + ERASE_FAILED_3_PASSED = 1; + } + erase_all_24.execute(); + if (erase_all_24.pass) { + ERASE_FAILED_4_PASSED = 1; + } + if (ERASE_FAILED_3_PASSED == 1) { + margin_read1_all1_12.execute(); + } else { + } + if (ERASE_FAILED_4_PASSED == 1) { + margin_read1_all1_13.execute(); + } else { + } + println("Test if_ran"); + erase_all_25.execute(); + ERASE_RAN_1_RAN = 1; + erase_all_26.execute(); + ERASE_RAN_2_RAN = 1; + if (ERASE_RAN_1_RAN == 1) { + margin_read1_all1_14.execute(); + } else { + } + if (ERASE_RAN_2_RAN == 1) { + margin_read1_all1_15.execute(); + } else { + } + println("Test unless_ran"); + erase_all_27.execute(); + ERASE_RAN_3_RAN = 1; + erase_all_28.execute(); + ERASE_RAN_4_RAN = 1; + if (ERASE_RAN_3_RAN == 1) { + } else { + margin_read1_all1_16.execute(); + } + if (ERASE_RAN_4_RAN == 1) { + } else { + margin_read1_all1_17.execute(); + } + println("Verify that job context wraps import"); + if (JOB == "FR") { + ERASE_1.execute(); + ERS_VFY_FAILED = ERASE_1.ERS_VFY_FAILED; + } else { + } + println("Verify that job context wraps enable block within an import"); + if (JOB == "FR") { + ADDITIONAL_ERASE.ADDITIONAL_ERASE = ADDITIONAL_ERASE; + ADDITIONAL_ERASE.execute(); + ADDITIONAL_ERASE_1.execute(); + } else { + } + println("Verify that flow.cz works..."); + margin_read1_all1_18.execute(); + println("Verify that flow.cz works with enable words"); + if (USB_XCVR_CZ == 1) { + xcvr_fs_vilvih.execute(); + xcvr_fs_vilvih_1.execute(); + xcvr_fs_vilvih_2.execute(); + xcvr_fs_vilvih_3.execute(); + } else { + } + println("Verify that MTO template works..."); + println("Speed binning example bug from video 5"); + 200MHZ_TESTS.execute(); + if (!200MHZ_TESTS.pass) { + G200_FAILED = 1; + } + if (G200_FAILED == 1) { + 100MHZ_TESTS.execute(); + G100_RAN = 100MHZ_TESTS.G100_RAN; + } else { + } + if (G100_RAN == 1) { + addBin(2); + } else { + } + println("Test node optimization within an if_failed branch"); + some_func_test.execute(); + if (!some_func_test.pass) { + if (ALARM == 1) { + } else { + } + if (ALARMENABLED == 1) { + } else { + } + } + cc_test_0.execute(); + cc_test_1.execute(); + cc_test_2.execute(); + DEEP_NESTED.execute(); + DEEP_TEST_FAILED = DEEP_NESTED.DEEP_TEST_FAILED; + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/TEST.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/TEST.flow new file mode 100644 index 00000000..294cea63 --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/TEST.flow @@ -0,0 +1,164 @@ +flow TEST { + + + setup { + suite meas_read_pump calls dc_tml.DcTest.GeneralPMU { + measurement.pattern = setupRef(OrigenTesters.patterns.meas_read_pump); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + forceMode = "VOLT"; + forceValue = "3.8[V]"; + measureMode = "PPMUpar"; + output = "None"; + pinlist = "@"; + ppmuClampHigh = "0[V]"; + ppmuClampLow = "0[V]"; + precharge = "OFF"; + prechargeVoltage = "0[V]"; + relaySwitchMode = "DEFAULT(BBM)"; + settlingTime = "0[s]"; + spmuClamp = "0[A]"; + termination = "OFF"; + testName = "passLimit_uA_mV"; + testerState = "CONNECTED"; + } + + suite meas_read_pump_1 calls dc_tml.DcTest.GeneralPMU { + measurement.pattern = setupRef(OrigenTesters.patterns.meas_read_pump); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + forceMode = "VOLT"; + forceValue = "3.8[V]"; + measureMode = "PPMUpar"; + output = "None"; + pinlist = "@"; + ppmuClampHigh = "0[V]"; + ppmuClampLow = "0[V]"; + precharge = "OFF"; + prechargeVoltage = "0[V]"; + relaySwitchMode = "DEFAULT(BBM)"; + settlingTime = "0[s]"; + spmuClamp = "0[A]"; + termination = "OFF"; + testName = "passLimit_uA_mV"; + testerState = "CONNECTED"; + } + + suite meas_read_pump_2 calls dc_tml.DcTest.GeneralPMU { + measurement.pattern = setupRef(OrigenTesters.patterns.meas_read_pump); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + forceMode = "VOLT"; + forceValue = "3.8[V]"; + measureMode = "PPMUpar"; + output = "None"; + pinlist = "@"; + ppmuClampHigh = "0[V]"; + ppmuClampLow = "0[V]"; + precharge = "OFF"; + prechargeVoltage = "0[V]"; + relaySwitchMode = "DEFAULT(BBM)"; + settlingTime = "0[s]"; + spmuClamp = "0[A]"; + termination = "OFF"; + testName = "passLimit_uA_mV"; + testerState = "CONNECTED"; + } + + suite meas_read_pump_3 calls dc_tml.DcTest.GeneralPMU { + measurement.pattern = setupRef(OrigenTesters.patterns.meas_read_pump); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + forceMode = "VOLT"; + forceValue = "3.8[V]"; + measureMode = "PPMUpar"; + output = "None"; + pinlist = "@"; + ppmuClampHigh = "0[V]"; + ppmuClampLow = "0[V]"; + precharge = "OFF"; + prechargeVoltage = "0[V]"; + relaySwitchMode = "DEFAULT(BBM)"; + settlingTime = "0[s]"; + spmuClamp = "0[A]"; + termination = "OFF"; + testName = "passLimit_uA_mV"; + testerState = "CONNECTED"; + } + + suite meas_read_pump_4 calls dc_tml.DcTest.GeneralPMU { + measurement.pattern = setupRef(OrigenTesters.patterns.meas_read_pump); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + forceMode = "VOLT"; + forceValue = "3.8[V]"; + measureMode = "PPMUpar"; + output = "None"; + pinlist = "@"; + ppmuClampHigh = "0[V]"; + ppmuClampLow = "0[V]"; + precharge = "OFF"; + prechargeVoltage = "0[V]"; + relaySwitchMode = "DEFAULT(BBM)"; + settlingTime = "0[s]"; + spmuClamp = "0[A]"; + termination = "OFF"; + testName = "passLimit_uA_mV"; + testerState = "CONNECTED"; + } + + suite meas_read_pump_5 calls dc_tml.DcTest.GeneralPMU { + measurement.pattern = setupRef(OrigenTesters.patterns.meas_read_pump); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + forceMode = "VOLT"; + forceValue = "3.8[V]"; + measureMode = "PPMUpar"; + output = "None"; + pinlist = "@"; + ppmuClampHigh = "0[V]"; + ppmuClampLow = "0[V]"; + precharge = "OFF"; + prechargeVoltage = "0[V]"; + relaySwitchMode = "DEFAULT(BBM)"; + settlingTime = "0[s]"; + spmuClamp = "0[A]"; + termination = "OFF"; + testName = "passLimit_uA_mV"; + testerState = "CONNECTED"; + } + + suite meas_read_pump_6 calls dc_tml.DcTest.GeneralPMU { + measurement.pattern = setupRef(OrigenTesters.patterns.meas_read_pump); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + forceMode = "VOLT"; + forceValue = "3.8[V]"; + measureMode = "PPMUpar"; + output = "None"; + pinlist = "@"; + ppmuClampHigh = "0[V]"; + ppmuClampLow = "0[V]"; + precharge = "OFF"; + prechargeVoltage = "0[V]"; + relaySwitchMode = "DEFAULT(BBM)"; + settlingTime = "0[s]"; + spmuClamp = "0[A]"; + termination = "OFF"; + testName = "passLimit_uA_mV"; + testerState = "CONNECTED"; + } + + suite program_ckbd calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + } + + execute { + program_ckbd.execute(); + meas_read_pump.execute(); + meas_read_pump_1.execute(); + meas_read_pump_2.execute(); + meas_read_pump_3.execute(); + meas_read_pump_4.execute(); + meas_read_pump_5.execute(); + meas_read_pump_6.execute(); + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/100MHZ_TESTS.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/100MHZ_TESTS.flow new file mode 100644 index 00000000..56e111d0 --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/100MHZ_TESTS.flow @@ -0,0 +1,16 @@ +flow 100MHZ_TESTS { + + out G100_RAN = -1; + + setup { + } + + execute { + G100_RAN = -1; + + G100_RAN = 1; + test100_1.execute(); + test100_2.execute(); + test100_3.execute(); + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/200MHZ_TESTS.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/200MHZ_TESTS.flow new file mode 100644 index 00000000..209a4144 --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/200MHZ_TESTS.flow @@ -0,0 +1,12 @@ +flow 200MHZ_TESTS { + + + setup { + } + + execute { + test200_1.execute(); + test200_2.execute(); + test200_3.execute(); + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/ADDITIONAL_ERASE.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/ADDITIONAL_ERASE.flow new file mode 100644 index 00000000..d6f1e151 --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/ADDITIONAL_ERASE.flow @@ -0,0 +1,21 @@ +flow ADDITIONAL_ERASE { + in ADDITIONAL_ERASE = -1; + + + setup { + suite erase_all calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + } + + execute { + if (ADDITIONAL_ERASE == 1) { + erase_all.execute(); + } else { + } + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/ADDITIONAL_ERASE_1.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/ADDITIONAL_ERASE_1.flow new file mode 100644 index 00000000..881d614e --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/ADDITIONAL_ERASE_1.flow @@ -0,0 +1,17 @@ +flow ADDITIONAL_ERASE_1 { + + + setup { + suite erase_all calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + } + + execute { + erase_all.execute(); + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/DEEP_NESTED.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/DEEP_NESTED.flow new file mode 100644 index 00000000..45d858cc --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/DEEP_NESTED.flow @@ -0,0 +1,16 @@ +flow DEEP_NESTED { + + out DEEP_TEST_FAILED = -1; + + setup { + } + + execute { + DEEP_TEST_FAILED = -1; + + deep_test.execute(); + if (!deep_test.pass) { + DEEP_TEST_FAILED = 1; + } + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/ERASE.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/ERASE.flow new file mode 100644 index 00000000..9fa5af84 --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/ERASE.flow @@ -0,0 +1,63 @@ +flow ERASE { + + out ERS_VFY_FAILED = -1; + + setup { + suite erase_all calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_2 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_3 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_4 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_5 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + flow ERASE_VFY calls OrigenTesters.flows.prb1.prb1_main.erase.ERASE_VFY { } + } + + execute { + ERS_VFY_FAILED = -1; + + erase_all.execute(); + erase_all_1.execute(); + erase_all_2.execute(); + erase_all_3.execute(); + erase_all_4.execute(); + erase_all_5.execute(); + ERASE_VFY.execute(); + ERS_VFY_FAILED = ERASE_VFY.ERS_VFY_FAILED; + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/ERASE_1.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/ERASE_1.flow new file mode 100644 index 00000000..5fb25492 --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/ERASE_1.flow @@ -0,0 +1,47 @@ +flow ERASE_1 { + + out ERS_VFY_FAILED = -1; + + setup { + suite erase_all calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_2 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite erase_all_3 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.erase_all); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + flow ERASE_VFY calls OrigenTesters.flows.prb1.prb1_main.erase_1.ERASE_VFY { } + } + + execute { + ERS_VFY_FAILED = -1; + + erase_all.execute(); + erase_all_1.execute(); + erase_all_2.execute(); + erase_all_3.execute(); + ERASE_VFY.execute(); + ERS_VFY_FAILED = ERASE_VFY.ERS_VFY_FAILED; + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/PROGRAM_CKBD.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/PROGRAM_CKBD.flow new file mode 100644 index 00000000..67ca3fc5 --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/PROGRAM_CKBD.flow @@ -0,0 +1,33 @@ +flow PROGRAM_CKBD { + + + setup { + suite program_ckbd calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd_b0); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite program_ckbd_1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd_b1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite program_ckbd_2 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd_b2); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + } + + execute { + program_ckbd.execute(); + program_ckbd_1.execute(); + program_ckbd_2.execute(); + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/PROGRAM_CKBD_1.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/PROGRAM_CKBD_1.flow new file mode 100644 index 00000000..bf481c82 --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/PROGRAM_CKBD_1.flow @@ -0,0 +1,33 @@ +flow PROGRAM_CKBD_1 { + + + setup { + suite program_ckbd calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd_b0); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite program_ckbd_1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd_b1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite program_ckbd_2 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd_b2); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + } + + execute { + program_ckbd.execute(); + program_ckbd_1.execute(); + program_ckbd_2.execute(); + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/PROGRAM_CKBD_2.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/PROGRAM_CKBD_2.flow new file mode 100644 index 00000000..b29ad48f --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/PROGRAM_CKBD_2.flow @@ -0,0 +1,33 @@ +flow PROGRAM_CKBD_2 { + + + setup { + suite program_ckbd calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd_b0); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite program_ckbd_1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd_b1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite program_ckbd_2 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd_b2); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + } + + execute { + program_ckbd.execute(); + program_ckbd_1.execute(); + program_ckbd_2.execute(); + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/PROGRAM_CKBD_3.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/PROGRAM_CKBD_3.flow new file mode 100644 index 00000000..529f4d58 --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/PROGRAM_CKBD_3.flow @@ -0,0 +1,33 @@ +flow PROGRAM_CKBD_3 { + + + setup { + suite program_ckbd calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd_b0); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite program_ckbd_1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd_b1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite program_ckbd_2 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.program_ckbd_b2); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + } + + execute { + program_ckbd.execute(); + program_ckbd_1.execute(); + program_ckbd_2.execute(); + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/erase/ERASE_VFY.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/erase/ERASE_VFY.flow new file mode 100644 index 00000000..c3b7a4b5 --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/erase/ERASE_VFY.flow @@ -0,0 +1,23 @@ +flow ERASE_VFY { + + out ERS_VFY_FAILED = -1; + + setup { + suite margin_read1_all1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + } + + execute { + ERS_VFY_FAILED = -1; + + margin_read1_all1.execute(); + if (!margin_read1_all1.pass) { + ERS_VFY_FAILED = 1; + } + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/erase_1/ERASE_VFY.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/erase_1/ERASE_VFY.flow new file mode 100644 index 00000000..c3b7a4b5 --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb1/prb1_main/erase_1/ERASE_VFY.flow @@ -0,0 +1,23 @@ +flow ERASE_VFY { + + out ERS_VFY_FAILED = -1; + + setup { + suite margin_read1_all1 calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.margin_read1_all1); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + } + + execute { + ERS_VFY_FAILED = -1; + + margin_read1_all1.execute(); + if (!margin_read1_all1.pass) { + ERS_VFY_FAILED = 1; + } + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb2/PRB2_MAIN.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb2/PRB2_MAIN.flow new file mode 100644 index 00000000..8bcfb63d --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb2/PRB2_MAIN.flow @@ -0,0 +1,25 @@ +flow PRB2_MAIN { + + + setup { + suite mrd_ckbd calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.mrd_ckbd); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite pgm_ckbd calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.pgm_ckbd); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + } + + execute { + pgm_ckbd.execute(); + mrd_ckbd.execute(); + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb2/PRB2_MAIN_1.flow b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb2/PRB2_MAIN_1.flow new file mode 100644 index 00000000..09a9ec6b --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/flows/prb2/PRB2_MAIN_1.flow @@ -0,0 +1,25 @@ +flow PRB2_MAIN_1 { + + + setup { + suite mrd_ckbd calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.mrd_ckbd); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + suite pgm_ckbd calls ac_tml.AcTest.FunctionalTest { + measurement.pattern = setupRef(OrigenTesters.patterns.pgm_ckbd); + measurement.specification = setupRef(OrigenTesters.specs.specs.Nominal); + output = "None"; + testName = "Functional"; + } + + } + + execute { + pgm_ckbd.execute(); + mrd_ckbd.execute(); + } +} diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/limits/Main.PRB1_Tests.csv b/test_apps/python_app/approved/v93ksmt8/test_program/limits/Main.PRB1_Tests.csv new file mode 100644 index 00000000..f23a9893 --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/limits/Main.PRB1_Tests.csv @@ -0,0 +1,113 @@ +Test Suite,Test,Test Number,Test Text,Low Limit,High Limit,Unit,Soft Bin +,,,,default,default +PRB1_MAIN.program_ckbd,PGM_CKBD,1000,program_ckbd.PGM_CKBD,0,0,,1100 +PRB1_MAIN.margin_read1_ckbd,margin_read1_ckbd,1010,margin_read1_ckbd,0,0,, +PRB1_MAIN.margin_read0_ckbd,margin_read0_ckbd,1030,margin_read0_ckbd,0,0,, +PRB1_MAIN.ERASE.erase_all,erase_all,2000,erase_all,0,0,, +PRB1_MAIN.ERASE.erase_all_1,erase_all_1,2010,erase_all_1,0,0,, +PRB1_MAIN.ERASE.erase_all_2,erase_all_2,2030,erase_all_2,0,0,, +PRB1_MAIN.ERASE.erase_all_3,erase_all_3,2060,erase_all_3,0,0,, +PRB1_MAIN.ERASE.erase_all_4,erase_all_4,2100,erase_all_4,0,0,, +PRB1_MAIN.ERASE.erase_all_5,erase_all_5,2150,erase_all_5,0,0,, +PRB1_MAIN.ERASE.ERASE_VFY.margin_read1_all1,margin_read1_all1,2210,margin_read1_all1,0,0,, +PRB1_MAIN.program_ckbd_1,program_ckbd_1,3000,program_ckbd_1,0,0,, +PRB1_MAIN.program_ckbd_2,program_ckbd_2,3010,program_ckbd_2,0,0,, +PRB1_MAIN.program_ckbd_3,program_ckbd_3,3020,program_ckbd_3,0,0,, +PRB1_MAIN.program_ckbd_4,program_ckbd_4,3030,program_ckbd_4,0,0,, +PRB1_MAIN.PROGRAM_CKBD.program_ckbd,program_ckbd,3040,program_ckbd,0,0,, +PRB1_MAIN.PROGRAM_CKBD.program_ckbd_1,program_ckbd_1,3041,program_ckbd_1,0,0,, +PRB1_MAIN.PROGRAM_CKBD.program_ckbd_2,program_ckbd_2,3042,program_ckbd_2,0,0,, +PRB1_MAIN.PROGRAM_CKBD_1.program_ckbd,program_ckbd,3050,program_ckbd,0,0,, +PRB1_MAIN.PROGRAM_CKBD_1.program_ckbd_1,program_ckbd_1,3051,program_ckbd_1,0,0,, +PRB1_MAIN.PROGRAM_CKBD_1.program_ckbd_2,program_ckbd_2,3052,program_ckbd_2,0,0,, +PRB1_MAIN.PROGRAM_CKBD_2.program_ckbd,program_ckbd,3060,program_ckbd,0,0,, +PRB1_MAIN.PROGRAM_CKBD_2.program_ckbd_1,program_ckbd_1,3061,program_ckbd_1,0,0,, +PRB1_MAIN.PROGRAM_CKBD_2.program_ckbd_2,program_ckbd_2,3062,program_ckbd_2,0,0,, +PRB1_MAIN.PROGRAM_CKBD_3.program_ckbd,program_ckbd,3070,program_ckbd,0,0,, +PRB1_MAIN.PROGRAM_CKBD_3.program_ckbd_1,program_ckbd_1,3071,program_ckbd_1,0,0,, +PRB1_MAIN.PROGRAM_CKBD_3.program_ckbd_2,program_ckbd_2,3072,program_ckbd_2,0,0,, +PRB1_MAIN.p1_only_test,p1_only_test,3080,p1_only_test,0,0,, +PRB1_MAIN.p1_or_p2_only_test,p1_or_p2_only_test,3090,p1_or_p2_only_test,0,0,, +PRB1_MAIN.not_p1_test,not_p1_test,3100,not_p1_test,0,0,, +PRB1_MAIN.not_p1_or_p2_test,not_p1_or_p2_test,3110,not_p1_or_p2_test,0,0,, +PRB1_MAIN.another_not_p1_or_p2_test,another_not_p1_or_p2_test,3120,another_not_p1_or_p2_test,0,0,, +PRB1_MAIN.por_ins,por_ins,3130,por_ins,0,0,, +PRB1_MAIN.erase_all,erase_all,3140,erase_all,0,0,, +PRB1_MAIN.erase_all_1,erase_all_1,3150,erase_all_1,0,0,, +PRB1_MAIN.erase_all_2,erase_all_2,3160,erase_all_2,0,0,, +PRB1_MAIN.erase_all_3,erase_all_3,3170,erase_all_3,0,0,, +PRB1_MAIN.erase_all_4,erase_all_4,3180,erase_all_4,0,0,, +PRB1_MAIN.margin_read1_all1,margin_read1_all1,3200,margin_read1_all1,0,0,, +PRB1_MAIN.erase_all_5,erase_all_5,3210,erase_all_5,0,0,, +PRB1_MAIN.margin_read1_all1_1,margin_read1_all1_1,3220,margin_read1_all1_1,0,0,, +PRB1_MAIN.erase_all_6,erase_all_6,3230,erase_all_6,0,0,, +PRB1_MAIN.margin_read1_all1_2,margin_read1_all1_2,3240,margin_read1_all1_2,0,0,, +PRB1_MAIN.erase_all_7,erase_all_7,3250,erase_all_7,0,0,, +PRB1_MAIN.margin_read1_all1_3,margin_read1_all1_3,3260,margin_read1_all1_3,0,0,, +PRB1_MAIN.erase_all_8,erase_all_8,3270,erase_all_8,0,0,, +PRB1_MAIN.margin_read1_all1_4,margin_read1_all1_4,3280,margin_read1_all1_4,0,0,, +PRB1_MAIN.erase_all_9,erase_all_9,3290,erase_all_9,0,0,, +PRB1_MAIN.margin_read1_all1_5,margin_read1_all1_5,4000,margin_read1_all1_5,0,0,, +PRB1_MAIN.erase_all_10,erase_all_10,4010,erase_all_10,0,0,, +PRB1_MAIN.erase_all_11,erase_all_11,4020,erase_all_11,0,0,, +PRB1_MAIN.erase_all_12,erase_all_12,4030,erase_all_12,0,0,, +PRB1_MAIN.erase_all_13,erase_all_13,4040,erase_all_13,0,0,, +PRB1_MAIN.erase_all_14,erase_all_14,4050,erase_all_14,0,0,, +PRB1_MAIN.erase_all_15,erase_all_15,4060,erase_all_15,0,0,, +PRB1_MAIN.erase_all_16,erase_all_16,4070,erase_all_16,0,0,, +PRB1_MAIN.erase_all_17,erase_all_17,4080,erase_all_17,0,0,, +PRB1_MAIN.erase_all_18,erase_all_18,4090,erase_all_18,0,0,, +PRB1_MAIN.margin_read1_all1_6,margin_read1_all1_6,4100,margin_read1_all1_6,0,0,, +PRB1_MAIN.margin_read1_all1_7,margin_read1_all1_7,4110,margin_read1_all1_7,0,0,, +PRB1_MAIN.erase_all_19,erase_all_19,4120,erase_all_19,0,0,, +PRB1_MAIN.erase_all_20,erase_all_20,4130,erase_all_20,0,0,, +PRB1_MAIN.margin_read1_all1_8,margin_read1_all1_8,4140,margin_read1_all1_8,0,0,, +PRB1_MAIN.margin_read1_all1_9,margin_read1_all1_9,4150,margin_read1_all1_9,0,0,, +PRB1_MAIN.erase_all_21,erase_all_21,4160,erase_all_21,0,0,, +PRB1_MAIN.erase_all_22,erase_all_22,4170,erase_all_22,0,0,, +PRB1_MAIN.margin_read1_all1_10,margin_read1_all1_10,4180,margin_read1_all1_10,0,0,, +PRB1_MAIN.margin_read1_all1_11,margin_read1_all1_11,4190,margin_read1_all1_11,0,0,, +PRB1_MAIN.erase_all_23,erase_all_23,4200,erase_all_23,0,0,, +PRB1_MAIN.erase_all_24,erase_all_24,4210,erase_all_24,0,0,, +PRB1_MAIN.margin_read1_all1_12,margin_read1_all1_12,4220,margin_read1_all1_12,0,0,, +PRB1_MAIN.margin_read1_all1_13,margin_read1_all1_13,4230,margin_read1_all1_13,0,0,, +PRB1_MAIN.erase_all_25,erase_all_25,4240,erase_all_25,0,0,, +PRB1_MAIN.erase_all_26,erase_all_26,4250,erase_all_26,0,0,, +PRB1_MAIN.margin_read1_all1_14,margin_read1_all1_14,4260,margin_read1_all1_14,0,0,, +PRB1_MAIN.margin_read1_all1_15,margin_read1_all1_15,4270,margin_read1_all1_15,0,0,, +PRB1_MAIN.erase_all_27,erase_all_27,4280,erase_all_27,0,0,, +PRB1_MAIN.erase_all_28,erase_all_28,4290,erase_all_28,0,0,, +PRB1_MAIN.margin_read1_all1_16,margin_read1_all1_16,4300,margin_read1_all1_16,0,0,, +PRB1_MAIN.margin_read1_all1_17,margin_read1_all1_17,4310,margin_read1_all1_17,0,0,, +PRB1_MAIN.ERASE_1.erase_all,erase_all,5000,erase_all,0,0,, +PRB1_MAIN.ERASE_1.erase_all_1,erase_all_1,5010,erase_all_1,0,0,, +PRB1_MAIN.ERASE_1.erase_all_2,erase_all_2,5030,erase_all_2,0,0,, +PRB1_MAIN.ERASE_1.erase_all_3,erase_all_3,5060,erase_all_3,0,0,, +PRB1_MAIN.ERASE_1.ERASE_VFY.margin_read1_all1,margin_read1_all1,5100,margin_read1_all1,0,0,, +PRB1_MAIN.ADDITIONAL_ERASE.erase_all,erase_all,5500,erase_all,0,0,, +PRB1_MAIN.ADDITIONAL_ERASE_1.erase_all,erase_all,5600,erase_all,0,0,, +PRB1_MAIN.margin_read1_all1_18,margin_read1_all1_18,5700,margin_read1_all1_18,0,0,, +PRB1_MAIN.xcvr_fs_vilvih,xcvr_fs_vilvih,5710,xcvr_fs_vilvih,0,0,, +PRB1_MAIN.xcvr_fs_vilvih_1,xcvr_fs_vilvih_1,5720,xcvr_fs_vilvih_1,0,0,, +PRB1_MAIN.xcvr_fs_vilvih_2,xcvr_fs_vilvih_2,5730,xcvr_fs_vilvih_2,0,0,, +PRB1_MAIN.xcvr_fs_vilvih_3,xcvr_fs_vilvih_3,5740,xcvr_fs_vilvih_3,0,0,, +PRB1_MAIN.200MHZ_TESTS.test200_1,test200_1,5950,test200_1,0,0,, +PRB1_MAIN.200MHZ_TESTS.test200_2,test200_2,5960,test200_2,0,0,, +PRB1_MAIN.200MHZ_TESTS.test200_3,test200_3,5970,test200_3,0,0,, +PRB1_MAIN.100MHZ_TESTS.test100_1,test100_1,5980,test100_1,0,0,, +PRB1_MAIN.100MHZ_TESTS.test100_2,test100_2,5990,test100_2,0,0,, +PRB1_MAIN.100MHZ_TESTS.test100_3,test100_3,6000,test100_3,0,0,, +PRB1_MAIN.some_func_test,some_func_test,6010,some_func_test,0,0,, +PRB1_MAIN.cc_test_0,cc_test_0,7000,cc_test_0,0,0,, +PRB1_MAIN.cc_test_1,cc_test_1,7001,cc_test_1,0,0,, +PRB1_MAIN.cc_test_2,cc_test_2,7002,cc_test_2,0,0,, +PRB1_MAIN.DEEP_NESTED.deep_test,deep_test,,deep_test,0,0,, +TEST.program_ckbd,program_ckbd,40000,program_ckbd,0,0,,1100 +TEST.meas_read_pump,meas_read_pump,40005,meas_read_pump,35,,,2 +TEST.meas_read_pump_1,meas_read_pump_1,40010,meas_read_pump_1,,45,,2 +TEST.meas_read_pump_2,meas_read_pump_2,40020,meas_read_pump_2,35,45,,2 +TEST.meas_read_pump_3,meas_read_pump_3,40030,meas_read_pump_3,35,45,,2 +TEST.meas_read_pump_4,meas_read_pump_4,40040,meas_read_pump_4,0.035,0.045,,2 +TEST.meas_read_pump_5,meas_read_pump_5,40050,meas_read_pump_5,0.035,0.045,, +TEST.meas_read_pump_6,meas_read_pump_6,40060,meas_read_pump_6,0.01,2000,, +on_deep_1,on_deep_1,,on_deep_1,0,0,, diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/limits/Main.PRB2_Tests.csv b/test_apps/python_app/approved/v93ksmt8/test_program/limits/Main.PRB2_Tests.csv new file mode 100644 index 00000000..e86efa11 --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/limits/Main.PRB2_Tests.csv @@ -0,0 +1,13 @@ +Test Suite,Test,Test Number,Test Text,Low Limit,High Limit,Unit,Soft Bin +,,,,default,default +erase_all,erase_all,10000,erase_all,0,0,, +margin_read1_all1,margin_read1_all1,10010,margin_read1_all1,0,0,, +erase_all_1,erase_all_1,10020,erase_all_1,0,0,, +margin_read1_all1_1,margin_read1_all1_1,10030,margin_read1_all1_1,0,0,, +PRB2_MAIN.pgm_ckbd,pgm_ckbd,11010,pgm_ckbd,0,0,, +PRB2_MAIN.mrd_ckbd,mrd_ckbd,11020,mrd_ckbd,0,0,, +erase_all_2,erase_all_2,12000,erase_all_2,0,0,, +margin_read1_all1_2,margin_read1_all1_2,12010,margin_read1_all1_2,0,0,, +PRB2_MAIN_1.pgm_ckbd,pgm_ckbd,13010,pgm_ckbd,0,0,, +PRB2_MAIN_1.mrd_ckbd,mrd_ckbd,13020,mrd_ckbd,0,0,, +margin_read1_all1_3,margin_read1_all1_3,14000,margin_read1_all1_3,0,0,, diff --git a/test_apps/python_app/approved/v93ksmt8/test_program/referenced.list b/test_apps/python_app/approved/v93ksmt8/test_program/referenced.list new file mode 100644 index 00000000..9050fb4f --- /dev/null +++ b/test_apps/python_app/approved/v93ksmt8/test_program/referenced.list @@ -0,0 +1,27 @@ +another_not_p1_or_p2_test +bitcell_iv_0 +bitcell_iv_1 +bitcell_iv_2 +bitmap_all0 +cc_test_0 +cc_test_1 +cc_test_2 +erase_all +margin_read0_ckbd +margin_read1_all1 +margin_read1_ckbd +meas_read_pump +mrd_ckbd +normal_read_ckbd +not_p1_or_p2_test +not_p1_test +p1_only_test +p1_or_p2_only_test +pgm_ckbd +por_ins +program_ckbd +program_ckbd_b0 +program_ckbd_b1 +program_ckbd_b2 +some_func_test +xcvr_fs_vilvih diff --git a/test_apps/python_app/example/commands/examples.py b/test_apps/python_app/example/commands/examples.py index e7797d06..80d05cf6 100644 --- a/test_apps/python_app/example/commands/examples.py +++ b/test_apps/python_app/example/commands/examples.py @@ -23,7 +23,7 @@ def run(**kwargs): "reference_dir": "approved", }, debug=debug, - targets=["dut/o1_dut", "tester/v93k_smt7"]) + targets=["dut/o1_dut", "tester/v93k_smt7", "tester/v93k_smt8"]) stats = origen.tester.stats() diff --git a/test_apps/python_app/example/flows/o1_testcases/components/deep_nested.py b/test_apps/python_app/example/flows/o1_testcases/components/deep_nested.py index a61c8de3..aa667c2a 100644 --- a/test_apps/python_app/example/flows/o1_testcases/components/deep_nested.py +++ b/test_apps/python_app/example/flows/o1_testcases/components/deep_nested.py @@ -1,2 +1,2 @@ with Flow() as flow: - flow.add_test("deep_test", id="deep_test") + flow.add_test("deep_test", id="deep_test", tname='some_custom_text') diff --git a/test_apps/python_app/example/flows/o1_testcases/components/prb1_main.py b/test_apps/python_app/example/flows/o1_testcases/components/prb1_main.py index 75e0d8cf..f62e50d5 100644 --- a/test_apps/python_app/example/flows/o1_testcases/components/prb1_main.py +++ b/test_apps/python_app/example/flows/o1_testcases/components/prb1_main.py @@ -3,7 +3,7 @@ # interface flow.func('program_ckbd', tname='PGM_CKBD', - tnum=1000, + number=1000, bin=100, soft_bin=1100) flow.func('margin_read1_ckbd', number=1010) @@ -187,27 +187,27 @@ flow.log('direct call') flow.meas("bgap_voltage_meas", - tnum=1050, + number=1050, bin=119, soft_bin=2, hi_limit=45, - number=5910) + ) flow.meas("bgap_voltage_meas1", number=5920) with tester().eq("j750"): - flow.meas("lo_voltage", tnum=1150, bin=95, soft_bin=5, number=5920) + flow.meas("lo_voltage", number=1150, bin=95, soft_bin=5) flow.meas("hi_voltage", pins="hi_v", - tnum=1160, + number=1160, bin=96, - soft_bin=6, - number=5930) + soft_bin=6 + ) flow.meas("ps_leakage", pins="power", - tnum=1170, + number=1170, bin=97, soft_bin=6, - number=5940) + ) flow.log('Speed binning example bug from video 5') with flow.group("200Mhz Tests", id="g200"): diff --git a/test_apps/python_app/example/flows/o1_testcases/prb1.py b/test_apps/python_app/example/flows/o1_testcases/prb1.py index 225672b0..fe6a2be6 100644 --- a/test_apps/python_app/example/flows/o1_testcases/prb1.py +++ b/test_apps/python_app/example/flows/o1_testcases/prb1.py @@ -1,4 +1,4 @@ -with Flow(flow_description="Probe1 Main") as flow: +with Flow(flow_description="Probe1 Main", namespace="OrigenTesters") as flow: #unless Origen.app.environment.name == 'v93k_global' flow.set_resources_filename('prb1') @@ -15,8 +15,9 @@ test_text="some_custom_text", id="deep_test_1") - with flow.if_failed("deep_test_1"): - flow.render_str("multi_bin;") + with tester().neq("v93ksmt8"): + with flow.if_failed("deep_test_1"): + flow.render_str("multi_bin;") flow.good_die(1, description="Good die!", softbin=1) diff --git a/test_apps/python_app/example/flows/o1_testcases/prb2.py b/test_apps/python_app/example/flows/o1_testcases/prb2.py index c2ee1003..bd57aa17 100644 --- a/test_apps/python_app/example/flows/o1_testcases/prb2.py +++ b/test_apps/python_app/example/flows/o1_testcases/prb2.py @@ -1,5 +1,6 @@ with Flow(bypass_sub_flows=True, add_flow_enable="enabled", + namespace="OrigenTesters", environment="probe") as flow: flow.name_override = 'prb2' # simple override to avoid uppercase flow.description = ''' diff --git a/test_apps/python_app/example/flows/o1_testcases/test.py b/test_apps/python_app/example/flows/o1_testcases/test.py index 39671a2f..910881ac 100644 --- a/test_apps/python_app/example/flows/o1_testcases/test.py +++ b/test_apps/python_app/example/flows/o1_testcases/test.py @@ -8,43 +8,38 @@ flow.description = '' #if tester.v93k? && tester.create_limits_file - # flow.func("program_ckbd", bin=100, soft_bin=1100, number=40000) + with tester().eq("v93ksmt8"): + flow.func("program_ckbd", bin=100, soft_bin=1100, number=40000) flow.meas("read_pump", - tnum=1050, bin=119, soft_bin=2, lo_limit=35, number=40005) flow.meas("read_pump", - tnum=1060, bin=119, soft_bin=2, hi_limit=45, number=40010) flow.meas("read_pump", - tnum=1070, bin=119, soft_bin=2, hi_limit=45, lo_limit=35, number=40020) flow.meas("read_pump", - tnum=1080, bin=119, soft_bin=2, hi_limit=45, lo_limit=35, number=40030) flow.meas("read_pump", - tnum=1090, bin=119, soft_bin=2, hi_limit=45 * mV, lo_limit=35 * mV, number=40040) flow.meas("read_pump", - tnum=1100, bin=119, soft_bin=2, hi_limit=45 * mV, @@ -52,7 +47,6 @@ continue_on_fail=True, number=40050) flow.meas("read_pump", - tnum=1110, bin=119, soft_bin=2, hi_limit=2000, @@ -61,34 +55,32 @@ number=40060) #unless tester.v93k? && tester.create_limits_file - flow.meas("read_pump", - tnum=1120, - bin=119, - soft_bin=2, - hi_limit="_some_spec", - lo_limit=0.01, - continue_on_fail=True, - number=40070) - flow.meas("read_pump", - tnum=1130, - bin=119, - soft_bin=2, - hi_limit=[1, 2], - number=40080) - flow.meas("read_pump", - tnum=1140, - bin=119, - soft_bin=2, - lo_limit=[1 * uA, 2 * uA, 3 * uA], - hi_limit=[4 * uA, 5e-06], - units="A", - defer_limits=True, - number=40090) + with tester().neq("v93ksmt8"): + flow.meas("read_pump", + bin=119, + soft_bin=2, + hi_limit="_some_spec", + lo_limit=0.01, + continue_on_fail=True, + number=40070) + flow.meas("read_pump", + bin=119, + soft_bin=2, + hi_limit=[1, 2], + number=40080) + flow.meas("read_pump", + bin=119, + soft_bin=2, + lo_limit=[1 * uA, 2 * uA, 3 * uA], + hi_limit=[4 * uA, 5e-06], + units="A", + defer_limits=True, + number=40090) # TODO: implement this when test case is imported #with tester().eq("uflex"): - # meas_multi_limits("bin_now", tnum=3000, bin=119, soft_bin=2) - # meas_multi_limits("bin_later", tnum=3000, bin=119, soft_bin=2, defer_limits=True) + # meas_multi_limits("bin_now", number=3000, bin=119, soft_bin=2) + # meas_multi_limits("bin_later", number=3000, bin=119, soft_bin=2, defer_limits=True) # log("Test of ultraflex render API") # line = flow.ultraflex.use_limit # line.units = "Hz" diff --git a/test_apps/python_app/example/interface/interface.py b/test_apps/python_app/example/interface/interface.py index d680e476..ca55d795 100644 --- a/test_apps/python_app/example/interface/interface.py +++ b/test_apps/python_app/example/interface/interface.py @@ -1,8 +1,12 @@ import origen from origen.interface import BaseInterface, dut, tester -from contextlib import contextmanager, ContextDecorator +from contextlib import contextmanager +from origen_metal._origen_metal import prog_gen as origen_prog_gen #import pdb; pdb.set_trace() +# Make some templates for SMT8 available +load_path = [origen.app.root.joinpath("example", "interface", "test_templates")] +origen_prog_gen.set_test_template_load_path(load_path) class Interface(BaseInterface): #def func(self, name): @@ -36,8 +40,6 @@ def func_igxl(i, block, **kwargs): nonlocal number nonlocal igxl nonlocal group - if number and i: - number += i ins = igxl.new_test_instance(name, library="std", template="functional", @@ -79,8 +81,6 @@ def func_v93k(i, block, **kwargs): nonlocal number nonlocal v93k nonlocal group - if number and i: - number += i tm = v93k.new_test_method("functional_test", library="ac_tml", allow_missing=True, @@ -88,6 +88,10 @@ def func_v93k(i, block, **kwargs): ts = v93k.new_test_suite(name, **kwargs) ts.test_method = tm with tester().eq("v93ksmt8"): + if number is not None: + ts.number = number + (i or 0) + ts.set_lo_limit(0) + ts.set_hi_limit(0) if kwargs.get("pin_levels"): ts.spec = kwargs.pop("pin_levels") else: @@ -166,7 +170,7 @@ def para(self, name, **kwargs): self.add_test(ins, **options) j750.new_patset(f"{name}_pset", pattern=f"{name}.PAT") - def meas(self, name, **kwargs): + def meas(self, name, number=None, **kwargs): options = {"duration": "static"} options.update(kwargs) @@ -232,6 +236,7 @@ def meas(self, name, **kwargs): ts = v93k.new_test_suite(name, **options) ts.test_method = tm with tester().eq("v93ksmt8"): + ts.number = number if kwargs.get("pin_levels"): ts.spec = kwargs.pop("pin_levels") else: diff --git a/test_apps/python_app/example/interface/test_templates/v93ksmt8/README.md b/test_apps/python_app/example/interface/test_templates/v93ksmt8/README.md new file mode 100644 index 00000000..a7289d2a --- /dev/null +++ b/test_apps/python_app/example/interface/test_templates/v93ksmt8/README.md @@ -0,0 +1,8 @@ +Not sure if there is a built in test method library for SMT8 like there +is for STM7. + +Just copied the SMT7 lib in here for use in the STM8 test cases, but it +doesn't make sense to build these into Origen. + +The interface adds this dir to the test library load path. + diff --git a/test_apps/python_app/example/interface/test_templates/v93ksmt8/ac_tml/frequency_by_digital_capture.json b/test_apps/python_app/example/interface/test_templates/v93ksmt8/ac_tml/frequency_by_digital_capture.json new file mode 100644 index 00000000..5813e2f0 --- /dev/null +++ b/test_apps/python_app/example/interface/test_templates/v93ksmt8/ac_tml/frequency_by_digital_capture.json @@ -0,0 +1,32 @@ +{ + "class_name": "ac_tml.AcTest.Frequency_byDigitalCapture", + + "parameters": { + "vectorVariableName": { + "type": "string" + }, + "algorithm": { + "type": "string", + "value": "FFT", + "accepted_values": ["FFT", "LinearFit"] + }, + "samplePeriod": { + "type": "time", + "value": 0 + }, + "targetFrequency": { + "type": "frequency", + "value": 0 + }, + "output": { + "type": "string", + "aliases": [], + "value": "None", + "accepted_values": ["None", "ReportUI", "ShowFailOnly"] + }, + "testName": { + "type": "string", + "value": "passFrequency_Mhz" + } + } +} \ No newline at end of file diff --git a/test_apps/python_app/example/interface/test_templates/v93ksmt8/ac_tml/functional_test.json b/test_apps/python_app/example/interface/test_templates/v93ksmt8/ac_tml/functional_test.json new file mode 100644 index 00000000..58d268e9 --- /dev/null +++ b/test_apps/python_app/example/interface/test_templates/v93ksmt8/ac_tml/functional_test.json @@ -0,0 +1,16 @@ +{ + "class_name": "ac_tml.AcTest.FunctionalTest", + + "parameters": { + "output": { + "type": "string", + "aliases": [], + "value": "None", + "accepted_values": ["None", "ReportUI", "ShowFailOnly"] + }, + "testName": { + "type": "string", + "value": "Functional" + } + } +} \ No newline at end of file diff --git a/test_apps/python_app/example/interface/test_templates/v93ksmt8/ac_tml/spec_search.json b/test_apps/python_app/example/interface/test_templates/v93ksmt8/ac_tml/spec_search.json new file mode 100644 index 00000000..242a100c --- /dev/null +++ b/test_apps/python_app/example/interface/test_templates/v93ksmt8/ac_tml/spec_search.json @@ -0,0 +1,40 @@ +{ + "class_name": "ac_tml.AcTest.SpecSearch", + + "parameters": { + "max": { + "type": "string" + }, + "method": { + "type": "string" + }, + "min": { + "type": "string" + }, + "resolution": { + "type": "string" + }, + "resultPinlist": { + "type": "string" + }, + "setupPinlist": { + "type": "string" + }, + "spec": { + "type": "string" + }, + "step": { + "type": "string" + }, + "output": { + "type": "string", + "aliases": [], + "value": "None", + "accepted_values": ["None", "ReportUI", "ShowFailOnly"] + }, + "testName": { + "type": "string", + "value": "SpecSearch_Test" + } + } +} \ No newline at end of file diff --git a/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/continuity.json b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/continuity.json new file mode 100644 index 00000000..695f7586 --- /dev/null +++ b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/continuity.json @@ -0,0 +1,50 @@ +{ + "class_name": "dc_tml.DcTest.Continuity", + + "parameters": { + "pinlist": { + "type": "string", + "aliases": ["pin_list"], + "value": "@" + }, + "testCurrent": { + "type": "current", + "aliases": [], + "value": 10e-6 + }, + "settlingTime": { + "type": "time", + "aliases": [], + "value": 1e-3 + }, + "measurementMode": { + "type": "string", + "aliases": [], + "value": "PPMUpar", + "accepted_values": ["PPMUpar", "ProgLoad"] + }, + "polarity": { + "type": "string", + "aliases": [], + "value": "SPOL", + "accepted_values": ["SPOL", "BPOL"] + }, + "prechargeToZeroVol": { + "type": "string", + "aliases": [], + "value": "ON", + "accepted_values": ["ON", "OFF"] + }, + "testName": { + "type": "string", + "aliases": [], + "value": "passVolt_mv" + }, + "output": { + "type": "string", + "aliases": [], + "value": "None", + "accepted_values": ["None", "ReportUI", "ShowFailOnly"] + } + } +} diff --git a/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/dps_connectivity.json b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/dps_connectivity.json new file mode 100644 index 00000000..753e13f1 --- /dev/null +++ b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/dps_connectivity.json @@ -0,0 +1,22 @@ +{ + "class_name": "dc_tml.DcTest.DpsConnectivity", + + "parameters": { + "dpsPins": { + "type": "string", + "aliases": [], + "value": "@" + }, + "testName": { + "type": "string", + "aliases": [], + "value": "DPS_ForceSense" + }, + "output": { + "type": "string", + "aliases": [], + "value": "None", + "accepted_values": ["None", "ReportUI", "ShowFailOnly"] + } + } +} diff --git a/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/dps_status.json b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/dps_status.json new file mode 100644 index 00000000..9e8e97ac --- /dev/null +++ b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/dps_status.json @@ -0,0 +1,46 @@ +{ + "class_name": "dc_tml.DcTest.DpsStatus", + + "parameters": { + "dpsPins": { + "type": "string", + "aliases": [], + "value": "@" + }, + "testName": { + "type": "string", + "aliases": [], + "value": "DPS_Status" + }, + "constantCurrent": { + "type": "string", + "aliases": [], + "value": "OFF", + "accepted_values": ["ON", "OFF"] + }, + "unregulated": { + "type": "string", + "aliases": [], + "value": "OFF", + "accepted_values": ["ON", "OFF"] + }, + "overVoltage": { + "type": "string", + "aliases": [], + "value": "OFF", + "accepted_values": ["ON", "OFF"] + }, + "overPowerTemp": { + "type": "string", + "aliases": [], + "value": "OFF", + "accepted_values": ["ON", "OFF"] + }, + "output": { + "type": "string", + "aliases": [], + "value": "None", + "accepted_values": ["None", "ReportUI", "ShowFailOnly"] + } + } +} diff --git a/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/dvm.json b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/dvm.json new file mode 100644 index 00000000..9875ff77 --- /dev/null +++ b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/dvm.json @@ -0,0 +1,33 @@ +{ + "class_name": "dc_tml.DcTest.DVM", + + "parameters": { + "pinlist": { + "type": "string", + "aliases": [], + "value": "@" + }, + "settlingTime": { + "type": "time", + "aliases": [], + "value": 0 + }, + "measureMode": { + "type": "string", + "aliases": [], + "value": "PPMUpar", + "accepted_values": ["PPMUpar", "ProgLoad"] + }, + "testName": { + "type": "string", + "aliases": [], + "value": "passVoltageLimit_mV" + }, + "output": { + "type": "string", + "aliases": [], + "value": "None", + "accepted_values": ["None", "ReportUI", "ShowFailOnly"] + } + } +} \ No newline at end of file diff --git a/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/general_pmu.json b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/general_pmu.json new file mode 100644 index 00000000..2169b0ca --- /dev/null +++ b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/general_pmu.json @@ -0,0 +1,80 @@ +{ + "class_name": "dc_tml.DcTest.GeneralPMU", + + "parameters": { + "pinlist": { + "type": "string", + "aliases": [], + "value": "@" + }, + "forceMode": { + "type": "string", + "aliases": [], + "value": "VOLT", + "accepted_values": ["VOLT", "CURR"] + }, + "forceValue": { + "type": "voltage", + "aliases": [], + "value": 3800e-3 + }, + "spmuClamp": { + "type": "current", + "value": 0 + }, + "precharge": { + "type": "string", + "value": "OFF", + "accepted_values": ["ON", "OFF"] + }, + "prechargeVoltage": { + "type": "voltage", + "value": 0 + }, + "settlingTime": { + "type": "time", + "value": 0 + }, + "testerState": { + "type": "string", + "value": "CONNECTED", + "accepted_values": ["CONNECTED", "DISCONNECTED", "UNCHANGED"] + }, + "termination": { + "type": "string", + "value": "OFF", + "accepted_values": ["ON", "OFF"] + }, + "measureMode": { + "type": "string", + "aliases": [], + "value": "PPMUpar", + "accepted_values": ["PPMUpar", "ProgLoad"] + }, + "relaySwitchMode": { + "type": "string", + "aliases": [], + "value": "DEFAULT(BBM)", + "accepted_values": ["DEFAULT(BBM)", "BBM", "MBB", "PARALLEL"] + }, + "ppmuClampLow": { + "type": "voltage", + "value": 0 + }, + "ppmuClampHigh": { + "type": "voltage", + "value": 0 + }, + "output": { + "type": "string", + "aliases": [], + "value": "None", + "accepted_values": ["None", "ReportUI", "ShowFailOnly"] + }, + "testName": { + "type": "string", + "aliases": [], + "value": "passLimit_uA_mV" + } + } +} \ No newline at end of file diff --git a/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/high_z.json b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/high_z.json new file mode 100644 index 00000000..7e4a31b8 --- /dev/null +++ b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/high_z.json @@ -0,0 +1,37 @@ +{ + "class_name": "dc_tml.DcTest.HighZ", + + "parameters": { + "pinlist": { + "type": "string", + "aliases": [], + "value": "@" + }, + "forceValue": { + "type": "voltage", + "aliases": [], + "value": 2500e-3 + }, + "settlingTime": { + "type": "time", + "value": 0 + }, + "relaySwitchMode": { + "type": "string", + "aliases": [], + "value": "DEFAULT(BBM)", + "accepted_values": ["DEFAULT(BBM)", "BBM", "MBB", "PARALLEL"] + }, + "output": { + "type": "string", + "aliases": [], + "value": "None", + "accepted_values": ["None", "ReportUI", "ShowFailOnly"] + }, + "testName": { + "type": "string", + "aliases": [], + "value": "passCurrent_uA" + } + } +} \ No newline at end of file diff --git a/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/leakage.json b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/leakage.json new file mode 100644 index 00000000..85bbb5fb --- /dev/null +++ b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/leakage.json @@ -0,0 +1,95 @@ +{ + "class_name": "dc_tml.DcTest.Leakage", + + "parameters": { + "pinlist": { + "type": "string", + "aliases": [], + "value": "@" + }, + "measure": { + "type": "string", + "aliases": [], + "value": "BOTH", + "accepted_values": ["BOTH", "LOW", "HIGH"] + }, + "forceVoltageLow": { + "type": "voltage", + "value": 400e-3 + }, + "forceVoltageHigh": { + "type": "voltage", + "value": 3800e-3 + }, + "spmuClampCurrentLow": { + "type": "current", + "value": 0 + }, + "spmuClampCurrentHigh": { + "type": "current", + "value": 0 + }, + "ppmuPreCharge": { + "type": "string", + "value": "ON", + "accepted_values": ["ON", "OFF"] + }, + "prechargeVoltageLow": { + "type": "voltage", + "value": 0 + }, + "prechargeVoltageHigh": { + "type": "voltage", + "value": 0 + }, + "settlingTimeLow": { + "type": "time", + "value": 0 + }, + "settlingTimeHigh": { + "type": "time", + "value": 0 + }, + "preFunction": { + "type": "string", + "value": "NO", + "accepted_values": ["NO", "ALL", "ToStopVEC", "ToStopCYC"] + }, + "controlTestNumOffFunctional": { + "type": "string", + "value": "NO", + "accepted_values": ["NO", "ALL", "ToStopVEC", "ToStopCYC"] + }, + "stopCycVecLow": { + "type": "integer", + "value": 0 + }, + "stopCycVecHigh": { + "type": "integer", + "value": 0 + }, + "measureMode": { + "type": "string", + "aliases": [], + "value": "PPMUpar", + "accepted_values": ["PPMUpar", "PPMUser", "SPMUser"] + }, + "relaySwitchMode": { + "type": "string", + "aliases": [], + "value": "DEFAULT(BBM)", + "accepted_values": ["DEFAULT(BBM)", "BBM", "MBB", "PARALLEL"] + }, + "output": { + "type": "string", + "aliases": [], + "value": "None", + "accepted_values": ["None", "ReportUI", "ShowFailOnly"] + }, + "testName": { + "type": "string", + "aliases": [], + "value": "(passCurrentLow_uA,passCurrentHigh_uA)" + } + } +} \ No newline at end of file diff --git a/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/operating_current.json b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/operating_current.json new file mode 100644 index 00000000..b64dcba9 --- /dev/null +++ b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/operating_current.json @@ -0,0 +1,34 @@ +{ + "class_name": "dc_tml.DcTest.OperatingCurrent", + + "parameters": { + "dpsPins": { + "type": "string", + "value": "@" + }, + "samples": { + "type": "integer", + "value": 4 + }, + "delayTime": { + "type": "time", + "value": 0 + }, + "termination": { + "type": "string", + "value": "OFF", + "accepted_values": ["ON", "OFF"] + }, + "output": { + "type": "string", + "aliases": [], + "value": "None", + "accepted_values": ["None", "ReportUI", "ShowFailOnly"] + }, + "testName": { + "type": "string", + "aliases": [], + "value": "passCurrLimit_uA" + } + } +} \ No newline at end of file diff --git a/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/output_dc.json b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/output_dc.json new file mode 100644 index 00000000..a6fae219 --- /dev/null +++ b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/output_dc.json @@ -0,0 +1,73 @@ +{ + "class_name": "dc_tml.DcTest.OutputDC", + + "parameters": { + "pinlist": { + "type": "string" + }, + "mode": { + "type": "string", + "value": "PROGRAMLOAD", + "accepted_values": ["PROGRAMLOAD", "PPMU", "SPMU", "PPMUTERM", "SPMUTERM"] + }, + "measureLevel": { + "type": "string", + "value": "BOTH", + "accepted_values": ["BOTH", "LOW", "HIGH"] + }, + "forceCurrentLow": { + "type": "current", + "value": 0 + }, + "forceCurrentHigh": { + "type": "current", + "value": 0 + }, + "maxPassLow": { + "type": "voltage", + "value": 0 + }, + "minPassLow": { + "type": "voltage", + "value": 0 + }, + "maxPassHigh": { + "type": "voltage", + "value": 0 + }, + "minPassHigh": { + "type": "voltage", + "value": 0 + }, + "settlingTimeLow": { + "type": "time", + "value": 0 + }, + "settlingTimeHigh": { + "type": "time", + "value": 0 + }, + "spmuClampVoltageLow": { + "type": "voltage", + "value": 0 + }, + "spmuClampVoltageHigh": { + "type": "voltage", + "value": 0 + }, + "vectorRange": { + "type": "string" + }, + "output": { + "type": "string", + "aliases": [], + "value": "None", + "accepted_values": ["None", "ReportUI", "ShowFailOnly"] + }, + "testName": { + "type": "string", + "aliases": [], + "value": "(OutputDC_LowLevel[V],OutputDC_HighLevel[V])" + } + } +} \ No newline at end of file diff --git a/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/production_iddq.json b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/production_iddq.json new file mode 100644 index 00000000..2f3fb301 --- /dev/null +++ b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/production_iddq.json @@ -0,0 +1,55 @@ +{ + "class_name": "dc_tml.DcTest.ProductionIddq", + + "parameters": { + "dpsPins": { + "type": "string", + "value": "Vee" + }, + "disconnectPins": { + "type": "string" + }, + "settlingTime": { + "type": "time", + "value": 0 + }, + "stopMode": { + "type": "string", + "value": "ToStopVEC", + "accepted_values": ["ToStopVEC", "ToStopCYC"] + }, + "strStopVecCycNum": { + "type": "string" + }, + "samples": { + "type": "integer", + "value": 16 + }, + "checkFunctional": { + "type": "string", + "value": "ON", + "accepted_values": ["ON", "OFF"] + }, + "checkTestNumOfFunctional": { + "type": "string", + "value": "OFF", + "accepted_values": ["ON", "OFF"] + }, + "gangedMode": { + "type": "string", + "value": "OFF", + "accepted_values": ["ON", "OFF"] + }, + "output": { + "type": "string", + "aliases": [], + "value": "None", + "accepted_values": ["None", "ReportUI", "ShowFailOnly"] + }, + "testName": { + "type": "string", + "aliases": [], + "value": "passCurrLimit_uA" + } + } +} \ No newline at end of file diff --git a/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/standby_current.json b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/standby_current.json new file mode 100644 index 00000000..7f162e88 --- /dev/null +++ b/test_apps/python_app/example/interface/test_templates/v93ksmt8/dc_tml/standby_current.json @@ -0,0 +1,34 @@ +{ + "class_name": "dc_tml.DcTest.StandbyCurrent", + + "parameters": { + "dpsPins": { + "type": "string", + "value": "@" + }, + "samples": { + "type": "integer", + "value": 16 + }, + "termination": { + "type": "string", + "value": "OFF", + "accepted_values": ["ON", "OFF"] + }, + "settlingTime": { + "type": "time", + "value": 0 + }, + "output": { + "type": "string", + "aliases": [], + "value": "None", + "accepted_values": ["None", "ReportUI", "ShowFailOnly"] + }, + "testName": { + "type": "string", + "aliases": [], + "value": "passCurrLimit_uA" + } + } +} \ No newline at end of file