+
+* SPICE and GDS2 Interfaces
+ * Custom cells (read GDS and SPICE)
+ * Generated cells (creates GDS and SPICE "on the fly")
+* Netlist functions
+ * Add (directional) pins
+ * Add and connect instances
+
+* Layout functions
+ * Place instances
+ * Add wires, routes, vias
+ * Channel and Power router
+* Verification functions (wrap around DRC and LVS tools)
+
+
+
+## Base Class Inheritance
+```mermaid
+flowchart TD
+ A[design.py \n\n General design and helper DRC constants] --> B[hierarchy_design.py \n\n DRC/LVS functions]
+ B --> C["hierarchy_spice.py \n\n Netlist related functionality"]
+ B --> D["hierarchy_layout.py \n\n Layout related functionality"]
+ C --> E["Functions: \n add_pins \n add_inst"]
+ C --> F["sp_read \n sp_write \n Power data \n Delay data"]
+ D --> G["Functions: \n add_{layout_pin,rect,...} \n place_inst \n create_channel_route \n etc."]
+ D --> H["gds_read \n gds_write \n get_blockages \n etc."]
+```
+
+
+
+## Parameterized Transistor (ptx or pfinfet)
+
+
+* Creates variable size/finger nmos or pmos transistor
+ * Optional gate and source/drain contacts in naive way
+ * Not optimal layout, but "good enough"
+ * Offset (0,0) is lower-left corner of active area
+* Size/fingers effect on size must be estimated elsewhere perhaps by trying configurations
+
+
+
+## Parameterized Cells
+
+
+Dynamically generated cells (in `$OPENRAM_HOME/pgates`)
+* Not the most efficient layouts but "ok"
+* Try to use restrictive design rules to keep them portable
+* Transistors
+ * `ptx`, `pfinfet`
+* Logic gates
+ * `pinv`, `pnand2`, `pnand3`, `pnor2`
+* Buffer/drivers
+ * `pbuf`, `pinvbuf`, `pdriver`
+* SRAM Logic
+ * `precharge`, `single_level_column_mux`
\ No newline at end of file
diff --git a/docs/source/basic_usage.md b/docs/source/basic_usage.md
new file mode 100644
index 00000000..4336a327
--- /dev/null
+++ b/docs/source/basic_usage.md
@@ -0,0 +1,131 @@
+### [Go Back](./index.md)
+
+# Basic Usage
+This page of the documentation explains the basic usage of OpenRAM.
+
+
+
+## Table of Contents
+1. [Environment Variable Setup](#environment-variable-setup-assuming-bash)
+2. [Command Line Usage](#command-line-usage)
+3. [Configuration Files](#configuration-files)
+4. [Common Configuration File Options](#common-configuration-file-options)
+5. [Output Files](#output-files)
+6. [Data Sheets](#data-sheets)
+
+
+
+## Environment Variable Setup (assuming bash)
+* OPENRAM_HOME defines where the compiler directory is
+ * ```export OPENRAM_HOME="$HOME/openram/compiler"```
+* OPENRAM_TECH defines list of paths where the technologies exist
+ * `export OPENRAM_TECH="$HOME/openram/technology"`
+ * Colon separated list so you can have private technology directories
+* Must also have any PDK related variables set up
+* Add compiler to `PYTHONPATH`
+ * `export PYTHONPATH="$PYTHONPATH:$OPENRAM_HOME"`
+
+
+
+## Command Line Usage
+* Basic command line (with or without py suffix):
+ * `openram.py config`
+ * `openram.py config.py`
+* Common arguments:
+ * `-t` specify technology (scn4m_subm or scmos or freepdk45)
+ * `-v` increase verbosity of output
+ * `-n` don't run DRC/LVS
+ * `-c` perform simulation-based characterization
+ * `-d` don't purge /tmp directory contents
+
+
+
+## Configuration Files
+* Memories are created using a Python configuration file to replicate results
+ * No YAML, JSON, etc.
+* Complete configuration options are in `$OPENRAM_HOME/options.py`
+* Some options can be specified on the command line as well
+ * Not recommended for replicating results
+* Example configuration file:
+ ```python
+ # Data word size
+ word_size = 2
+ # Number of words in the memory
+ num_words = 16
+
+ # Technology to use in $OPENRAM_TECH
+ tech_name = "scn4m_subm"
+ # Process corners to characterize
+ process_corners = [ "TT" ]
+ # Voltage corners to characterize
+ supply_voltages = [ 3.3 ]
+ # Temperature corners to characterize
+ temperatures = [ 25 ]
+
+ # Output directory for the results
+ output_path = "temp"
+ # Output file base name
+ output_name = "sram_16x2"
+
+ # Disable analytical models for full characterization (WARNING: slow!)
+ # analytical_delay = False
+
+ # To force this to use magic and netgen for DRC/LVS/PEX
+ # Could be calibre for FreePDK45
+ drc_name = "magic"
+ lvs_name = "netgen"
+ pex_name = "magic"
+ ```
+
+
+
+## Common Configuration File Options
+* Characterization corners
+ * `supply_voltages = [1.7, 1.8, 1.9]`
+ * `temperatures = [25, 50, 100]`
+ * `process_corners = ["SS", "TT", "FF"]`
+* Do not generate layout
+ * `netlist_only = True`
+* Multi-port options
+ * `num_rw_ports = 1`
+ * `num_r_ports = 1`
+ * `num_w_ports = 0`
+* Customized module or bit cell
+ * `bitcell = "bitcell_1rw_1r"`
+ * `replica_bitcell = "replica_bitcell_1rw_1r"`
+* Enable simulation characterization
+ > **Warning**: Slow!
+ * `analytical_delay = False`
+* Output name and location
+ * `output_path = "temp"`
+ * `output_name = "sram_32x256"`
+* Force tool selection (should match the PDK!)
+ * `drc_name = "magic"`
+ * `lvs_name = "netgen"`
+ * `pex_name = "magic"`
+* Include shared configuration options using Python imports
+ * `from corners_freepdk45 import *`
+
+
+
+## Output Files
+The output files are placed in the `output_dir` defined in the configuration file.
+
+The base name is specified by `output_name` and suffixes are added.
+
+The final results files are:
+* GDS (.gds)
+* SPICE (.sp)
+* Verilog (.v)
+* P&R Abstract (.lef)
+* Liberty (multiple corners .lib)
+* Datasheet (.html)
+* Log (.log)
+* Configuration (.py) for replication of creation
+
+
+
+## Data Sheets
+
+
+
\ No newline at end of file
diff --git a/docs/source/bitcells.md b/docs/source/bitcells.md
new file mode 100644
index 00000000..1c0875b1
--- /dev/null
+++ b/docs/source/bitcells.md
@@ -0,0 +1,40 @@
+### [Go Back](./index.md)
+
+# Bitcells
+This page of the documentation explains the bitcells supported by OpenRAM.
+
+
+
+## Table of Contents
+1. [Multiport Bitcells](#multiport-bitcells)
+2. [Relative Bitcell Sizes](#relative-bitcell-sizes-035um-scmos)
+3. [Thin SRAM Bitcells](#thin-sram-bitcells-130nm)
+
+
+
+## Multiport Bitcells
+* Based on 6T SRAM cell
+ * Standard read-write
+ * Isolated read-only ports
+ * Write-only port (not sized for reads)
+* Can accommodate foundry bitcells
+
+
+
+
+
+## Relative Bitcell Sizes (0.35um SCMOS)
+|
|
|
|
+| :-----------------------------------------------: | :------------------------------------------------: | :--------------------------------------------------: |
+| Standard 6T (1rw) 6.8um x 9.2um | Isolated Read 10T (1rw, 1r) 10.9um x 13.9um | DFF 21.9um x 21.2um (from OSU standard cell library) |
+
+
+
+## Thin SRAM Bitcells (130nm)
+|
|
|
|
|
+| :--------------------------------------------------------: | :------------------------------------------------------: | :-----------------------------------------------------------------: | :-------------------------------------------------------------: |
+| Single Port 1.2um x 1.58um | Dual Port 2.40um x 1.58um | Single Port (w/ straps & taps) 2.49um x 1.58um | Dual Port (w/ straps & taps) 3.12um x 1.97um |
+
+|
|
+| :----------------------------------------------------------: |
+| DFF (for reference) 5.83um x 7.07 um |
\ No newline at end of file
diff --git a/docs/source/characterization.md b/docs/source/characterization.md
new file mode 100644
index 00000000..c0c309aa
--- /dev/null
+++ b/docs/source/characterization.md
@@ -0,0 +1,178 @@
+### [Go Back](./index.md)
+
+# Characterization
+This page of the documentation explains the characterization of OpenRAM.
+
+
+
+## Table of Contents
+1. [Characterization Overview](#characterization-overview)
+2. [Characterizer Organization](#characterizer-organization)
+3. [Characterization Options](#characterization-options)
+4. [Characterization Measurements](#characterization-measurements)
+5. [Analytical Characterization](#analytical-characterization)
+6. [Multiport Characterization](#multiport-characterization)
+7. [Characterizer Unit Test Use](#characterizer-unit-test-use)
+8. [Functional Simulation](#functional-simulation)
+9. [Power/Delay Characterization](#powerdelay-characterization)
+10. [Timing Graph](#timing-graph)
+11. [Graph Creation Example: Buffer](#graph-creation-example-buffer)
+12. [Graph Module Exclusion](#graph-module-exclusion)
+13. [Timing Measurement Checks](#timing-measurement-checks)
+
+
+
+## Characterization Overview
+Measures the timing/power through SPICE simulation:
+* Generates the SPICE stimulus: The stimulus is written in standard SPICE format and can be used with any simulator that supports this.
+* Runs the circuit simulations: To produce the average power, setup/hold times, and timing delay of the memory design.
+* Parses the simulator's output: The setup time, hold time, and delay are found using a bidirectional search technique.
+* Produces the output in a Liberty (.lib) file.
+
+
+
+## Characterizer Organization
+* Core Modules
+ * `delay.py` - Generates the delays and power of input SRAM and corner
+ * `setup_hold.py` - Generates setup and hold timing of DFFs by corner
+ * `lib.py` - Characterizes SRAM and builds Liberty file
+ * `stimuli.py` - Generates SPICE stimulus file for characterization
+* Auxiliary Modules
+ * `simulation.py` - Base class for SRAM characterization modules
+ * `trim_spice.py` - Removes portions of SRAM SPICE to speedup simulation
+ * `measurements.py` - Contains classes to aid SPICE measurements
+ * `char_utils.py` - Contains common functions used during characterization
+ * `logical_effort.py` - Helper class for analytical delay model
+* Testing Support Modules
+ * Other modules are derivatives of the simulation module used in the unit tests
+
+
+
+## Characterization Options
+* Characterization by Configuration File
+ * The process, voltage, and temperature (PVT) for characterization are defined in the config file.
+ * Running OpenRAM generates a Liberty (.lib) file for every corner characterized.
+ * Delays, slews, power determined for each input slew and outputs load combination in config file.
+* OpenRAM Characterization Mode
+ * Supports analytical and SPICE based characterization
+ * Analytical characterization is default
+ * SPICE characterization enabled with -c flag (requires SPICE simulator)
+
+
+
+## Characterization Measurements
+* Characterization is performed primarily to generate tables in .lib file
+ * cell_rise/cell_fall - Delay of from negative clock edge to DOUT when reading a 1 or 0 respectively
+ * rise_transition/fall_transition - Slew of DOUT when read 1 or 0 respectively
+ * Setup and hold time for inputs (setup_rising, hold_rising)
+ * Total power and leakage power
+ * Delays and slews and intended to be independent of clock period.
+ * Fall delays are copied to rise delays after characterization*
+* Characterizer can help with debugging or optimization
+ * Delay characterizer also produces Sense Amp Enable Timing to help debug read failures.
+ * Delay class can edited or can be base class if other measurements are wanted.
+> **Note**: Rise delays are dependent on the clock period if measured from negative clock edge due to precharge.
+
+
+
+## Analytical Characterization
+* Delay
+ * Assumes a worst case delay through decoder, word line, and bit lines
+ * Calculates RC delay at each stage using parameters for handmade cells, unit capacitances, and unit resistances which are defined in the technology setup
+ * Output slews are estimated based on delays
+ * Wire delays only estimated for bitline delay
+* Power
+ * Dynamic power at each stage calculated using $C * V^2 * frequency$
+ * Leakage power estimated with parameters in technology setup
+* Corners add linear variations in delay and power
+
+
+
+## Multiport Characterization
+* Supports any port configuration specified by the configuration file
+ * Any number of Read, Write, and Read/Write ports
+ * Any custom bitcells may require modifications for characterization
+* Characterization Algorithm
+ * Feasible period found for each port
+ * Common minimum period is found for all ports
+ * Power and delay is characterized on each port
+* Characterization Runtime
+ * Ports are characterized separately for accuracy
+ * Runtime increases linearly with ports and can be slow.
+
+
+
+## Characterizer Unit Test Use
+* OpenRAM will use the characterizer to generate data for .lib by default
+* Characterizer modules can be instantiated separately from lib.py to generate and test data
+ * Example: `21_ngspice_delay_test.py`
+ * Delay module generates data to compare against previously generated data to error check any recent OpenRAM changes having a large effect on the delay
+* Delay/Simulation module can be used as base class and altered to include custom measurements
+
+
+
+## Functional Simulation
+* Assumes uninitialized memory
+* Random operations
+ * Uses multiple ports when available
+ * Read, write, or noop
+ * Random address
+ * Random data
+* Memory checks
+ * Uses standard CMOS noise margins
+ * Compares read with last write (or feed-through value if being written)
+
+
+
+## Power/Delay Characterization
+* Prunes unused portions of circuit for run-time
+* Setup time, hold time, and delay are found using a bidirectional search.
+ * Finds a feasible period
+ * Iterates until convergence
+* Dynamic and leakage measured
+* Output saved in Liberty (.lib) file.
+ * Uses NLDM
+ * Wish list: CCS
+
+
+
+## Timing Graph
+* OpenRAM has SPICE like modules and instances
+* A timing graph is created using the SPICE netlist, names and paths through lower level modules.
+* Graph used in characterizer for debugging timing issues associated with the Sense Amp Enable
+
+
+
+## Graph Creation Example: Buffer
+
+* SPICE instantiated module (vdd, gnd excluded from graph)
+* Xbuf1 A Z vdd gnd Buffer
+* Base module has its own naming for ports and internal signals
+
+
+* Node names reduced to top-most SPICE level with internal signals maintained.
+* Internal modules determine edges between nodes
+
+
+* Most lower level modules (gates, PTX, FF, etc) determine edges by connecting every input to every output by default.
+* Custom timing paths can be overridden in any module
+
+
+
+## Graph Module Exclusion
+* Modules can be excluded from the graph before it's built
+* This can help trim timing paths that are known to not affect the overall timing
+
+
+|
|
|
+| :-------------------------------------------------------------------------: | :----------------------------------------------------------------------------: |
+| Graph without exclusion | Graph with exclusion |
+
+
+
+## Timing Measurement Checks
+In addition to measurements done for characterization. Several measurements are done to help debug memory failures.
+* Bitline measurements - Voltage of bitlines measured the checked to have at least a 10% difference
+* Bitcell Measurements - Voltage measured on internal storage of cells and check that they match the operation.
+* Output voltage measurements - Output voltage (`DOUT`) checked at end of cycle so it matches operation.
+* Sense Amp Enable Timing - Delay of `S_EN` should not exceed a half-period
\ No newline at end of file
diff --git a/docs/source/control_logic.md b/docs/source/control_logic.md
new file mode 100644
index 00000000..c51d3842
--- /dev/null
+++ b/docs/source/control_logic.md
@@ -0,0 +1,100 @@
+### [Go Back](./index.md)
+
+# Control Logic and Timing
+This page of the documentation explains the control logic and timing of OpenRAM.
+
+
+
+## Table of Contents
+1. [Read Timing](#read-timing)
+2. [Write Timing](#write-timing)
+3. [External Control Signals](#external-control-signals)
+4. [Internal Control Signals](#internal-control-signals)
+5. [Replica Bitline (RBL)](#replica-bitline-rbl)
+6. [Internal Control Signals Diagram (Read)](#internal-control-signals-diagram-read)
+7. [Internal Control Signals Diagram (Write)](#internal-control-signals-diagram-write)
+8. [Clock Distribution](#clock-distribution)
+
+
+
+## Read Timing
+
+
+
+
+### Read Timing Simulation
+
+
+
+
+## Write Timing
+
+
+
+
+### Write Timing Simulation
+
+
+
+
+## External Control Signals
+* Behaves as a synchronous register interface
+ * Address and data captured on positive edge
+ * Data is available after the negative edge (before next positive edge)
+ * Clock is used for internal control generation
+* Clock cycle
+ * Clock high: capture inputs + precharge + decode
+ * Clock low: read/write
+* Reads and writes on multiple ports to the same address in the same cycle "feed through" but the noise margins of the bitcell must be able to handle this
+
+
+
+## Internal Control Signals
+* Sense Enable (`s_en`) -- Active high sense amp enable from Replica Bit Line (RB)
+ * RBL input: `rbl_wl = gated_clk_bar & we_bar`
+ * Delayed RBL output: `pre_s_en = DELAY(rbl_bl)`
+ * Buffered enable: `s_en = BUF(pre_s_en)`
+* Write Driver Enable (`w_en`) -- Active high write driver enable
+ * `w_en = we`
+ * `we` is directly from control flops
+* Precharge Enable Bar (`p_en_bar`) -- Active low enable of precharge
+ * `p_en_bar = !(gated_clk_bar)`
+ * Active for writes as well to prevent half select destruction
+* Word line enable (`wl_en`) -- Active high word line enable
+ * `wl_en = BUF(gated_clk_bar)`
+
+
+
+## Replica Bitline (RBL)
+
+
+* Determines when to start sensing by replicating a bitcell array column
+* Replica Bitline Column (RBC) matches transition of column
+ * `rbl_bl = RBC(rbl_wl)`
+* Delay Line delays the input signal to match word line driver
+ * `pre_s_en = DELAY(rbl_bl)`
+* Buffer drives `s_en` signal to sense amps
+
+
+
+## Internal Control Signals Diagram (Read)
+
+
+
+
+## Internal Control Signals Diagram (Write)
+
+
+
+
+## Clock Distribution
+* External clock (`clk`)
+* Buffered clock (`clk_buf`) drives all DFFs in the design
+ * `clk_buf = BUF(clk)`
+* Buffered clock bar (`clk_bar`) used in control logic
+ * `clk_bar = INV(clk_buf)`
+* Gated Clocks (`gated_clk` and `gated_clk_bar`) used in control logic
+ * This is LOW when disabled
+ * `gated_clk_bar = cs && clk_bar`
+ * This is LOW when disabled
+ * `gated_clk = cs && clk_buf`
\ No newline at end of file
diff --git a/docs/source/debug.md b/docs/source/debug.md
new file mode 100644
index 00000000..258683b6
--- /dev/null
+++ b/docs/source/debug.md
@@ -0,0 +1,141 @@
+### [Go Back](./index.md)
+
+# Debugging and Unit Testing
+This page of the documentation explains the debugging and unit testing of OpenRAM.
+
+
+
+## Table of Contents
+1. [Unit Tests](#unit-tests)
+2. [Unit Test Organization](#unit-test-organization)
+3. [Running Unit Tests](#running-unit-tests)
+4. [Successful Unit Tests](#successful-unit-tests)
+5. [Debugging Unsuccessful Unit Tests](#debugging-unsuccessful-unit-tests-or-openrampy)
+6. [Temporary Output Files](#temporary-output-files)
+
+
+
+## Unit Tests
+OpenRAM has the set of thorough regression tests implemented with the Python unit test framework:
+* Unit tests allow users to add features without worrying about breaking functionality.
+* Unit tests guide users when porting to new technologies.
+* Every sub-module has its own regression test.
+* There are regression tests for memory functionality, library cell verification, timing verification, and technology verification.
+
+
+
+## Unit Test Organization
+* `00_code_format_test.py` does basic lint checking.
+* `01_library_drc_test.py` checks DRC of all library cells for the technology.
+* `02_library_lvs_test.py` checks LVS of all library cells for the technology.
+* `03_*_test.py` checks DRC and LVS of wires and transistors classes.
+* `04_*_test.py` checks DRC and LVS of parameterized cells.
+* `05-19_*_test.py` checks DRC and LVS of module cells (moving upward in hierarchy with numbers)
+* `20_*_test.py` check DRC and LVS of full SRAM layouts with various configurations.
+* `21_*_test.py` checks timing of full SRAMs and compares (with tolerance) to precomputed result.
+ > **Note**: These tests may fail using different simulators due to the tolerance level.
+* `22_*_test.py` checks functional simulation of full SRAMs with various configurations.
+* `23-25_*_test.py` checks lib, lef, and verilog outputs using diff.
+* `30_openram_test.py` checks command-line interface and whether output files are created.
+
+
+
+## Running Unit Tests
+* Tests can be run in the `$OPENRAM_HOME/tests` directory
+* Command line arguments
+ * `-v` for verbose
+ * `-t` freepdk45 for tech
+ * `-d` to preserve /tmp results (done automatically if test fails)
+* Individual tests
+ * `01_library_drc_test.py`
+* All tests
+ * `regress.py`
+
+
+
+## Successful Unit Tests
+```console
+user@host:/openram/compiler/tests$ ./regress.py
+ ______________________________________________________________________________
+|==============================================================================|
+|========= Running Test for: =========|
+|========= scn4m_subm =========|
+|========= ./regress.py =========|
+|========= /tmp/openram_mrg_13245_temp/ =========|
+|==============================================================================|
+runTest (00_code_format_check_test.code_format_test) ... ok
+runTest (01_library_drc_test.library_drc_test) ... ok
+runTest (02_library_lvs_test.library_lvs_test) ... ok
+runTest (03_contact_test.contact_test) ... ok
+runTest (03_path_test.path_test) ... ok
+.
+.
+.
+```
+```console
+user@host:/openram/compiler/tests$ ./03_ptx_1finger_nmos_test.py
+ ______________________________________________________________________________
+|==============================================================================|
+|========= Running Test for: =========|
+|========= scn4m_subm =========|
+|========= ./03_ptx_1finger_nmos_test.py =========|
+|========= /tmp/openram_mrg_13750_temp/ =========|
+|==============================================================================|
+.
+----------------------------------------------------------------------
+Ran 1 test in 0.596s
+
+OK
+```
+
+
+
+## Debugging Unsuccessful Unit Tests (or openram.py)
+* You will get an ERROR during unit test and see a stack trace
+* Examine the temporary output files in the temp directory (/tmp/mydir)
+```console
+ _____________________________________________________________________________
+|==============================================================================|
+|========= Running Test for: =========|
+|========= scn4m_subm =========|
+|========= ./04_pinv_10x_test.py =========|
+|========= /tmp/mydir =========|
+|==============================================================================|
+ERROR: file magic.py: line 174: DRC Errors pinv_0 2
+F
+======================================================================
+FAIL: runTest (__main__.pinv_test)
+----------------------------------------------------------------------
+Traceback (most recent call last):
+ File "./04_pinv_10x_test.py", line 22, in runTest
+ self.local_check(tx)
+ File "/Users/mrg/openram/compiler/tests/testutils.py", line 45, in local_check
+ self.fail("DRC failed: {}".format(a.name))
+AssertionError: DRC failed: pinv_0
+
+----------------------------------------------------------------------
+Ran 1 test in 0.609s
+
+FAILED (failures=1)
+```
+
+### It didn't finish... where are my files?
+* OpenRAM puts all temporary files in a temporary directory named:
+ * `/tmp/openram_
+
+* Encompasses everything except
+ * Data and Address Flops
+ * Control logic
+ * Multi-bank logic
+* Arranges ports
+ * Port 0 is left/bottom
+ * Port 1 is right/top
+
+
+
+## Port Data
+* Encapsulates all of the datapath logic for a rw, w, or r port
+ * Sense amplifiers (read types)
+ * Write drivers (write types)
+ * Column mux (if any)
+ * Precharge (read or write type) (write to not destroy half selected cells in a row)
+* Also includes a precharge for the replica columns
+
+
+
+## Port Address
+* Encapsulates the row decoder and wordline driver for easier placement next to a bank
+* Each port will have its own port_address module
+
+
+
+## Plain Bitcell Array
+
+
+* 2D Array of bit cells
+ * Each row alternately flips vertically
+* Assume bitcells tile
+ * Boundary is determined by boundary layer in GDS
+ * Word line must abut
+ * Bit lines must abut
+
+
+
+## Variations of Bitcells Needed
+* Normal bitcell for data storage
+* Replica bitcell that is fixed to output a 0 value
+* Dummy bitcell with bitlines disconnected (purely for wordline load and lithography regularity)
+
+
+
+
+
+## Replica Bitcell Array
+* Bitcells: B=regular, D=dummy, R=replica
+* Main bitcell array ( $\color{green}{\textrm{green}}$ )
+* Replica cols for each read port ( $\color{skyblue}{\textrm{blue}}$ ) on left or right (any number)
+* Dummy bitcells on the top, bottom, left, and right for lithography regularity ( $\color{red}{\textrm{red}}$ )
+* Replica columns activate two replica bitcells
+ * $\color{blue}{\textrm{One}}$ driven by replica wordline
+ * $\color{royalblue}{\textrm{Second}}$ driven by one of the normal wordlines (dark blue)
+* Second port word and bit lines not shown
+ * Would be on right and top
+
+
+
+## 1D Arrays
+
+
+* Several modules have 1D arrays:
+ * `sense_amp_array`
+ * `write_driver_array`
+ * `precharge_array`
+ * `single_level_column_mux_array`
+ * `tri_gate_array`
+ * `wordline_driver` (*should change name to _array)
+* `sense_amp_array`, `write_driver_array`, `tri_gate_array` match column mux stride to space out
+* Wish list: Allow wide sense amplifier array to use multiple rows of sense amplifiers.
+
+
+
+
+
+## 2D Arrays
+* Regular DFF arrays (`dff_array.py`)
+* Buffered DFF arrays (`dff_buf_array.py`)
+* Inverted DFF array (`dff_inv_array.py`)
+* Can be $1*N$ or $N*1$ or $M*N$
+ * Wish list: $M*N$ routes pins to edges
+
+
+
+
+
+* Configurable fanout and stages
+ * `[4,4,4]` means 3 FO4 stages
+ * `[1,1,4,4]` means 2 FO1 stages followed by FO4
+
+
+
+## Hierarchical (Address) Decoder
+
+
+* Generic `hierarchical_predecode` class
+ * Places routing rails and decode inverters
+* Derived to implement multiple predecoders
+ * `hierarchical_predecode_2x4`
+ * `hierarchical_predecode_3x8`
+ * `hierarchical_predecode_4x16`
+* Hierarchical decoder uses predecoder + another decode stage
+* Predecoders are also used for the column mux decode and bank select decode
+* Wish list: Handle thin bitcell height
\ No newline at end of file
diff --git a/docs/source/index.md b/docs/source/index.md
new file mode 100644
index 00000000..282e9b0d
--- /dev/null
+++ b/docs/source/index.md
@@ -0,0 +1,104 @@
+# OpenRAM Documentation
+
+
+These pages provide the documentation of OpenRAM. You can use the links below to navigate through the documentation.
+
+
+
+## Directory
+1. [Contributors/Collaborators](#contributorscollaborators)
+2. [OpenRAM Dependencies](#openram-dependencies)
+3. [Supported Technologies](#supported-technologies)
+4. [Bitcells](./bitcells.md)
+5. [Architecture](./architecture.md)
+6. [Implementation](#implementation)
+7. [Technology and Tool Portability](#technology-and-tool-portability)
+8. [Basic Usage](./basic_usage.md)
+9. [Tutorials](./tutorials.md)
+10. [Debugging and Unit Testing](./debug.md)
+11. [Technology Setup](./technology_setup.md)
+12. [Library Cells](./library_cells.md)
+13. [Base Data Structures](./base_data_structures.md)
+14. [Hierarchical Design Modules](./design_modules.md)
+15. [Control Logic and Timing](./control_logic.md)
+16. [Routing](./routing.md)
+17. [Characterization](./characterization.md)
+18. [Results](./results.md)
+
+
+
+## Contributors/Collaborators
+
+
+* Prof. Matthew Guthaus (UCSC)
+* Prof. James Stine & Dr. Samira Ataei (Oklahoma State University)
+* UCSC students:
+ * Bin Wu
+ * Hunter Nichols
+ * Michael Grimes
+ * Jennifer Sowash
+ * Jesse Cirimelli-Low
+
+* Many other past students:
+ * Jeff Butera
+ * Tom Golubev
+ * Marcelo Sero
+ * Seokjoong Kim
+
+
+
+## OpenRAM Dependencies
+* Python 3.6+
+ * NumPy
+* Spice Simulator
+ * Ngspice 26 (or later)
+ * Hspice I-2013.12-1 (or later)
+ * CustomSim 2017 (or later)
+* DRC
+ * Calibre 2017.3_29.23
+ * Magic 8.x (http://opencircuitdesign.com/magic/)
+* LVS
+ * Calibre 2017.3_29.23
+ * Netgen 1.5 (http://opencircuitdesign.com/netgen/)
+* Git (any version)
+
+
+
+## Supported Technologies
+* NCSU FreePDK 45nm
+ * Non-fabricable but contains DSM rules
+ * Calibre required for DRC/LVS
+* MOSIS 0.35um (SCN4M_SUBM)
+ * Fabricable technology
+ * Magic/Netgen or Calibre for DRC/LVS
+ * 4 layers metal required for supply routing
+* NCSU FreePDK 15nm & ASAP 7nm
+ * In progress
+
+
+
+## Implementation
+* Front-end mode
+ * Generates SPICE, layout views, timing models
+ * Netlist-only mode can skip the physical design too
+ * Doesn't perform DRC/LVS
+ * Estimates power/delay analytically
+* Back-end mode
+ * Generates SPICE, layout views, timing models
+ * Performs DRC/LVS
+ * Can perform at each level of hierarchy or at the end
+ * Simulates power/delay
+ * Can be back-annotated or not
+
+
+
+## Technology and Tool Portability
+* OpenRAM is technology independent by using a technology directory that includes:
+ * Technology's specific information
+ * Technology's rules such as DRC rules and the GDS layer map
+ * Custom designed library cells (6T, sense amp, DFF) to improve the SRAM density.
+* For technologies that have specific design requirements, such as specialized well contacts, the user can include helper functions in the technology directory.
+* Verification wrapper scripts
+ * Uses a wrapper interface with DRC and LVS tools that allow flexibility
+ * DRC and LVS can be performed at all levels of the design hierarchy to enhance bug tracking.
+ * DRC and LVS can be disabled completely for improved run-time or if licenses are not available.
\ No newline at end of file
diff --git a/docs/source/library_cells.md b/docs/source/library_cells.md
new file mode 100644
index 00000000..e89c1c2c
--- /dev/null
+++ b/docs/source/library_cells.md
@@ -0,0 +1,96 @@
+### [Go Back](./index.md)
+
+# Library Cells
+This page of the documentation explains the library cells of OpenRAM.
+
+
+
+## Table of Contents
+1. [Required Hard/Custom Cells](#required-hardcustom-cells)
+2. [Bitcell(s)](#bitcells)
+3. [Multiport Bitcells](#multiport-bitcells)
+4. [Parameterized Bitcell](#parameterized-bitcell)
+5. [Sense Amplifier](#sense-amplifier)
+6. [DFF](#dff)
+7. [Tristate/Write Driver](#tristatewrite-driver)
+
+
+
+## Required Hard/Custom Cells
+* Located in
+ * `$OPENRAM_TECH/
+
+
+
+
+## Sense Amplifier
+* Needs a sense amplifier that is pitch matched to the bitcell.
+ * `$OPENRAM_TECH/gds_lib/sense_amp.gds`
+ * `$OPENRAM_TECH/sp_lib/sense_amp.sp`
+ * `$OPENRAM_HOME/modules/sense_amp.py`
+* Wish list: pin names are fixed right now as `bl`, `br`, `dout`, `en`, `vdd`, `gnd`
+
+
+
+## DFF
+* Needs a standard cell DFF for the address and data registers.
+ * `$OPENRAM_TECH/gds_lib/dff.gds `
+ * `$OPENRAM_TECH/sp_lib/dff.sp`
+ * `$OPENRAM_HOME/modules/dff.py`
+* Have auxiliary code to create:
+ * Buffered DFFs (`dff_buf.py`) using dynamically generated inverters (pinv)
+ * Inverted output DFFs (`dff_inv.py`) using a dynamically generated inverters (pinv)
+ * 2-D DFF arrays
+ * Regular DFF arrays (`dff_array.py`)
+ * Buffered DFF arrays (`dff_buf_array.py`)
+ * Inverted DFF array (`dff_inv_array.py`)
+* Wish list: pin names are fixed right now as `D`, `Q`, `Qb`, `clk`, `vdd`, `gnd`
+
+
+
+## Tristate/Write Driver
+* Tristate is used for multi-bank implementations
+* Write driver drives the data onto the bitlines
+* Both of these are currently library cells, but plans are to make them dynamically generated (`ptristate.py` and `pwrite_driver.py`)
\ No newline at end of file
diff --git a/docs/source/results.md b/docs/source/results.md
new file mode 100644
index 00000000..dd2c0ba3
--- /dev/null
+++ b/docs/source/results.md
@@ -0,0 +1,67 @@
+### [Go Back](./index.md)
+
+# Results
+This page of the documentation explains the results of OpenRAM.
+
+
+
+## Table of Contents
+1. [Small Layouts](#small-layouts)
+2. [Relative Planar Bitcells](#relative-planar-bitcells-035um-scmos)
+3. [SRAM Area](#sram-area)
+4. [Generated Layout by OpenRAM](#generated-layout-by-openram-for-a-multiport-6r2w-sram-in-32-nm-soi-cmos-technology)
+5. [Timing and Density Results for Generated SRAMs](#timing-and-density-results-for-generated-srams)
+6. [Comparison with Fabricated SRAMs](#comparison-with-fabricated-srams)
+7. [Conclusions](#conclusions)
+
+
+
+## Small Layouts
+|
|
|
+| :----------------------------------------------------------: | :----------------------------------------------------------: |
+| 512 x 16b x 1rw FreePDK45 | 2048 x 32b x 1rw FreePDK45 |
+
+
+
+## Relative Planar Bitcells (0.35um SCMOS)
+|
|
|
|
+| :-----------------------------------------------: | :------------------------------------------------: | :--------------------------------------------------: |
+| Standard 6T (1rw) 6.8um x 9.2um | Isolated Read 10T (1rw, 1r) 10.9um x 13.9um | DFF 21.9um x 21.2um (from OSU standard cell library) |
+
+
+
+## SRAM Area
+
+
+
+
+## Generated Layout by OpenRAM for a multiport (6R/2W) SRAM in 32 nm SOI CMOS Technology
+
+
+
+
+## Timing and Density Results for Generated SRAMs
+
+
+
+
+## Comparison with Fabricated SRAMs
+| $\textrm{Reference}$ | $\textrm{Feature Size}$ | $\textrm{Technology}$ | $\textrm{Density } (Mb/mm^2)$ |
+| :---------------------- | :---------------------: | :-------------------: | :---------------------------: |
+| $\textrm{IEEE-VLSI'08}$ | $65 nm$ | $\textrm{CMOS}$ | $0.7700$ |
+| $\textrm{JSSC'11}$ | $45 nm$ | $\textrm{CMOS}$ | $0.3300$ |
+| $\textrm{JSSC'13}$ | $40 nm$ | $\textrm{CMOS}$ | $0.9400$ |
+| $\textrm{OpenRAM}$ | $45 nm$ | $\textrm{FreePDK45}$ | $0.8260$ |
+| $\textrm{JSSC'92}$ | $0.5 \mu m$ | $\textrm{CMOS}$ | $0.0036$ |
+| $\textrm{JSSC'94}$ | $0.5 \mu m$ | $\textrm{BICMOS}$ | $0.0020$ |
+| $\textrm{JSSC'99}$ | $0.5 \mu m$ | $\textrm{CMOS}$ | $0.0050$ |
+| $\textrm{OpenRAM}$ | $0.5 \mu m$ | $\textrm{SCMOS}$ | $0.0050$ |
+
+
+
+## Conclusions
+* The main motivation behind OpenRAM is to promote and simplify memory-related research in academia and provides a platform to implement and test new memory designs.
+* OpenRAM is open-sourced, flexible, and portable and can be adapted to various technologies.
+* OpenRAM generates the circuit, functional model, and layout of variable-sized SRAMs.
+* OpenRAM provides a memory characterizer for synthesis timing/power models.
+* We are also actively introducing new features, such as non-6T memories, variability characterization, word-line segmenting, characterization speed-up, etc.
\ No newline at end of file
diff --git a/docs/source/routing.md b/docs/source/routing.md
new file mode 100644
index 00000000..e76a29c8
--- /dev/null
+++ b/docs/source/routing.md
@@ -0,0 +1,56 @@
+### [Go Back](./index.md)
+
+# Routing
+This page of the documentation explains the routing of OpenRAM.
+
+
+
+## Table of Contents
+1. [Power Supply Options](#power-supply-options)
+2. [Power Routing](#power-routing)
+3. [Power Supply Algorithm](#power-supply-algorithm)
+4. [Channel Router](#channel-router)
+
+
+
+## Power Supply Options
+* Unrouted
+ * Leave must-connect metal 3 pins for vdd and gnd within the array
+* Grid
+ * Connect in a metal 3 and 4 grid
+ * Blockage aware
+ * Can encounter DRC errors with off-grid pins
+ * Works with commercial tools but not so well with OpenRoad
+* Work in Progress: Hanan Grid / Steiner Tree:
+ * Route tree on Hanan metal 3 and 4 grid instead of full grid
+ * Blockage aware
+
+
+
+## Power Routing
+
+
+* All power pins are brought to M3 and routed as a grid on M3/M4
+* Considers blockages of M3/M4 by control and data signals
+* Considers wide/long metal spacing rules
+
+
+
+## Power Supply Algorithm
+* 1st: Route vertical and horizontal grids (blockage aware, allow connection to correct supply)
+* 2nd: Check direct overlaps of power pins
+* 3rd: Single direction probes to connect
+* 4th: A* maze router
+
+
+
+## Channel Router
+* SRAMs typically try to use minimal layers of metal
+ * Primarily used to connect decoders, input/output circuitry, or control logic
+* Wish list
+ * Minimize number of tracks
+ * Must consider impact on floorplan
+
+|
|
|
+| :-------------------------------------------------------------------------: | :---------------------------------------------------------------------: |
+| Credit: Chen & Chang, EDA Handbook, Chapter 12, Global and detailed routing | Sense amp to data flop connection |
\ No newline at end of file
diff --git a/docs/source/technology_setup.md b/docs/source/technology_setup.md
new file mode 100644
index 00000000..8375c40e
--- /dev/null
+++ b/docs/source/technology_setup.md
@@ -0,0 +1,125 @@
+### [Go Back](./index.md)
+
+# Technology Setup
+This page of the documentation explains the technology setup of OpenRAM.
+
+
+
+## Table of Contents
+1. [Technology Directories](#technology-directories)
+2. Technology Configuration:
+ 1. [Layer Map](#technology-configuration-layer-map)
+ 2. [GDS](#technology-configuration-gds)
+ 3. [DRC](#technology-configuration-drc)
+ 4. [SPICE](#technology-configuration-spice)
+ 5. [Parameters](#technology-configuration-parameters)
+
+
+
+## Technology Directories
+* Environment variable OPENRAM_TECH specifies list of technology directories
+ * Similar to `*nix $PATH`
+* Directory structure:
+ ```
+ techname/
+ __init__.py -- Sets up PDK environment
+ tech/ -- Contains technology configuration
+ __init__.py -- Loads all modules
+ tech.py -- SPICE, DRC, GDS, and layer config
+ gds_lib/ -- Contains .gds files for each lib cell
+ sp_lib/ -- Contains .sp file for each lib cell
+ models/ -- Contains SPICE device corner models
+ (tf/) -- May contain some PDK material
+ (mag_lib/) -- May contain other layout formats
+ ```
+
+
+
+## Technology Configuration: Layer Map
+* Layer map contains mapping of layer names to GDS layers
+* Layer names are used in OpenRAM code directly
+ ```python
+ layer={}
+ layer["vtg"] = -1
+ layer["vth"] = -1
+ layer["contact"] = 47
+ layer["pwell"] = 41
+ ...
+ layer["metal4"] = 31
+ layer["text"] = 63
+ layer["boundary"] = 63
+ layer["blockage"] = 83
+ ```
+
+
+
+## Technology Configuration: GDS
+* OpenRAM uses the gdsMill library (included and heavily modified)
+* Units defined for GDS format
+ * First number is DB units per user units
+ * Second number is DB unit in meters
+ ```python
+ # GDS file info
+ GDS={}
+ # gds units
+ GDS["unit"]=(0.001,1e-6)
+ # default label zoom
+ GDS["zoom"] = 0.5
+ ```
+* Zoom defines default zoom for labels
+* More info on the GDS format at:
+ * http://boolean.klaasholwerda.nl/interface/bnf/gdsformat.html
+
+
+
+## Technology Configuration: DRC
+* Creates the design_rule class with several parts:
+ * Grid size
+ * Location of DRC, LVS, PEX rules and layer map
+ * Subset of design rules for FEOL and BEOL
+* Design rules have common naming scheme (names used in OpenRAM)
+ * `minwidth_