diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 00000000..5a8c6f66
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,14 @@
+[run]
+omit =
+ # omit anything in a .local directory anywhere
+ */.local/*
+ # omit everything in /usr
+ /usr/*
+[paths]
+source =
+ /home/gitlab-runner/builds/2fd64746/0
+ /home/gitlab-runner/builds/2fd64746/1
+ /home/gitlab-runner/builds/2fd64746/2
+ /home/gitlab-runner/builds/2fd64746/3
+ /home/gitlab-runner/builds/2fd64746/4
+ /home/gitlab-runner/builds/2fd64746/5
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 96e30d2d..27c341aa 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,6 +1,39 @@
+before_script:
+ - . /home/gitlab-runner/setup-paths.sh
+ - export OPENRAM_HOME="`pwd`/compiler"
+ - export OPENRAM_TECH="`pwd`/technology"
+
+stages:
+ - test
+ - coverage
+
freepdk45:
- script: "/home/gitlab-runner/regress_freepdk45.sh"
+ stage: test
+ script:
+ - coverage run -p $OPENRAM_HOME/tests/regress.py -t freepdk45
+ artifacts:
+ paths:
+ - .coverage.*
+ expire_in: 1 week
scn4m_subm:
- script: "/home/gitlab-runner/regress_scn4m_subm.sh"
+ stage: test
+ script:
+ - coverage run -p $OPENRAM_HOME/tests/regress.py -t scn4m_subm
+ artifacts:
+ paths:
+ - .coverage.*
+ expire_in: 1 week
+
+coverage:
+ stage: coverage
+ script:
+ - coverage combine
+ - coverage report
+ - coverage html -d coverage_html
+ artifacts:
+ paths:
+ - coverage_html
+ expire_in: 1 week
+ coverage: '/TOTAL.+ ([0-9]{1,3}%)/'
diff --git a/README.md b/README.md
index 91e00bbd..693d32ef 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,18 @@
# OpenRAM
-Master: [](https://github.com/VLSIDA/PrivateRAM/commits/master)
-Dev: [](https://github.com/VLSIDA/PrivateRAM/commits/dev)
-[](https://github.com/VLSIDA/PrivateRAM/archive/master.zip)
+
+[](https://www.python.org/)
[](./LICENSE)
+Master:
+[](https://github.com/VLSIDA/PrivateRAM/commits/master)
+
+[](https://github.com/VLSIDA/PrivateRAM/archive/master.zip)
+
+Dev:
+[](https://github.com/VLSIDA/PrivateRAM/commits/dev)
+
+[](https://github.com/VLSIDA/PrivateRAM/archive/dev.zip)
+
An open-source static random access memory (SRAM) compiler.
# What is OpenRAM?
diff --git a/compiler/pgates/pbuf.py b/compiler/pgates/pbuf.py
new file mode 100644
index 00000000..0d30a89b
--- /dev/null
+++ b/compiler/pgates/pbuf.py
@@ -0,0 +1,123 @@
+import debug
+import design
+from tech import drc
+from math import log
+from vector import vector
+from globals import OPTS
+from pinv import pinv
+
+class pbuf(design.design):
+ """
+ This is a simple buffer used for driving loads.
+ """
+ from importlib import reload
+ c = reload(__import__(OPTS.bitcell))
+ bitcell = getattr(c, OPTS.bitcell)
+
+ unique_id = 1
+
+ def __init__(self, driver_size=4, height=bitcell.height, name=""):
+
+ stage_effort = 4
+ # FIXME: Change the number of stages to support high drives.
+
+ if name=="":
+ name = "pbuf_{0}_{1}".format(driver_size, pbuf.unique_id)
+ pbuf.unique_id += 1
+
+ design.design.__init__(self, name)
+ debug.info(1, "Creating {}".format(self.name))
+
+
+ # Shield the cap, but have at least a stage effort of 4
+ input_size = max(1,int(driver_size/stage_effort))
+ self.inv1 = pinv(size=input_size, height=height) # 1
+ self.add_mod(self.inv1)
+
+ self.inv2 = pinv(size=driver_size, height=height) # 2
+ self.add_mod(self.inv2)
+
+ self.width = self.inv1.width + self.inv2.width
+ self.height = self.inv1.height
+
+ self.create_layout()
+
+ #self.offset_all_coordinates()
+
+ self.DRC_LVS()
+
+ def create_layout(self):
+ self.add_pins()
+ self.add_insts()
+ self.add_wires()
+ self.add_layout_pins()
+
+ def add_pins(self):
+ self.add_pin("A")
+ self.add_pin("Z")
+ self.add_pin("vdd")
+ self.add_pin("gnd")
+
+ def add_insts(self):
+ # Add INV1 to the right
+ self.inv1_inst=self.add_inst(name="buf_inv1",
+ mod=self.inv1,
+ offset=vector(0,0))
+ self.connect_inst(["A", "zb_int", "vdd", "gnd"])
+
+
+ # Add INV2 to the right
+ self.inv2_inst=self.add_inst(name="buf_inv2",
+ mod=self.inv2,
+ offset=vector(self.inv1_inst.rx(),0))
+ self.connect_inst(["zb_int", "Z", "vdd", "gnd"])
+
+
+ def add_wires(self):
+ # inv1 Z to inv2 A
+ z1_pin = self.inv1_inst.get_pin("Z")
+ a2_pin = self.inv2_inst.get_pin("A")
+ mid_point = vector(z1_pin.cx(), a2_pin.cy())
+ self.add_path("metal1", [z1_pin.center(), mid_point, a2_pin.center()])
+
+
+ def add_layout_pins(self):
+ # Continous vdd rail along with label.
+ vdd_pin=self.inv1_inst.get_pin("vdd")
+ self.add_layout_pin(text="vdd",
+ layer="metal1",
+ offset=vdd_pin.ll().scale(0,1),
+ width=self.width,
+ height=vdd_pin.height())
+
+ # Continous gnd rail along with label.
+ gnd_pin=self.inv1_inst.get_pin("gnd")
+ self.add_layout_pin(text="gnd",
+ layer="metal1",
+ offset=gnd_pin.ll().scale(0,1),
+ width=self.width,
+ height=vdd_pin.height())
+
+ z_pin = self.inv2_inst.get_pin("Z")
+ self.add_layout_pin_rect_center(text="Z",
+ layer="metal2",
+ offset=z_pin.center())
+ self.add_via_center(layers=("metal1","via1","metal2"),
+ offset=z_pin.center())
+
+ a_pin = self.inv1_inst.get_pin("A")
+ self.add_layout_pin_rect_center(text="A",
+ layer="metal2",
+ offset=a_pin.center())
+ self.add_via_center(layers=("metal1","via1","metal2"),
+ offset=a_pin.center())
+
+
+
+ def analytical_delay(self, slew, load=0.0):
+ """ Calculate the analytical delay of DFF-> INV -> INV """
+ inv1_delay = self.inv1.analytical_delay(slew=slew, load=self.inv2.input_load())
+ inv2_delay = self.inv2.analytical_delay(slew=inv1_delay.slew, load=load)
+ return inv1_delay + inv2_delay
+
+
diff --git a/compiler/tests/04_pbuf_test.py b/compiler/tests/04_pbuf_test.py
new file mode 100644
index 00000000..f784c671
--- /dev/null
+++ b/compiler/tests/04_pbuf_test.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+"""
+Run a regression test on a 2-row buffer cell
+"""
+
+import unittest
+from testutils import header,openram_test
+import sys,os
+sys.path.append(os.path.join(sys.path[0],".."))
+import globals
+from globals import OPTS
+import debug
+
+class pbuf_test(openram_test):
+
+ def runTest(self):
+ globals.init_openram("config_20_{0}".format(OPTS.tech_name))
+ global verify
+ import verify
+
+ import pbuf
+
+ debug.info(2, "Testing inverter/buffer 4x 8x")
+ a = pbuf.pbuf(8)
+ self.local_check(a)
+
+ globals.end_openram()
+
+# instantiate a copdsay of the class to actually run the test
+if __name__ == "__main__":
+ (OPTS, args) = globals.parse_args()
+ del sys.argv[1:]
+ header(__file__, OPTS.tech_name)
+ unittest.main()
diff --git a/images/Python-3.5-green.svg b/images/Python-3.5-green.svg
new file mode 100644
index 00000000..5856e0ee
--- /dev/null
+++ b/images/Python-3.5-green.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/images/download-stable-blue.svg b/images/download-stable-blue.svg
new file mode 100644
index 00000000..2fbc3649
--- /dev/null
+++ b/images/download-stable-blue.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/images/download-unstable-blue.svg b/images/download-unstable-blue.svg
new file mode 100644
index 00000000..a233df6b
--- /dev/null
+++ b/images/download-unstable-blue.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/images/download.svg b/images/download.svg
deleted file mode 100644
index 95d978ed..00000000
--- a/images/download.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-
-