Skip to content

Patgen Dev Notes

Stephen McGinty edited this page Feb 28, 2020 · 5 revisions

These are planning notes on how the patgen internals should be constructed, there is a ticket for discussing it here: https://github.com/Origen-SDK/o2/issues/90

General Comments Re. the Pattern AST

  • In Rust, AST nodes should always be added via constructors, not direct struct literal creation
    • Good app note here on how to enforce that: https://words.steveklabnik.com/structure-literals-vs-constructors-in-rust
    • The constructor should append the new node to the AST immediately upon creation – code triggering a cycle must not have to think about whether it should be appended to a currently open reg transaction vs. the top-level, the node constructors will deal with that.
    • This will avoid multiple change points if a node struct field is added
  • However, most AST node creation should be done by API methods, e.g. my_pin.drive(), vs. creating a Pin action node directly, though the latter will always be available throughout the Rust domain.
  • AST nodes are immutable upon construction
  • The AST itself should be thought of as immutable except for the following permitted mutations:
    • New nodes can (of course) be appended
    • New nodes can be inserted, e.g. before_last_cycle
    • Nodes can be deleted
  • The above exceptions are removed and the AST is fully immutable once the frontend pattern definition stage is complete and backend generation (rendering) begins
  • All mutations (e.g. clean up, optimizations, compressions) are then done by processing (walking) the AST and outputting a new one, these are called stages for the rest of this document.
  • Only the master AST needs to be kept in static memory, derivatives could be ephemeral and can generally be discarded as processing moves onto the next stage.

AST Storage

  • A new mutable static should be added here similar to DUT, propose it is called TESTS - https://github.com/Origen-SDK/o2/blob/master/rust/origen/src/lib.rs#L36
    • Name chosen instead of ‘PATTERNS’ since this could/should grow to include things that are not strictly in the pattern domain and it is more like a representation of the current test – e.g. could include pin force/measure nodes, etc.
    • Propose to have a separate one for test programs in future, e.g. FLOWS to avoid borrow issues
  • A key concern here will be memory usage, the master AST should be permanently stored until generation is completed, but there needs to the concept of scratch/temporary storage that can be reclaimed as these structures could be big and have a lot of duplication as generation moves through stages.
  • src/core/tests.rs should define this singleton and it should have the following properties:
    • master_nodes: Vec<AstNode> - All master nodes (those created during frontend generation) created should be stored in here.
      • The node's index in this vector is its ID
      • master_nodes[0] is the top-level of the current AST
      • A method should be available to clear this at the start of the next test generation, similar to the target change method in Dut
      • Individual nodes are never deleted from here, deleting a node from the AST will mean removing its ID from its parent node's children vector.
    • stage_nodes: Vec<Vec<AstNode>> - Nodes created by processing the master AST to the next stage and from processing one stage to the next. Note that it is a vector of vectors.
      • A method should be available to request storage for a new stage. That should create a new Vec<AstNode> if none is available and return its index to the caller. The caller would be responsible for storing the ID of their allocated stage bank.
      • A method should be available to declare that a stage bank can be discarded.
      • Within each bank it will operate the same as master_nodes with stage_nodes[n][0] being the top-level node of the given stage.
    • active_temp_nodes: Vec<usize> - For keeping track of which stage node banks are still reserved. If an existing bank is not listed in here then it can be cleared and re-used for another stage.

Node Definitions and APIs

  • All node struct definitions should be in module src/ast (could also be src/core/ast, but thinking this deserves its own top-level entity since it will be referred to a lot I think).
  • Probably a lot of sub-modules below this, e.g.
    • src/ast/reg.rs
    • src/ast/pin.rs
    • src/ast/tester.rs
    • src/ast/tester/v93k.rs
    • src/ast/jtag.rs
  • There should generally be a 1:1 mapping between an API method and an AST node, e.g. tester.cycle() and tester.wait() should map to similarly named nodes in src/ast/tester.rs.
  • ATE-specific APIs should be similarly mapped, an API method like tester.v93k.do_x() should map to a DoX node in the src/ast/v93k.rs module.

Python Domain

  • Generally, APIs should be used to cross the Rust/Python boundary and not direct node creation. That said, if @coreyeng can or already does provides some macro-magic to expose all the AST structs and their constructors then so be it, though the AST node structure should really be Origen-internal private and not part of the public API.