WIP: Clarify some examples and add additional comments
diff --git a/vpr/src/base/pass.h b/vpr/src/base/pass.h
index 79fcd76..9ace81a 100644
--- a/vpr/src/base/pass.h
+++ b/vpr/src/base/pass.h
@@ -3,6 +3,33 @@
 
 #include "vpr_context_fwd.h"
 
+/*
+ * Somewhere the host application will setup a VPR state context and create
+ * passes to be run on the state context.
+ *
+ * For example:
+ *      
+ *      int main() {
+ *          
+ *          VprContext vpr_ctx;
+ *
+ *          std::vector<std::unique_ptr<Pass>> passes;
+ *
+ *          //Add various passes
+ *          passes.emplace_back(std::make_unique<MyPass>(vpr_ctx);
+ *          passes.emplace_back(std::make_unique<OtherPass>(vpr_ctx);
+ *          ...
+ *             
+ *          //Run all passes
+ *          for (auto& pass : passes) {
+ *              pass->run_pass();
+ *          }
+ *      }
+ */
+
+/*
+ * Abstract interface for a pass
+ */
 class Pass {
     public:
         virtual bool run_pass() = 0;
@@ -10,15 +37,20 @@
 
 /*
  * Mutable (read/wrtie) pass
+ *
+ * Mutable passes can modify their context
  */
 class MutablePass : public Pass {
     public:
         MutablePass(VprContext& vpr_ctx);
 
+        //All passes can access the full context immutably (read-only)
         const VprContext& ctx() const { return vpr_ctx_; }
 
-        virtual bool run_pass() final { return run_on_mutable(vpr_ctx_); }
+        //Deligate to run_on_mutable()
+        virtual bool run_pass() final { return run_on_mutable(vpr_ctx_); } //Note final prevents sub-classes from re-defining
 
+        //All MutablePasses get access to the full context mutably (read/write)
         virtual bool run_on_mutable(VprContext& mutable_ctx) = 0;
 
     private:
@@ -27,15 +59,21 @@
 
 /*
  * Immutable (read-only) pass
+ *
+ * Immutable passes can not modify their input context
  */
 class ImmutablePass : public Pass {
     public:
         ImmutablePass(const VprContext& vpr_ctx);
 
+        //All passes can access the full context immutably (read-only)
         const VprContext& ctx() const { return vpr_ctx_; }
 
-        virtual bool run_pass() final { return run_on_immutable(vpr_ctx_); }
+        //Deligate to run_on_immutable()
+        virtual bool run_pass() final { return run_on_immutable(vpr_ctx_); } //Note final prevents sub-classes from re-defining
 
+        //All ImmutablePasses implement run_on_immutable() which provides immutable (read-only)
+        //acess to the entire VPR context
         virtual bool run_on_immutable(const VprContext& immutable_ctx) = 0;
 
     private:
@@ -47,8 +85,11 @@
  */
 class AtomPass : public MutablePass {
     public:
-        virtual bool run_on_mutable(VprContext& ctx) final { return run_on_atom(ctx.mutable_atom()); }
+        //Deligate to run_on_atom()
+        virtual bool run_on_mutable(VprContext& ctx) final { return run_on_atom(ctx.mutable_atom()); } //Note final prevents sub-classes from re-defining
 
+        //All AtomPass derived passes only get mutable access to the AtomContext.
+        //Note that they can still get immutable access to the full context via ctx().
         virtual bool run_on_atom(AtomContext& atom_ctx) = 0;
 };
 
diff --git a/vpr/src/passes/clean_atom_netlist_pass.h b/vpr/src/passes/clean_atom_netlist_pass.h
index 2bee3fd..af1b82c 100644
--- a/vpr/src/passes/clean_atom_netlist_pass.h
+++ b/vpr/src/passes/clean_atom_netlist_pass.h
@@ -4,7 +4,7 @@
 #include "pass.h"
 
 
-class CleanAtomNetlistPass {
+class CleanAtomNetlistPass : public AtomPass {
     
     bool run_on_atom(AtomContext& atom_ctx) override {
         auto& arch = ctx().device().arch;
diff --git a/vpr/src/passes/pack_pass.h b/vpr/src/passes/pack_pass.h
new file mode 100644
index 0000000..1b3cbcf
--- /dev/null
+++ b/vpr/src/passes/pack_pass.h
@@ -0,0 +1,29 @@
+#ifndef PACK_PASS_H
+#define PACK_PASS_H
+#include "pass.h"
+#include "pack.h"
+
+class PackNetlistPass : public ClusterPass {
+    PackPass(const t_packer_opts& packer_opts,
+             std::vector<t_lb_type_rr_graph> lb_type_rr_graphs)
+        : packer_opts_(packer_opts)
+        , lb_type_rr_graphs_(lb_type_rr_graphs) {}
+    
+    bool run_on_clustering(ClusteringContext& cluster_ctx) override {
+        const auto& arch = ctx().device().arch;
+
+        try_pack(&packer_opts_,
+                 &arch,
+                 arch.models,
+                 arch.models_library,
+                 lb_type_rr_graphs_,
+                 cluster_ctx);
+
+        return true;
+    }
+
+    t_packer_opts packer_opts_;
+    std::vector<t_lb_type_rr_graph> lb_type_rr_graphs_;
+};
+
+#endif
diff --git a/vpr/src/passes/read_blif_pass.h b/vpr/src/passes/read_blif_pass.h
index 7edacdf..190ef6a 100644
--- a/vpr/src/passes/read_blif_pass.h
+++ b/vpr/src/passes/read_blif_pass.h
@@ -3,7 +3,7 @@
 #include "pass.h"
 #include "read_blif.h"
 
-class ReadBlifPass : public DevicePass {
+class ReadBlifPass : public AtomPass {
     ReadBlifPass(const e_circuit_format& cct_fmt,
                  const std::string& blif_file_path)
         : cct_fmt_(cct_fmt)