├── .gitignore ├── ARCHITECTURE.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── cells ├── LC_oscillator │ ├── cdac.lua │ ├── connector.lua │ ├── core.lua │ ├── cross_coupled_pair.lua │ ├── current_mirror.lua │ ├── fill.lua │ ├── fixed_capacitor.lua │ ├── resonator.lua │ ├── toplevel.lua │ ├── varactorbase.lua │ └── varbank.lua ├── RF │ ├── patterned_ground_shield.lua │ └── transmission_line.lua ├── SAR_ADC │ ├── buf_array.lua │ ├── cap_array.lua │ ├── sample_and_hold.lua │ ├── switch_network_down.lua │ └── switch_network_up.lua ├── __test │ ├── align_sub.lua │ ├── align_top.lua │ ├── angled_path.lua │ ├── path.lua │ ├── pathextension.lua │ ├── premapped.lua │ ├── rectangle.lua │ ├── rotation.lua │ ├── sub.lua │ ├── subsub.lua │ ├── top.lua │ ├── translation.lua │ └── via.lua ├── analog │ ├── LC_oscillator.lua │ ├── common_centroid.lua │ ├── cross_coupled_pair.lua │ ├── crystal_IC_oscillator.lua │ ├── current_mirror_multiple.lua │ ├── current_starved_ringoscillator.lua │ ├── currentmirror.lua │ ├── inverter.lua │ ├── inverter_chain.lua │ ├── ringoscillator.lua │ ├── self_biased_inverter.lua │ ├── simple_currentmirror.lua │ ├── stacked_ringoscillator.lua │ ├── strongARM_comparator.lua │ ├── track_hold.lua │ ├── transmission_gate.lua │ └── vertical_inverter.lua ├── auxiliary │ ├── decap.lua │ ├── groundmesh.lua │ ├── guardring.lua │ ├── metalgrid.lua │ ├── pad.lua │ ├── padring.lua │ ├── pads.lua │ ├── powergridadapter.lua │ ├── svg2layout.lua │ ├── text.lua │ └── welltap.lua ├── basic │ ├── cmos.lua │ ├── cmos_bjt.lua │ ├── cmos_connected.lua │ ├── diode.lua │ ├── ldmos.lua │ ├── mosfet.lua │ ├── polyresistor.lua │ └── stacked_mosfet_array.lua ├── logic │ └── counter.lua ├── optical │ └── grated_coupler.lua ├── passive │ ├── capacitor │ │ ├── mom.lua │ │ └── tin.lua │ └── inductor │ │ ├── circular.lua │ │ ├── octagonal.lua │ │ ├── spiral.lua │ │ └── spiral_rectangular.lua ├── pll │ ├── c2mos_frequency_divider.lua │ └── pfd.lua ├── stdcells │ ├── 1_inv_gate.lua │ ├── 21_gate.lua │ ├── 221_gate.lua │ ├── 22_gate.lua │ ├── all_cells.lua │ ├── and_gate.lua │ ├── base.lua │ ├── buf.lua │ ├── cinv.lua │ ├── colstop.lua │ ├── dff.lua │ ├── dffnq.lua │ ├── dffnrq.lua │ ├── dffnrsq.lua │ ├── dffnsq.lua │ ├── dffpq.lua │ ├── dffprq.lua │ ├── dffprsq.lua │ ├── dffpsq.lua │ ├── endcell.lua │ ├── fill.lua │ ├── generic2bit.lua │ ├── half_adder.lua │ ├── harness.lua │ ├── isogate.lua │ ├── latch.lua │ ├── leftcolstop.lua │ ├── mux.lua │ ├── nand_gate.lua │ ├── nand_nor_layout_base.lua │ ├── nor_gate.lua │ ├── not_gate.lua │ ├── or_gate.lua │ ├── rightcolstop.lua │ ├── rowstop.lua │ ├── tbuf.lua │ ├── tgate.lua │ ├── tie_high.lua │ ├── tie_highlow.lua │ ├── tie_low.lua │ ├── xnor_gate.lua │ └── xor_gate.lua └── transmitter │ └── memory.lua ├── configure.sh ├── doc ├── Makefile ├── celldesign.pdf ├── doc.tex ├── export.pdf ├── info │ ├── mosfet.png │ ├── mosfet_complex.png │ └── ringoscillator.png ├── presentation.pdf ├── src │ ├── Makefile │ ├── celldesign │ │ ├── Makefile │ │ ├── code │ │ │ ├── hierarchy_example.lua │ │ │ ├── merge_into_example.lua │ │ │ ├── momcap.lua │ │ │ ├── ringoscillator.lua │ │ │ ├── ringoscillator_anchor.lua │ │ │ ├── ringoscillator_move_point.lua │ │ │ ├── ringoscillator_nocopy.lua │ │ │ └── simple_rectangle.lua │ │ └── main.tex │ ├── export │ │ ├── Makefile │ │ └── main.tex │ ├── preamble.tex │ ├── presentation │ │ ├── Makefile │ │ ├── beamerthemeopc.sty │ │ ├── main.auxlock │ │ ├── main.snm │ │ ├── main.tex │ │ └── preamble.tex │ ├── techdoc │ │ ├── Makefile │ │ └── main.tex │ ├── techfiles │ │ ├── Makefile │ │ └── main.tex │ └── userguide │ │ ├── Makefile │ │ └── main.tex ├── techdoc.pdf ├── techfiles.pdf └── userguide.pdf ├── examples ├── autofill │ ├── main.lua │ └── run.sh ├── cells │ ├── LC_oscillator.lua │ ├── comparator.lua │ ├── current_starved_ringoscillator.lua │ ├── mosfet.lua │ ├── ringoscillator.lua │ └── run.sh ├── digital │ ├── generate.lua │ └── run.sh ├── place_and_route_automatic │ ├── cellinfo.lua │ ├── generate_cell.lua │ ├── place_route_generate.lua │ ├── run.sh │ └── serial_ctrl.v └── svg │ ├── gilfoyle.lua │ ├── gilfoyle.svg │ ├── pineapple.lua │ ├── pineapple.svg │ ├── run.sh │ ├── talentandsweat.lua │ └── talentandsweat.svg ├── export ├── debug │ └── init.lua ├── gdstext │ └── init.lua ├── html │ └── init.lua ├── luaSKILL │ └── init.lua ├── magic │ └── init.lua ├── oasis │ └── init.lua ├── ppm │ └── init.lua ├── svg │ └── init.lua ├── template │ └── init.lua └── tikz │ └── init.lua ├── interface └── virtuoso │ ├── backup.il │ ├── call.il │ ├── cdsinit.il.sample │ ├── cells.il │ ├── edit_update.il │ ├── export.il │ ├── init.il │ ├── menu.il │ ├── misc.il │ ├── settings.il │ └── subcell.il ├── logo ├── Makefile ├── logo.pdf ├── logo.tex └── logo.txt ├── resources ├── extract_pinoffsets.lua ├── extract_stdcells_netlists.sh ├── opc.lib ├── opc.lylvs ├── opc.lyp ├── opc.v └── stdcells_netlists │ ├── 1_inv_gate.sp │ ├── 21_gate.sp │ ├── 221_gate.sp │ ├── 22_gate.sp │ ├── all_cells.sp │ ├── and_gate.sp │ ├── buf.sp │ ├── cinv.sp │ ├── colstop.sp │ ├── dff.sp │ ├── dffnq.sp │ ├── dffnrq.sp │ ├── dffnsq.sp │ ├── dffpq.sp │ ├── dffprq.sp │ ├── dffpsq.sp │ ├── endcell.sp │ ├── generic2bit.sp │ ├── half_adder.sp │ ├── harness.sp │ ├── isogate.sp │ ├── latch.sp │ ├── latch_cell.sp │ ├── leftcolstop.sp │ ├── mux.sp │ ├── nand_gate.sp │ ├── nand_nor_layout_base.sp │ ├── nor_gate.sp │ ├── not_gate.sp │ ├── or_gate.sp │ ├── register.sp │ ├── rightcolstop.sp │ ├── shiftregister.sp │ ├── tbuf.sp │ ├── test.sp │ ├── tgate.sp │ ├── xnor_gate.sp │ └── xor_gate.sp ├── saradc ├── DAC_differential.lua ├── caparray.lua ├── comparator.lua ├── sample_and_hold.lua ├── switch_network_down.lua └── switch_network_up.lua ├── src ├── Makefile ├── bltrshape.c ├── bltrshape.h ├── cells.c ├── cells.h ├── cells │ └── powergrid.c ├── cmdoptions.c ├── cmdoptions.h ├── cmdoptions_def.c ├── cpu.c ├── cpu.h ├── create_latex_API_doc.c ├── embed_compiled_lua_file.c ├── export.c ├── export.h ├── export_common.c ├── export_common.h ├── export_writer.c ├── export_writer.h ├── filesystem.c ├── filesystem.h ├── gdsexport.c ├── gdsexport.h ├── gdsparser.c ├── gdsparser.h ├── generate_manpage.c ├── geometry.c ├── geometry.h ├── geometry_triangulate.c ├── graphics.c ├── graphics.h ├── hashmap.c ├── hashmap.h ├── info.c ├── info.h ├── lcheck.c ├── lcheck.h ├── ldebug.c ├── ldebug.h ├── ldir.c ├── ldir.h ├── lgenerics.c ├── lgenerics.h ├── lgeometry.c ├── lgeometry.h ├── lobject.c ├── lobject.h ├── lplacement.c ├── lplacement.h ├── lplacer.c ├── lplacer.h ├── lplacer_classic.c ├── lplacer_classic.h ├── lplacer_common.c ├── lplacer_common.h ├── lplacer_floorplan.h ├── lplacer_nonoverlapping.c ├── lplacer_nonoverlapping.h ├── lplacer_rand.c ├── lplacer_rand.h ├── lpoint.c ├── lpoint.h ├── lpostprocess.c ├── lpostprocess.h ├── lrouter.c ├── lrouter.h ├── lrouter_field.c ├── lrouter_field.h ├── lrouter_min_heap.c ├── lrouter_min_heap.h ├── lrouter_moves.c ├── lrouter_moves.h ├── lrouter_net.c ├── lrouter_net.h ├── lrouter_queue.c ├── lrouter_queue.h ├── lrouter_route.c ├── lrouter_route.h ├── lua │ ├── lapi.c │ ├── lapi.h │ ├── lauxlib.c │ ├── lauxlib.h │ ├── lbaselib.c │ ├── lcode.c │ ├── lcode.h │ ├── lcorolib.c │ ├── lctype.c │ ├── lctype.h │ ├── ldblib.c │ ├── ldebug.c │ ├── ldebug.h │ ├── ldo.c │ ├── ldo.h │ ├── ldump.c │ ├── lfunc.c │ ├── lfunc.h │ ├── lgc.c │ ├── lgc.h │ ├── linit.c │ ├── liolib.c │ ├── ljumptab.h │ ├── llex.c │ ├── llex.h │ ├── llimits.h │ ├── lmathlib.c │ ├── lmem.c │ ├── lmem.h │ ├── loadlib.c │ ├── lobject.c │ ├── lobject.h │ ├── lopcodes.c │ ├── lopcodes.h │ ├── lopnames.h │ ├── loslib.c │ ├── lparser.c │ ├── lparser.h │ ├── lprefix.h │ ├── lstate.c │ ├── lstate.h │ ├── lstring.c │ ├── lstring.h │ ├── lstrlib.c │ ├── ltable.c │ ├── ltable.h │ ├── ltablib.c │ ├── ltm.c │ ├── ltm.h │ ├── lua.h │ ├── lua.hpp │ ├── luac.c │ ├── luaconf.h │ ├── lualib.h │ ├── lundump.c │ ├── lundump.h │ ├── lvm.c │ ├── lvm.h │ ├── lzio.c │ └── lzio.h ├── lua_util.c ├── lua_util.h ├── lutil.c ├── lutil.h ├── main.api_help.c ├── main.api_help.h ├── main.api_help │ ├── aux.c │ ├── curve.c │ ├── generics.c │ ├── geometry.c │ ├── global.c │ ├── graphics.c │ ├── layouthelpers.c │ ├── object.c │ ├── pcell.c │ ├── placement.c │ ├── placer.c │ ├── point.c │ ├── router.c │ ├── routing.c │ ├── technology.c │ └── util.c ├── main.c ├── main.cell.c ├── main.cell.h ├── main.functions.c ├── main.functions.h ├── main.gds.c ├── main.gds.h ├── main.tutorial.c ├── main.tutorial.h ├── main.verilog.c ├── main.verilog.h ├── math.h ├── modules │ ├── aux.lua │ ├── check.lua │ ├── generator.lua │ ├── globals.lua │ ├── graphics.lua │ ├── layouthelpers.lua │ ├── load.lua │ ├── pcell.lua │ ├── placement.lua │ ├── routing.lua │ ├── stack.lua │ ├── util.lua │ ├── verilog.lua │ └── verilogprocessor.lua ├── object.c ├── object.h ├── pcell.c ├── pcell.h ├── placement.c ├── placement.h ├── point.c ├── point.h ├── polygon.c ├── polygon.h ├── postprocess.c ├── postprocess.h ├── scripts │ ├── assistant.lua │ ├── list_anchors.lua │ ├── list_cells.lua │ ├── list_parameters.lua │ └── templates.lua ├── shape.c ├── shape.h ├── skillexport.c ├── skillexport.h ├── support │ └── gdstypetable.lua ├── tagged_value.c ├── tagged_value.h ├── technology.c ├── technology.h ├── terminal_colors.c ├── terminal_colors.h ├── transformationmatrix.c ├── transformationmatrix.h ├── union.c ├── union.h ├── util.c ├── util.h ├── util_cmodule.c ├── util_cmodule.h ├── vector.c ├── vector.h └── version.h └── tech ├── freePDK45 ├── config.lua ├── constraints.lua ├── layermap.lua └── vias.lua ├── opc ├── config.lua ├── constraints.lua ├── layermap.lua ├── place_route │ └── cellinfo.lua └── vias.lua ├── skywater130 ├── config.lua ├── constraints.lua ├── layermap.lua └── vias.lua └── template ├── config.lua └── layermap.lua /.gitignore: -------------------------------------------------------------------------------- 1 | # main programs and generated code files 2 | Makefile 3 | opc 4 | opc-debug 5 | !tech/opc 6 | src/embed_compiled_lua_file 7 | src/create_latex_API_doc 8 | src/config.h 9 | src/modulemanager.c 10 | src/modulemanager.h 11 | src/scriptmanager.c 12 | src/scriptmanager.h 13 | src/generate_manpage 14 | src/tags 15 | src/debug 16 | src/release 17 | opc.1 18 | 19 | # generated layouts and helpers 20 | openPCells.* 21 | pineapple.gds 22 | talentandsweat.gds 23 | gilfoyle.gds 24 | openPCells_extracted.cir 25 | pfile.lua 26 | verilogimport 27 | 28 | # generated files in example folder 29 | examples/digital/digital.lua 30 | examples/*/*.gds 31 | examples/*/*.sp 32 | 33 | # NDA-related 34 | tech/GF22FDSOI 35 | tech/cmos22fdsoi 36 | tech/TSMC28HPCplus 37 | 38 | # build object files 39 | src/*.o 40 | 41 | # code tags 42 | tags 43 | 44 | # lua object files 45 | src/lua/lua 46 | src/lua/luac 47 | src/lua/*.o 48 | src/lua/liblua.a 49 | 50 | # tex auxiliary files 51 | *.aux 52 | *.log 53 | *.toc 54 | *.pygtex 55 | *_minted* 56 | *.nav 57 | *.out 58 | *.vrb 59 | 60 | # development information 61 | devinfo 62 | 63 | # test code 64 | srctodo 65 | 66 | # test files 67 | testfiles 68 | debug 69 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | Hello and thanks for considering contributing to openPCells. This project is intended to be used and enhanced by many people, gathering different kinds of 3 | knowledge. 4 | 5 | ## How do I contribute? 6 | All kinds of contributions are welcome, including (but not limited to) feature requests, bug fixes, cell defintions, documentation enhancements and technology 7 | definitions. Furthermore, the provided cells are currently not being tested in many technologies, as this needs access to those. If you are working with 8 | integrated circuits and have technology access, testing the generated layouts of various cells with different parameter values is very valuable for improving the 9 | code of the cells. 10 | 11 | I try to add stuff that needs fixing or implementing to the todo file. There is of course also the issue list on github, but that's probably out-of-sync. 12 | -------------------------------------------------------------------------------- /cells/LC_oscillator/fill.lua: -------------------------------------------------------------------------------- 1 | function layout(cell, _P, env) 2 | local filler = pcell.create_layout("auxiliary/decap", "_filler", { 3 | cellsize = env.decap.cellsize, 4 | meshmetals = { 8 }, 5 | meshmetalwidths = { 1250 }, 6 | drawgrid = false, 7 | drawmoscap = false, 8 | }) 9 | --cell:merge_into(filler:copy():move_to(point.create(-60000, -15000))) 10 | --cell:merge_into(filler:copy():move_to(point.create(-60000, -25000))) 11 | end 12 | -------------------------------------------------------------------------------- /cells/RF/patterned_ground_shield.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameters( 3 | { "width", 100 }, 4 | { "space", 100 }, 5 | { "regionwidth", 10000 } 6 | ) 7 | end 8 | 9 | function layout(shield, _P) 10 | local pitch = _P.width + _P.space 11 | local numlines = _P.regionwidth // (2 * pitch) 12 | 13 | -- assemble quarter layout 14 | local quarter = object.create("quarter") 15 | for i = 1, numlines do 16 | geometry.rectanglebltr(quarter, generics.metal(3), 17 | point.create(-numlines * pitch + _P.space / 2 + (i - 1) * pitch, -numlines * pitch), 18 | point.create(-numlines * pitch + _P.space / 2 + (i - 1) * pitch + _P.width, -numlines * pitch + (i - 1) * pitch + _P.width + _P.space / 2) 19 | ) 20 | end 21 | 22 | -- assemble half layout 23 | local half = object.create("half") 24 | half:merge_into(quarter) 25 | half:merge_into(quarter:mirror_at_yaxis()) 26 | 27 | -- assemble full layout 28 | shield:merge_into(half) 29 | shield:merge_into(half:rotate_90_left()) 30 | shield:merge_into(half:rotate_90_left()) 31 | shield:merge_into(half:rotate_90_left()) 32 | end 33 | -------------------------------------------------------------------------------- /cells/RF/transmission_line.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameters( 3 | { "width", 5000 }, 4 | { "length", 50000 }, 5 | { "groundwidth", 10000 }, 6 | { "groundspace", 5000 }, 7 | { "shieldwidth", 100 }, 8 | { "shieldspace", 100 }, 9 | { "metalnum", -1 }, 10 | { "shieldmetal", 1 } 11 | ) 12 | end 13 | 14 | function layout(tline, _P) 15 | geometry.rectangle(tline, generics.metal(_P.metalnum), _P.length, _P.width) 16 | geometry.rectangle(tline, generics.metal(_P.metalnum), _P.length, _P.groundwidth, 0, 0, 1, 2, 0, _P.width + 2 * _P.groundspace + _P.groundwidth) 17 | geometry.rectangle(tline, generics.metal(_P.shieldmetal), _P.shieldwidth, _P.width + 2 * _P.groundspace + 2 * _P.groundwidth, 0, 0, _P.length // (_P.shieldwidth + _P.shieldspace), 1, _P.shieldwidth + _P.shieldspace, 0) 18 | geometry.via(tline, _P.shieldmetal, _P.metalnum, _P.length, _P.groundwidth, 0, 0, 1, 2, 0, _P.width + 2 * _P.groundwidth) 19 | tline:add_port("P1", generics.metalport(_P.metalnum), point.create(-_P.length / 2, 0)) 20 | tline:add_port("PG1", generics.metalport(_P.metalnum), point.create(-_P.length / 2, _P.width / 2 + _P.groundspace + _P.groundwidth / 2)) 21 | tline:add_port("PG1", generics.metalport(_P.metalnum), point.create(-_P.length / 2, -_P.width / 2 - _P.groundspace - _P.groundwidth / 2)) 22 | tline:add_port("P2", generics.metalport(_P.metalnum), point.create( _P.length / 2, 0)) 23 | tline:add_port("PG2", generics.metalport(_P.metalnum), point.create( _P.length / 2, _P.width / 2 + _P.groundspace + _P.groundwidth / 2)) 24 | tline:add_port("PG2", generics.metalport(_P.metalnum), point.create( _P.length / 2, -_P.width / 2 - _P.groundspace - _P.groundwidth / 2)) 25 | end 26 | -------------------------------------------------------------------------------- /cells/__test/align_sub.lua: -------------------------------------------------------------------------------- 1 | function layout(cell) 2 | geometry.ring(cell, generics.metal(1), point.create(0, 0), 1000, 1000, 100) 3 | cell:set_alignment_box( 4 | point.create(-500, -500), 5 | point.create(500, 500), 6 | point.create(-400, -400), 7 | point.create(400, 400) 8 | ) 9 | end 10 | -------------------------------------------------------------------------------- /cells/__test/align_top.lua: -------------------------------------------------------------------------------- 1 | function layout(cell) 2 | local subref = pcell.create_layout("__test/align_sub", "sub") 3 | local subcenter = cell:add_child(subref, "sub1") 4 | subcenter:translate(2000, 2000) 5 | local subtop = cell:add_child(subref, "subtop") 6 | subtop:abut_top(subcenter) 7 | subtop:align_left(subcenter) 8 | local subbottom = cell:add_child(subref, "subbottom") 9 | subbottom:abut_bottom(subcenter) 10 | subbottom:align_left(subcenter) 11 | local subleft = cell:add_child(subref, "subleft") 12 | subleft:abut_left(subcenter) 13 | subleft:align_bottom(subcenter) 14 | local subright = cell:add_child(subref, "subright") 15 | subright:abut_right(subcenter) 16 | subright:align_bottom(subcenter) 17 | end 18 | -------------------------------------------------------------------------------- /cells/__test/angled_path.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | 3 | end 4 | 5 | function layout(cell) 6 | geometry.any_angle_path(cell, generics.metal(1), { 7 | point.create(0, 0), 8 | point.create(10000, 100000), 9 | point.create(15000, 100000), 10 | }, 5000, 100, true, true) 11 | end 12 | -------------------------------------------------------------------------------- /cells/__test/path.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | 3 | end 4 | 5 | function layout(cell) 6 | geometry.path(cell, generics.metal(1), { point.create(-100, 0), point.create(100, 0) }, 20) 7 | end 8 | -------------------------------------------------------------------------------- /cells/__test/pathextension.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | 3 | end 4 | 5 | function layout(cell, _P) 6 | geometry.path(cell, generics.metal(1), { point.create(0, 0), point.create(1000, 0) }, 100, "square") 7 | end 8 | -------------------------------------------------------------------------------- /cells/__test/premapped.lua: -------------------------------------------------------------------------------- 1 | function layout(cell) 2 | geometry.rectangle(cell, generics.premapped(nil, { gds = { layer = 0, purpose = 0 }, SKILL = { layer = "M1", purpose = "drawing" } }), 100, 100) 3 | end 4 | -------------------------------------------------------------------------------- /cells/__test/rectangle.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | end 3 | 4 | function layout(cell, _P) 5 | geometry.rectangle(cell, generics.metal(1), 50, 50, 0, 50) 6 | --geometry.rectangle(cell, generics.metal(1), 50, 50):translate(0, -50) 7 | --cell:add_anchor("A", point.create(0, 75)) 8 | end 9 | -------------------------------------------------------------------------------- /cells/__test/rotation.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | 3 | end 4 | 5 | function layout(cell) 6 | local subref = object.create("subref") 7 | geometry.rectanglebltr(subref, generics.metal(1), point.create(0, 0), point.create(100, 100)) 8 | local sub = cell:add_child(subref, "sub") 9 | sub:rotate_90_left() 10 | end 11 | -------------------------------------------------------------------------------- /cells/__test/sub.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | 3 | end 4 | 5 | function layout(cell, _P) 6 | local subsub = pcell.create_layout("__test/subsub", "subsub") 7 | cell:add_child(subsub, "subsub0"):translate(-100, -100) 8 | cell:add_child(subsub, "subsub1"):translate( 100, -100) 9 | cell:add_child(subsub, "subsub2"):translate( 0, 100) 10 | 11 | geometry.rectangle(cell, generics.metal(1), 20, 20) 12 | end 13 | -------------------------------------------------------------------------------- /cells/__test/subsub.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | 3 | end 4 | 5 | function layout(cell, _P) 6 | geometry.via(cell, 1, 2, 100, 100) 7 | end 8 | -------------------------------------------------------------------------------- /cells/__test/top.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | 3 | end 4 | 5 | function layout(cell, _P) 6 | -- place flat rectangle 7 | --geometry.rectangle(cell, generics.metal(1), 200, 200) 8 | 9 | -- place subcells 10 | local sub = pcell.create_layout("__test/sub", "sub") 11 | cell:add_child(sub, "sub0"):translate( 0, 500) 12 | cell:add_child(sub, "sub2"):translate( 0, -500):flipy() 13 | cell:add_child(sub, "sub3"):translate( 500, 0) 14 | cell:add_child(sub, "sub4"):translate(-500, 0) 15 | end 16 | -------------------------------------------------------------------------------- /cells/__test/translation.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | end 3 | 4 | function layout(cell, _P) 5 | geometry.rectangle(cell, generics.metal(1), 50, 50) 6 | cell:translate(200, 0) 7 | geometry.rectangle(cell, generics.metal(2), 50, 50) 8 | end 9 | -------------------------------------------------------------------------------- /cells/__test/via.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | 3 | end 4 | 5 | function layout(cell) 6 | geometry.via(cell, 1, 2, 80, 60) 7 | end 8 | -------------------------------------------------------------------------------- /cells/analog/LC_oscillator.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | 3 | end 4 | 5 | function layout(osc, _P) 6 | local inductor = pcell.create_layout("passive/inductor/octagonal", "inductor", { turns = 1, metalnum = -2 }) 7 | osc:merge_into(inductor) 8 | 9 | local cap = pcell.create_layout("passive/capacitor/mom", "momcap", { fingers = 20, fheight = 2000, firstmetal = 3, lastmetal = 5 }) 10 | osc:merge_into(cap:translate(0, -20000)) 11 | 12 | local ccp = pcell.create_layout("analog/cross_coupled_pair", "cross_coupled_pair") 13 | osc:merge_into(ccp) 14 | end 15 | -------------------------------------------------------------------------------- /cells/analog/crystal_IC_oscillator.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameters( 3 | { "invfingers", 4 }, 4 | { "resfingers", 50 } 5 | ) 6 | end 7 | 8 | function layout(oscillator, _P) 9 | local gatecontacts = util.fill_all_with(_P.invfingers, "center") 10 | local npcontacts = util.fill_even_with(_P.invfingers + 1, "inner", "power") 11 | local cmosref = pcell.create_layout("basic/cmos", "mosfets", { 12 | gatelength = 40, 13 | gatespace = 90, 14 | gatecontactpos = gatecontacts, 15 | pcontactpos = npcontacts, 16 | ncontactpos = npcontacts, 17 | separation = 400, 18 | }) 19 | 20 | local resref = pcell.create_layout("basic/polyresistor", "resistor", { nxfingers = _P.resfingers, nyfingers = 2, dummies = 0, xspace = 90, contactheight = 200, extension = 300 }) 21 | 22 | local moscore = oscillator:add_child(cmosref, "moscore") 23 | local polyres = oscillator:add_child(resref, "resistor") 24 | end 25 | -------------------------------------------------------------------------------- /cells/analog/currentmirror.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameters( 3 | { "ifingers", 4 }, 4 | { "ofingers", 4 }, 5 | { "interdigitate", false } 6 | --{ "sourcemetal", 2 }, 7 | --{ "outmetal", 3 } 8 | ) 9 | end 10 | 11 | function layout(currentmirror, _P) 12 | local baseopt = { 13 | fingerwidth = 500, 14 | connectsource = true, 15 | connsourcewidth = 200, 16 | connsourcespace = 100, 17 | drawtopgate = true, 18 | drawtopgatestrap = true, 19 | topgatecompsd = false, 20 | }) 21 | local diode = pcell.create_layout("basic/mosfet", "diode", util.add_options(baseopt, { 22 | fingers = _P.ifingers, 23 | diodeconnected = true, 24 | })) 25 | local source = pcell.create_layout("basic/mosfet", "source", util.add_options(baseopt, { 26 | fingers = _P.ofingers, 27 | conndrainmetal = 2, 28 | drawdrainvia = true, 29 | connectdrain = true, 30 | })) 31 | diode:move_anchor("sourcedrainrightbl") 32 | source:move_anchor("sourcedrainleftbl") 33 | currentmirror:merge_into(diode) 34 | currentmirror:merge_into(source) 35 | 36 | geometry.rectanglebltr(currentmirror, generics.metal(1), diode:get_anchor("topgate1bl"), source:get_anchor(string.format("topgate%dtr", _P.ofingers))) 37 | end 38 | -------------------------------------------------------------------------------- /cells/analog/track_hold.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | 3 | end 4 | 5 | function layout(cell, _P) 6 | local momcap = pcell.create_layout("passive/capacitor/mom", "momcap") 7 | local mom1 = cell:add_child(momcap, "mom2") 8 | mom1:move_anchor("minus") 9 | local mom2 = cell:add_child(momcap, "mom2") 10 | mom2:move_anchor("plus") 11 | mom2:flipy() 12 | end 13 | -------------------------------------------------------------------------------- /cells/basic/diode.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameters( 3 | { "diodetype", "pn", posvals = set("pn", "np") }, 4 | { "width", 1000 }, 5 | { "height", 1000 }, 6 | { "extension", 100 } 7 | ) 8 | end 9 | 10 | function layout(diode, _P) 11 | geometry.rectangle(diode, generics.other("active"), _P.width, _P.height) 12 | geometry.rectangle(diode, generics.contact("active"), _P.width, _P.height) 13 | geometry.rectangle(diode, generics.other("soiopen"), _P.width + 2 * _P.extension, _P.height + 2 * _P.extension) 14 | --geometry.rectangle(diode, generics.diode(_P.diodetype), _P.width + 2 * _P.extension, _P.height + 2 * _P.extension) 15 | end 16 | -------------------------------------------------------------------------------- /cells/passive/inductor/spiral.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameters( 3 | { "turns", 3 }, 4 | { "width", 6000 }, 5 | { "spacing", 6000 }, 6 | { "innerradius", 50000 }, 7 | { "pointsperturn", 8 }, 8 | { "metalnum", -1 }, 9 | { "grid", 100 } 10 | ) 11 | end 12 | 13 | local function fix_to_grid(val, grid) 14 | if val < 0 then 15 | return grid * math.ceil(val / grid) 16 | else 17 | return grid * math.floor(val / grid) 18 | end 19 | end 20 | 21 | function layout(inductor, _P) 22 | local pitch = _P.width + _P.spacing 23 | local pathpts = {} 24 | local append = util.make_insert_xy(pathpts) 25 | local startangle = -math.pi / 4 26 | local numpoints = _P.turns * _P.pointsperturn 27 | 28 | local dir = math.pi / 2 29 | local x = fix_to_grid(_P.innerradius * math.cos(startangle), _P.grid) 30 | local y = fix_to_grid(_P.innerradius * math.sin(startangle), _P.grid) 31 | local addr = math.sqrt(1) * _P.innerradius 32 | for i = 1, numpoints do 33 | append(x, y) 34 | --addr = addr + pitch / 2 35 | --addr = addr + pitch / 10 36 | local dx = addr * math.cos(dir) 37 | local dy = addr * math.sin(dir) 38 | x = fix_to_grid(x + dx, _P.grid) 39 | y = fix_to_grid(y + dy, _P.grid) 40 | dir = dir + 2 * math.pi / _P.pointsperturn 41 | end 42 | --inductor:merge_into(geometry.any_angle_path(generics.metal(_P.metalnum), pathpts, _P.width, _P.grid)) 43 | geometry.path(inductor, generics.metal(_P.metalnum), pathpts, _P.width) 44 | --inductor:merge_into(geometry.rectangle(generics.metal(-2), 45 | -- fix_to_grid(math.sqrt(2) * (_P.innerradius + 0 * pitch), _P.grid), 46 | -- fix_to_grid(math.sqrt(2) * (_P.innerradius + 0 * pitch), _P.grid) 47 | --)) 48 | --inductor:merge_into(geometry.rectangle(generics.metal(-3), 49 | -- fix_to_grid(math.sqrt(2) * _P.innerradius + 2 * pitch, _P.grid), 50 | -- fix_to_grid(math.sqrt(2) * _P.innerradius + 2 * pitch, _P.grid) 51 | --)) 52 | end 53 | -------------------------------------------------------------------------------- /cells/passive/inductor/spiral_rectangular.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameters( 3 | { "turns(Number of Turns)", 3 }, 4 | { "width(Width)", 6000 }, 5 | { "spacing(Line Spacing)", 6000 }, 6 | { "innerdiameter(Inner Diameter)", 10000 }, 7 | { "metalnum(Conductor Metal)", -1, "integer" }, 8 | { "method(Method)", "rectangularyx" } 9 | ) 10 | end 11 | 12 | function layout(inductor, _P) 13 | local pathpts = {} 14 | local append = util.make_insert_xy(pathpts) 15 | local pitch = _P.width + _P.spacing 16 | for i = 1, _P.turns do 17 | local xy = (_P.innerdiameter + _P.width) / 2 + (i - 1) * pitch 18 | append( xy + 0.00 * pitch, -xy + 0.00 * pitch) 19 | append( xy + 0.00 * pitch, xy + 0.50 * pitch) 20 | append(-xy - 0.50 * pitch, xy + 0.50 * pitch) 21 | append(-xy - 0.50 * pitch, -xy - 1.00 * pitch) 22 | end 23 | geometry.path_midpoint(inductor, generics.metal(_P.metalnum), pathpts, _P.width, _P.method, true) 24 | geometry.rectangle(inductor, generics.metal(-2), 2 * math.floor(math.sqrt(2) * _P.innerdiameter / 2 / 2), 2 * math.floor(math.sqrt(2) * _P.innerdiameter / 2 / 2)) 25 | end 26 | -------------------------------------------------------------------------------- /cells/stdcells/1_inv_gate.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameters( 3 | { "subgate", "nand_gate", posvals = set("nand_gate", "nor_gate", "xor_gate") }, 4 | { "subgatefingers", 1 }, 5 | { "notfingers", 1 } 6 | ) 7 | pcell.inherit_parameters("stdcells/base") 8 | end 9 | 10 | function layout(gate, _P) 11 | local xpitch = _P.gatelength + _P.gatespace 12 | 13 | local subgatename = string.format("stdcells/%s", _P.subgate) 14 | 15 | local subgate_baseparameters = {} 16 | for k, v in pairs(_P) do 17 | if pcell.has_parameter(subgatename, k) then 18 | subgate_baseparameters[k] = v 19 | end 20 | end 21 | local subgateref = pcell.create_layout(subgatename, "subgate", util.add_options(subgate_baseparameters, { 22 | fingers = _P.subgatefingers, 23 | })) 24 | gate:merge_into(subgateref) 25 | 26 | local notgate_baseparameters = {} 27 | for k, v in pairs(_P) do 28 | if pcell.has_parameter("stdcells/not_gate", k) then 29 | notgate_baseparameters[k] = v 30 | end 31 | end 32 | local invref = pcell.create_layout("stdcells/not_gate", "inv", util.add_options(notgate_baseparameters, { 33 | fingers = _P.notfingers, 34 | shiftoutput = xpitch / 2, 35 | })) 36 | invref:abut_right(subgateref) 37 | gate:merge_into(invref) 38 | 39 | -- draw connection 40 | geometry.rectanglebltr(gate, generics.metal(1), 41 | subgateref:get_anchor("O") .. invref:get_anchor("I"):translate(xpitch - _P.sdwidth / 2 - _P.routingspace, 0), 42 | invref:get_anchor("I"):translate(xpitch - _P.sdwidth / 2 - _P.routingspace, _P.routingwidth) 43 | ) 44 | 45 | gate:inherit_alignment_box(subgateref) 46 | gate:inherit_alignment_box(invref) 47 | 48 | -- ports 49 | gate:add_port_with_anchor("A", generics.metalport(1), subgateref:get_anchor("A")) 50 | gate:add_port_with_anchor("B", generics.metalport(1), subgateref:get_anchor("B")) 51 | gate:add_port_with_anchor("O", generics.metalport(1), invref:get_anchor("O")) 52 | gate:add_port("VDD", generics.metalport(1), subgateref:get_anchor("VDD")) 53 | gate:add_port("VSS", generics.metalport(1), subgateref:get_anchor("VSS")) 54 | end 55 | -------------------------------------------------------------------------------- /cells/stdcells/21_gate.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | A --------------- GATE2 3 | GATE2 ---- O 4 | B2 ----- GATE1 --- GATE2 5 | GATE1 6 | B1 ----- GATE1 7 | ]] 8 | function parameters() 9 | pcell.add_parameters( 10 | { "gate1", "nand_gate" }, 11 | { "gate2", "nor_gate" } 12 | ) 13 | end 14 | 15 | function layout(gate, _P) 16 | local bp = pcell.get_parameters("stdcells/base"); 17 | 18 | local gate1ref = pcell.create_layout(string.format("stdcells/%s", _P.gate1), "gate1") 19 | local gate1 = gate:add_child(gate1ref, "gate1") 20 | 21 | local gate2ref = pcell.create_layout(string.format("stdcells/%s", _P.gate2), "gate2") 22 | local gate2 = gate:add_child(gate2ref, "gate2") 23 | gate2:abut_left(gate1) 24 | 25 | gate:inherit_alignment_box(gate1) 26 | gate:inherit_alignment_box(gate2) 27 | 28 | -- draw connections 29 | geometry.path(gate, generics.metal(1), 30 | geometry.path_points_yx(gate1:get_anchor("O"), { 31 | gate2:get_anchor("B") 32 | }), 33 | bp.sdwidth) 34 | 35 | --draw ports 36 | gate:add_port("A", generics.metalport(1), gate2:get_anchor("A")) 37 | gate:add_port("B1", generics.metalport(1), gate1:get_anchor("A")) 38 | gate:add_port("B2", generics.metalport(1), gate1:get_anchor("B")) 39 | gate:add_port("O", generics.metalport(1), gate2:get_anchor("O")) 40 | gate:add_port("VDD", generics.metalport(1), gate1:get_anchor("VDD")) 41 | gate:add_port("VSS", generics.metalport(1), gate1:get_anchor("VSS")) 42 | end 43 | -------------------------------------------------------------------------------- /cells/stdcells/and_gate.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameters( 3 | { "nandfingers", 1 }, 4 | { "notfingers", 1 } 5 | ) 6 | pcell.inherit_parameters("stdcells/base") 7 | end 8 | 9 | function layout(gate, _P) 10 | local baseparameters = {} 11 | for k, v in pairs(_P) do 12 | if pcell.has_parameter("stdcells/1_inv_gate", k) then 13 | baseparameters[k] = v 14 | end 15 | end 16 | local subgate = pcell.create_layout("stdcells/1_inv_gate", "and_gate", util.add_options(baseparameters, { 17 | subgate = "nand_gate", 18 | subgatefingers = _P.nandfingers, 19 | notfingers = _P.notfingers, 20 | })) 21 | gate:exchange(subgate) 22 | end 23 | -------------------------------------------------------------------------------- /cells/stdcells/buf.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameters( 3 | { "ifingers", 1 }, 4 | { "ofingers", 1 }, 5 | { "shiftinput1", 0 }, 6 | { "shiftinput2", 0 } 7 | ) 8 | pcell.inherit_parameters("stdcells/base") 9 | end 10 | 11 | function layout(gate, _P) 12 | local baseparameters = {} 13 | for name, value in pairs(_P) do 14 | if pcell.has_parameter("stdcells/not_gate", name) then 15 | baseparameters[name] = value 16 | end 17 | end 18 | local iinv = pcell.create_layout("stdcells/not_gate", "iinv", util.add_options(baseparameters, { 19 | fingers = _P.ifingers, 20 | shiftinput = _P.shiftinput1, 21 | shiftoutput = _P.gatelength / 2 + _P.gatespace / 2 22 | })) 23 | 24 | local oinv = pcell.create_layout("stdcells/not_gate", "oinv", util.add_options(baseparameters, { 25 | fingers = _P.ofingers, 26 | shiftinput = _P.shiftinput2, 27 | shiftoutput = _P.gatelength / 2 + _P.gatespace / 2 28 | })) 29 | oinv:abut_right(iinv) 30 | gate:merge_into(iinv) 31 | gate:merge_into(oinv) 32 | 33 | -- draw connection 34 | local ishift = _P.ifingers % 2 == 0 and 0 or 1 35 | geometry.path(gate, generics.metal(1), 36 | geometry.path_points_yx(iinv:get_anchor("O"), { 37 | oinv:get_anchor("I"), 38 | }), _P.sdwidth) 39 | 40 | gate:inherit_alignment_box(iinv) 41 | gate:inherit_alignment_box(oinv) 42 | 43 | -- anchors 44 | gate:add_anchor("in", iinv:get_anchor("I")) 45 | gate:add_anchor("iout", iinv:get_anchor("O")) 46 | gate:add_anchor("bout", oinv:get_anchor("O")) 47 | 48 | -- ports 49 | gate:add_port("I", generics.metalport(1), iinv:get_anchor("I")) 50 | gate:add_port("O", generics.metalport(1), oinv:get_anchor("O")) 51 | gate:add_port("VDD", generics.metalport(1), oinv:get_anchor("VDD")) 52 | gate:add_port("VSS", generics.metalport(1), oinv:get_anchor("VSS")) 53 | end 54 | -------------------------------------------------------------------------------- /cells/stdcells/colstop.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameter("fingers", 1) 3 | pcell.add_parameter("leftnotright", true) 4 | pcell.inherit_parameters("stdcells/base") 5 | end 6 | 7 | function layout(gate, _P) 8 | local gatecontactpos = { "dummy" } 9 | local sdcontacts 10 | if _P.leftnotright then 11 | sdcontacts = { "power", "unused" } 12 | else 13 | sdcontacts = { "unused", "power" } 14 | end 15 | local leftpolylines = {} 16 | local rightpolylines = {} 17 | for i = 1, _P.fingers do 18 | local entry = { length = _P.gatelength, space = _P.gatespace } 19 | if _P.leftnotright then 20 | leftpolylines[i] = entry 21 | else 22 | rightpolylines[i] = entry 23 | end 24 | end 25 | local baseparameters = {} 26 | for name, value in pairs(_P) do 27 | if pcell.has_parameter("stdcells/harness", name) then 28 | baseparameters[name] = value 29 | end 30 | end 31 | local harness = pcell.create_layout("stdcells/harness", "harness", util.add_options(baseparameters, { 32 | gatecontactpos = gatecontactpos, 33 | pcontactpos = sdcontacts, 34 | ncontactpos = sdcontacts, 35 | drawactive = false, 36 | drawgatecontacts = false, 37 | drawtopgcut = false, 38 | drawbotgcut = false, 39 | drawleftstopgate = _P.leftnotright, 40 | leftpolylines = leftpolylines, 41 | drawrightstopgate = not _P.leftnotright, 42 | rightpolylines = rightpolylines, 43 | })) 44 | gate:merge_into(harness) 45 | gate:inherit_alignment_box(harness) 46 | end 47 | -------------------------------------------------------------------------------- /cells/stdcells/dffnq.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.inherit_parameters("stdcells/dff", { 3 | "clockpolarity", 4 | "enable_Q", 5 | "enable_QN", 6 | "enable_set", 7 | "enable_reset", 8 | }) 9 | end 10 | 11 | function layout(gate, _P) 12 | local baseparameters = {} 13 | for name, value in pairs(_P) do 14 | if pcell.has_parameter("stdcells/dff", name) then 15 | baseparameters[name] = value 16 | end 17 | end 18 | local dff = pcell.create_layout("stdcells/dff", "dffnq", util.add_options(baseparameters, { 19 | clockpolarity = "negative", 20 | enable_Q = true, 21 | enable_QN = false, 22 | enable_set = false, 23 | enable_reset = false, 24 | })) 25 | gate:exchange(dff) 26 | end 27 | -------------------------------------------------------------------------------- /cells/stdcells/dffnrq.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.inherit_parameters("stdcells/dff", { 3 | "clockpolarity", 4 | "enable_Q", 5 | "enable_QN", 6 | "enable_set", 7 | "enable_reset", 8 | }) 9 | end 10 | 11 | function layout(gate, _P) 12 | local baseparameters = {} 13 | for name, value in pairs(_P) do 14 | if pcell.has_parameter("stdcells/harness", name) then 15 | baseparameters[name] = value 16 | end 17 | end 18 | local dff = pcell.create_layout("stdcells/dff", "dffnrq", util.add_options(baseparameters, { 19 | clockpolarity = "negative", 20 | enable_Q = true, 21 | enable_QN = false, 22 | enable_set = false, 23 | enable_reset = true, 24 | })) 25 | gate:exchange(dff) 26 | end 27 | -------------------------------------------------------------------------------- /cells/stdcells/dffnrsq.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.inherit_parameters("stdcells/dff", { 3 | "clockpolarity", 4 | "enable_Q", 5 | "enable_QN", 6 | "enable_set", 7 | "enable_reset", 8 | }) 9 | end 10 | 11 | function layout(gate, _P) 12 | local baseparameters = {} 13 | for name, value in pairs(_P) do 14 | if pcell.has_parameter("stdcells/harness", name) then 15 | baseparameters[name] = value 16 | end 17 | end 18 | local dff = pcell.create_layout("stdcells/dff", "dffnrsq", util.add_options(baseparameters, { 19 | clockpolarity = "negative", 20 | enable_Q = true, 21 | enable_QN = false, 22 | enable_set = true, 23 | enable_reset = true, 24 | })) 25 | gate:exchange(dff) 26 | end 27 | -------------------------------------------------------------------------------- /cells/stdcells/dffnsq.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.inherit_parameters("stdcells/dff", { 3 | "clockpolarity", 4 | "enable_Q", 5 | "enable_QN", 6 | "enable_set", 7 | "enable_reset", 8 | }) 9 | end 10 | 11 | function layout(gate, _P) 12 | local baseparameters = {} 13 | for name, value in pairs(_P) do 14 | if pcell.has_parameter("stdcells/dff", name) then 15 | baseparameters[name] = value 16 | end 17 | end 18 | local dff = pcell.create_layout("stdcells/dff", "dffnsq", util.add_options(baseparameters, { 19 | clockpolarity = "negative", 20 | enable_Q = true, 21 | enable_QN = false, 22 | enable_set = true, 23 | enable_reset = false, 24 | })) 25 | gate:exchange(dff) 26 | end 27 | -------------------------------------------------------------------------------- /cells/stdcells/dffpq.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.inherit_parameters("stdcells/dff", { 3 | "clockpolarity", 4 | "enable_Q", 5 | "enable_QN", 6 | "enable_set", 7 | "enable_reset", 8 | }) 9 | end 10 | 11 | function layout(gate, _P) 12 | local baseparameters = {} 13 | for name, value in pairs(_P) do 14 | if pcell.has_parameter("stdcells/harness", name) then 15 | baseparameters[name] = value 16 | end 17 | end 18 | local dff = pcell.create_layout("stdcells/dff", "dffpq", util.add_options(baseparameters, { 19 | clockpolarity = "positive", 20 | enable_Q = true, 21 | enable_QN = false, 22 | enable_set = false, 23 | enable_reset = false, 24 | })) 25 | gate:exchange(dff) 26 | end 27 | -------------------------------------------------------------------------------- /cells/stdcells/dffprq.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.inherit_parameters("stdcells/dff", { 3 | "clockpolarity", 4 | "enable_Q", 5 | "enable_QN", 6 | "enable_set", 7 | "enable_reset", 8 | }) 9 | end 10 | 11 | function layout(gate, _P) 12 | local baseparameters = {} 13 | for name, value in pairs(_P) do 14 | if pcell.has_parameter("stdcells/dff", name) then 15 | baseparameters[name] = value 16 | end 17 | end 18 | local dff = pcell.create_layout("stdcells/dff", "dffprq", util.add_options(baseparameters, { 19 | clockpolarity = "positive", 20 | enable_Q = true, 21 | enable_QN = false, 22 | enable_set = false, 23 | enable_reset = true, 24 | })) 25 | gate:exchange(dff) 26 | end 27 | -------------------------------------------------------------------------------- /cells/stdcells/dffprsq.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.inherit_parameters("stdcells/dff", { 3 | "clockpolarity", 4 | "enable_Q", 5 | "enable_QN", 6 | "enable_set", 7 | "enable_reset", 8 | }) 9 | end 10 | 11 | function layout(gate, _P) 12 | local baseparameters = {} 13 | for name, value in pairs(_P) do 14 | if pcell.has_parameter("stdcells/dff", name) then 15 | baseparameters[name] = value 16 | end 17 | end 18 | local dff = pcell.create_layout("stdcells/dff", "dfprsq", util.add_options(baseparameters, { 19 | clockpolarity = "positive", 20 | enable_Q = true, 21 | enable_QN = false, 22 | enable_set = true, 23 | enable_reset = true, 24 | })) 25 | gate:exchange(dff) 26 | end 27 | -------------------------------------------------------------------------------- /cells/stdcells/dffpsq.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.inherit_parameters("stdcells/dff", { 3 | "clockpolarity", 4 | "enable_Q", 5 | "enable_QN", 6 | "enable_set", 7 | "enable_reset", 8 | }) 9 | end 10 | 11 | function layout(gate, _P) 12 | local baseparameters = {} 13 | for name, value in pairs(_P) do 14 | if pcell.has_parameter("stdcells/dff", name) then 15 | baseparameters[name] = value 16 | end 17 | end 18 | local dff = pcell.create_layout("stdcells/dff", "dffpsq", util.add_options(baseparameters, { 19 | clockpolarity = "positive", 20 | enable_Q = true, 21 | enable_QN = false, 22 | enable_set = true, 23 | enable_reset = false, 24 | })) 25 | gate:exchange(dff) 26 | end 27 | -------------------------------------------------------------------------------- /cells/stdcells/endcell.lua: -------------------------------------------------------------------------------- 1 | function layout(cell, _P) 2 | local bp = pcell.get_parameters("stdcells/base") 3 | local xpitch = bp.gatespace + bp.gatelength 4 | local separation = bp.numinnerroutes * bp.routingwidth + (bp.numinnerroutes + 1) * bp.routingspace 5 | 6 | --geometry.rectangle(cell, generics.other("gate"), bp.gatelength, separation + bp.pwidth + bp.nwidth, 0, 0, 5, 1, xpitch, 0) 7 | end 8 | -------------------------------------------------------------------------------- /cells/stdcells/fill.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameters( 3 | { "fingers", 1 } 4 | ) 5 | pcell.inherit_parameters("stdcells/base") 6 | end 7 | 8 | function layout(gate, _P) 9 | local xpitch = _P.gatespace + _P.gatelength 10 | 11 | local gatecontactpos = {} 12 | for i = 1, _P.fingers do 13 | gatecontactpos[i] = "dummy" 14 | end 15 | 16 | local contactpos = {} 17 | for i = 1, _P.fingers + 1 do 18 | contactpos[i] = "unused" 19 | end 20 | local baseparameters = {} 21 | for name, value in pairs(_P) do 22 | if pcell.has_parameter("stdcells/harness", name) then 23 | baseparameters[name] = value 24 | end 25 | end 26 | local harness = pcell.create_layout("stdcells/harness", "mosfets", util.add_options(baseparameters, { 27 | gatecontactpos = gatecontactpos, 28 | pcontactpos = contactpos, 29 | ncontactpos = contactpos, 30 | })) 31 | gate:merge_into(harness) 32 | gate:inherit_alignment_box(harness) 33 | end 34 | -------------------------------------------------------------------------------- /cells/stdcells/half_adder.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | CO = A & B 3 | S = A XOR B 4 | --]] 5 | function layout(gate, _P) 6 | local bp = pcell.get_parameters("stdcells/base"); 7 | 8 | local andgate = pcell.create_layout("stdcells/and_gate", "and_gate") 9 | gate:merge_into(andgate) 10 | gate:inherit_alignment_box(andgate) 11 | 12 | local isogate = pcell.create_layout("stdcells/isogate", "isogate") 13 | isogate:abut_right(andgate) 14 | gate:merge_into(isogate:copy()) 15 | 16 | local xorgate = pcell.create_layout("stdcells/xor_gate", "xorgate") 17 | xorgate:abut_right(isogate) 18 | gate:merge_into(xorgate) 19 | gate:inherit_alignment_box(xorgate) 20 | 21 | geometry.path(gate, generics.metal(2), 22 | geometry.path_points_xy(andgate:get_anchor("A"), { 23 | xorgate:get_anchor("A") 24 | }), bp.sdwidth) 25 | geometry.viabltr(gate, 1, 2, 26 | andgate:get_anchor("A"):translate(-bp.sdwidth / 2, -bp.sdwidth / 2), 27 | andgate:get_anchor("A"):translate( bp.sdwidth / 2, bp.sdwidth / 2) 28 | ) 29 | 30 | geometry.path(gate, generics.metal(2), { 31 | andgate:get_anchor("B"), xorgate:get_anchor("B") 32 | }, bp.sdwidth) 33 | geometry.viabltr(gate, 1, 2, 34 | andgate:get_anchor("B"):translate(-bp.sdwidth / 2, -bp.sdwidth / 2), 35 | andgate:get_anchor("B"):translate( bp.sdwidth / 2, bp.sdwidth / 2) 36 | ) 37 | 38 | gate:add_port_with_anchor("A", generics.metalport(1), andgate:get_anchor("A")) 39 | gate:add_port_with_anchor("B", generics.metalport(1), andgate:get_anchor("B")) 40 | gate:add_port_with_anchor("COUT", generics.metalport(1), andgate:get_anchor("O")) 41 | gate:add_port("S", generics.metalport(1), xorgate:get_anchor("O")) 42 | end 43 | -------------------------------------------------------------------------------- /cells/stdcells/isogate.lua: -------------------------------------------------------------------------------- 1 | function config() 2 | pcell.set_property("hidden", true) 3 | end 4 | 5 | function parameters() 6 | pcell.inherit_parameters("stdcells/base") 7 | end 8 | 9 | function layout(gate, _P) 10 | local xpitch = _P.gatespace + _P.gatelength 11 | 12 | local baseparameters = {} 13 | for k, v in pairs(_P) do 14 | if pcell.has_parameter("stdcells/harness", k) then 15 | baseparameters[k] = v 16 | end 17 | end 18 | local harness = pcell.create_layout("stdcells/harness", "mosfets", util.add_options(baseparameters, { 19 | gatecontactpos = { "dummy" }, 20 | pcontactpos = { "power", "power" }, 21 | ncontactpos = { "power", "power" }, 22 | pwidthoffset = _P.pwidthoffset, 23 | nwidthoffset = _P.nwidthoffset, 24 | drawdummyactivecontacts = false, 25 | })) 26 | gate:merge_into(harness) 27 | 28 | gate:inherit_alignment_box(harness) 29 | 30 | gate:add_port("VDD", generics.metalport(1), harness:get_area_anchor("PRp").bl) 31 | gate:add_port("VSS", generics.metalport(1), harness:get_area_anchor("PRn").bl) 32 | 33 | -- center gate 34 | gate:translate(xpitch / 2, 0) 35 | end 36 | -------------------------------------------------------------------------------- /cells/stdcells/leftcolstop.lua: -------------------------------------------------------------------------------- 1 | function layout(colstop) 2 | local cell = pcell.create_layout("stdcells/colstop", "leftcolstop", { fingers = 1 }) 3 | colstop:exchange(cell) 4 | end 5 | -------------------------------------------------------------------------------- /cells/stdcells/mux.lua: -------------------------------------------------------------------------------- 1 | function layout(gate, _P) 2 | local bp = pcell.get_parameters("stdcells/base") 3 | local xpitch = bp.gatespace + bp.gatelength 4 | 5 | local gatecontactpos = { 6 | "upper", "lower", "center" 7 | } 8 | 9 | local contactpos = { "power", "inner", "inner", "power" } 10 | local harness = pcell.create_layout("stdcells/harness", "harness", { 11 | gatecontactpos = gatecontactpos, 12 | pcontactpos = contactpos, 13 | ncontactpos = contactpos, 14 | }) 15 | gate:merge_into(harness) 16 | gate:inherit_alignment_box(harness) 17 | 18 | -- ports 19 | gate:add_port_with_anchor("A", generics.metalport(1), harness:get_area_anchor("G1").bl) 20 | gate:add_port_with_anchor("B", generics.metalport(1), harness:get_area_anchor("G1").bl) 21 | gate:add_port_with_anchor("O", generics.metalport(1), point.create((3 + 1) * xpitch / 2, 0)) 22 | gate:add_port("VDD", generics.metalport(1), harness:get_area_anchor("PRp").bl) 23 | gate:add_port("VSS", generics.metalport(1), harness:get_area_anchor("PRn").bl) 24 | end 25 | -------------------------------------------------------------------------------- /cells/stdcells/nand_gate.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameter("fingers", 1) 3 | pcell.add_parameter("shiftoutput", 0) 4 | pcell.inherit_parameters("stdcells/base") 5 | end 6 | 7 | function layout(gate, _P) 8 | local baseparameters = {} 9 | for k, v in pairs(_P) do 10 | if pcell.has_parameter("stdcells/nand_nor_layout_base", k) then 11 | baseparameters[k] = v 12 | end 13 | end 14 | local base = pcell.create_layout("stdcells/nand_nor_layout_base", "nand_gate", util.add_options(baseparameters, { 15 | fingers = _P.fingers, 16 | gatetype = "nand", 17 | shiftoutput = _P.shiftoutput 18 | })) 19 | gate:exchange(base) 20 | end 21 | -------------------------------------------------------------------------------- /cells/stdcells/nor_gate.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameter("fingers", 1) 3 | pcell.add_parameter("shiftoutput", 0) 4 | pcell.inherit_parameters("stdcells/base") 5 | end 6 | 7 | function layout(gate, _P) 8 | local baseparameters = {} 9 | for k, v in pairs(_P) do 10 | if pcell.has_parameter("stdcells/nand_nor_layout_base", k) then 11 | baseparameters[k] = v 12 | end 13 | end 14 | local base = pcell.create_layout("stdcells/nand_nor_layout_base", "nand_gate", util.add_options(baseparameters, { 15 | fingers = _P.fingers, 16 | gatetype = "nor", 17 | shiftoutput = _P.shiftoutput 18 | })) 19 | gate:exchange(base) 20 | end 21 | -------------------------------------------------------------------------------- /cells/stdcells/or_gate.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameters( 3 | { "norfingers", 1 }, 4 | { "notfingers", 1 } 5 | ) 6 | pcell.inherit_parameters("stdcells/base") 7 | end 8 | 9 | function layout(gate, _P) 10 | local baseparameters = {} 11 | for k, v in pairs(_P) do 12 | if pcell.has_parameter("stdcells/1_inv_gate", k) then 13 | baseparameters[k] = v 14 | end 15 | end 16 | local subgate = pcell.create_layout("stdcells/1_inv_gate", "and_gate", util.add_options(baseparameters, { 17 | subgate = "nor_gate", 18 | subgatefingers = _P.norfingers, 19 | notfingers = _P.notfingers, 20 | })) 21 | gate:exchange(subgate) 22 | end 23 | -------------------------------------------------------------------------------- /cells/stdcells/rightcolstop.lua: -------------------------------------------------------------------------------- 1 | function layout(colstop) 2 | local cell = pcell.create_layout("stdcells/colstop", "rightcolstop", { leftnotright = false, fingers = 1 }) 3 | colstop:exchange(cell) 4 | end 5 | -------------------------------------------------------------------------------- /cells/stdcells/tbuf.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameters( 3 | { "ifingers", 1 }, 4 | { "ofingers", 1 } 5 | ) 6 | pcell.inherit_parameters("stdcells/base") 7 | end 8 | 9 | function layout(gate, _P) 10 | -- inverter 11 | local inv = pcell.create_layout("stdcells/not_gate", "inv", { inputpos = "lower1", fingers = _P.ifingers }) 12 | gate:merge_into(inv) 13 | 14 | local isogate = pcell.create_layout("stdcells/isogate", "isogate") 15 | isogate:abut_right(inv) 16 | gate:merge_into(isogate) 17 | 18 | -- clocked inverter 19 | local cinv = pcell.create_layout("stdcells/cinv", "cinv", { fingers = _P.ofingers }) 20 | cinv:abut_right(isogate) 21 | gate:merge_into(cinv) 22 | 23 | -- connections 24 | geometry.path(gate, generics.metal(1), 25 | geometry.path_points_yx(inv:get_anchor("O"), { 26 | cinv:get_anchor("EP") 27 | }), _P.routingwidth) 28 | geometry.path(gate, generics.metal(2), { inv:get_anchor("I"), cinv:get_anchor("EN") }, _P.routingwidth) 29 | geometry.viabltr(gate, 1, 2, 30 | inv:get_anchor("I"):translate(-_P.gatelength / 2, -_P.routingwidth / 2), 31 | inv:get_anchor("I"):translate( _P.gatelength / 2, _P.routingwidth / 2) 32 | ) 33 | geometry.viabltr(gate, 1, 2, 34 | cinv:get_anchor("EN"):translate(-_P.gatelength / 2, -_P.routingwidth / 2), 35 | cinv:get_anchor("EN"):translate( _P.gatelength / 2, _P.routingwidth / 2) 36 | ) 37 | 38 | geometry.path(gate, generics.metal(2), { cinv:get_anchor("I"), point.combine_12(inv:get_anchor("I"), cinv:get_anchor("I")) }, _P.routingwidth) 39 | geometry.viabltr(gate, 1, 2, 40 | point.combine_12(inv:get_anchor("I"), cinv:get_anchor("I")):translate(-_P.gatelength / 2, -_P.routingwidth / 2), 41 | point.combine_12(inv:get_anchor("I"), cinv:get_anchor("I")):translate( _P.gatelength / 2, _P.routingwidth / 2) 42 | ) 43 | geometry.viabltr(gate, 1, 2, 44 | cinv:get_anchor("I"):translate(-_P.gatelength / 2, -_P.routingwidth / 2), 45 | cinv:get_anchor("I"):translate( _P.gatelength / 2, _P.routingwidth / 2) 46 | ) 47 | 48 | -- ports 49 | gate:add_port_with_anchor("EN", generics.metalport(1), inv:get_anchor("I")) 50 | gate:add_port_with_anchor("I", generics.metalport(1), cinv:get_anchor("I")) 51 | gate:add_port_with_anchor("O", generics.metalport(1), cinv:get_anchor("O")) 52 | gate:add_port("VDD", generics.metalport(1), isogate:get_anchor("VDD")) 53 | gate:add_port("VSS", generics.metalport(1), isogate:get_anchor("VSS")) 54 | end 55 | -------------------------------------------------------------------------------- /cells/stdcells/tie_high.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameters( 3 | { "fingers", 2, posvals = even() } 4 | ) 5 | pcell.inherit_parameters("stdcells/base") 6 | end 7 | 8 | function layout(cell, _P) 9 | local baseparameters = {} 10 | for name, value in pairs(_P) do 11 | if pcell.has_parameter("stdcells/tie_highlow", name) then 12 | baseparameters[name] = value 13 | end 14 | end 15 | local base = pcell.create_layout("stdcells/tie_highlow", "tie_high", util.add_options(baseparameters, { 16 | high = true, 17 | fingers = _P.fingers 18 | })) 19 | cell:exchange(base) 20 | end 21 | -------------------------------------------------------------------------------- /cells/stdcells/tie_low.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameters( 3 | { "fingers", 2, posvals = even() } 4 | ) 5 | pcell.inherit_parameters("stdcells/base") 6 | end 7 | 8 | function layout(cell, _P) 9 | local baseparameters = {} 10 | for name, value in pairs(_P) do 11 | if pcell.has_parameter("stdcells/tie_highlow", name) then 12 | baseparameters[name] = value 13 | end 14 | end 15 | local base = pcell.create_layout("stdcells/tie_highlow", "tie_low", util.add_options(baseparameters, { 16 | high = false, 17 | fingers = _P.fingers 18 | })) 19 | cell:exchange(base) 20 | end 21 | -------------------------------------------------------------------------------- /cells/transmitter/memory.lua: -------------------------------------------------------------------------------- 1 | function parameters() 2 | pcell.add_parameters( 3 | { "numlanes", 64 }, 4 | { "bitsperlane", 32 }, 5 | { "bitresolution", 8 } 6 | ) 7 | end 8 | 9 | function layout(memory, _P) 10 | local dffpref = pcell.create_layout("stdcells/dff", "dffp", { clockpolarity = "positive" }) 11 | local dffnref = pcell.create_layout("stdcells/dff", "dffn", { clockpolarity = "negative" }) 12 | local laneref = object.create("lane") 13 | local dffs = {} 14 | for j = 1, _P.bitresolution do 15 | for k = 1, _P.bitsperlane do 16 | local dff = laneref:add_child((k % 2 == 1) and dffpref or dffnref, string.format("dff_%d_%d", j, k)) 17 | if k > 1 then 18 | dff:move_anchor("left", dffs[(j - 1) * _P.bitsperlane + k - 1]:get_anchor("right")) 19 | elseif j > 1 then 20 | dff:move_anchor("bottom", dffs[(j - 2) * _P.bitsperlane + 1]:get_anchor("top")) 21 | end 22 | if j % 2 == 0 then 23 | dff:flipy() 24 | end 25 | dffs[(j - 1) * _P.bitsperlane + k] = dff 26 | -- connection to next dff 27 | if k > 1 then 28 | geometry.path(laneref, generics.metal(1), 29 | geometry.path_points_yx(dffs[(j - 1) * _P.bitsperlane + k - 1]:get_anchor("Q"), { 30 | dffs[(j - 1) * _P.bitsperlane + k]:get_anchor("D") 31 | }), 40 32 | ) 33 | end 34 | end 35 | if _P.bitsperlane > 1 then 36 | geometry.path(laneref, generics.metal(3), { 37 | dffs[(j - 1) * _P.bitsperlane + 1]:get_anchor("CLK"), 38 | dffs[(j - 1) * _P.bitsperlane + _P.bitsperlane]:get_anchor("CLK") 39 | }, 40) 40 | end 41 | laneref:add_anchor("D", dffs[(j - 1) * _P.bitsperlane + 1]:get_anchor("D")) 42 | end 43 | laneref:set_alignment_box( 44 | dffs[1]:get_anchor("bottomleft"), 45 | dffs[_P.bitresolution * _P.bitsperlane]:get_anchor("topright") 46 | ) 47 | 48 | local lanes = {} 49 | for i = 1, _P.numlanes do 50 | lanes[i] = memory:add_child(laneref, string.format("lane_%d", i)) 51 | if i % 2 == 0 then 52 | lanes[i]:flipy() 53 | end 54 | if i > 1 then 55 | lanes[i]:move_anchor("bottom", lanes[i - 1]:get_anchor("top")) 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | cells := ../cells/passive/capacitor/mom.lua ../cells/passive/inductor/octagonal.lua 2 | documents := presentation.pdf userguide.pdf techdoc.pdf techfiles.pdf celldesign.pdf export.pdf 3 | 4 | .PHONY: all 5 | all: ${documents} 6 | 7 | .PHONY: full 8 | full: 9 | @$(MAKE) all 10 | rm ${documents} 11 | @$(MAKE) all 12 | rm ${documents} 13 | @$(MAKE) all 14 | 15 | presentation.pdf: src/presentation/main.tex src/presentation/preamble.tex 16 | $(MAKE) -C src/presentation main.pdf 17 | mv src/presentation/main.pdf presentation.pdf 18 | 19 | userguide.pdf: src/userguide/main.tex src/preamble.tex 20 | $(MAKE) -C src/userguide main.pdf 21 | mv src/userguide/main.pdf userguide.pdf 22 | 23 | techdoc.pdf: src/techdoc/main.tex src/preamble.tex 24 | $(MAKE) -C src/techdoc main.pdf 25 | mv src/techdoc/main.pdf techdoc.pdf 26 | 27 | celldesign.pdf: src/celldesign/main.tex src/preamble.tex ${cells} src/celldesign/code/* 28 | $(MAKE) -C src/celldesign main.pdf 29 | mv src/celldesign/main.pdf celldesign.pdf 30 | 31 | techfiles.pdf: src/techfiles/main.tex src/preamble.tex 32 | $(MAKE) -C src/techfiles main.pdf 33 | mv src/techfiles/main.pdf techfiles.pdf 34 | 35 | export.pdf: src/export/main.tex src/preamble.tex 36 | $(MAKE) -C src/export main.pdf 37 | mv src/export/main.pdf export.pdf 38 | 39 | # in src directories 40 | main.pdf: 41 | lualatex -shell-escape main.tex 42 | 43 | .PHONY: clean 44 | clean: 45 | $(MAKE) -C src/presentation clean 46 | $(MAKE) -C src/userguide clean 47 | $(MAKE) -C src/techdoc clean 48 | $(MAKE) -C src/celldesign clean 49 | $(MAKE) -C src/techfiles clean 50 | -------------------------------------------------------------------------------- /doc/celldesign.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patrickschulz/openPCells/14f34e0a04d0e87ac7ac1027ab7522b20e90d074/doc/celldesign.pdf -------------------------------------------------------------------------------- /doc/export.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patrickschulz/openPCells/14f34e0a04d0e87ac7ac1027ab7522b20e90d074/doc/export.pdf -------------------------------------------------------------------------------- /doc/info/mosfet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patrickschulz/openPCells/14f34e0a04d0e87ac7ac1027ab7522b20e90d074/doc/info/mosfet.png -------------------------------------------------------------------------------- /doc/info/mosfet_complex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patrickschulz/openPCells/14f34e0a04d0e87ac7ac1027ab7522b20e90d074/doc/info/mosfet_complex.png -------------------------------------------------------------------------------- /doc/info/ringoscillator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patrickschulz/openPCells/14f34e0a04d0e87ac7ac1027ab7522b20e90d074/doc/info/ringoscillator.png -------------------------------------------------------------------------------- /doc/presentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patrickschulz/openPCells/14f34e0a04d0e87ac7ac1027ab7522b20e90d074/doc/presentation.pdf -------------------------------------------------------------------------------- /doc/src/Makefile: -------------------------------------------------------------------------------- 1 | main.pdf: main.tex 2 | lualatex -shell-escape main.tex 3 | 4 | .PHONY: clean 5 | clean: 6 | latexmk -C 7 | -------------------------------------------------------------------------------- /doc/src/celldesign/Makefile: -------------------------------------------------------------------------------- 1 | ../Makefile -------------------------------------------------------------------------------- /doc/src/celldesign/code/hierarchy_example.lua: -------------------------------------------------------------------------------- 1 | local toplevel = object.create("toplevel") 2 | local sub = object.create("sub") 3 | local subsub = object.create("subsub") 4 | sub:add_child(subsub, "subsub1") 5 | sub:add_child(subsub, "subsub2") 6 | toplevel:add_child(sub, "sub") 7 | -------------------------------------------------------------------------------- /doc/src/celldesign/code/merge_into_example.lua: -------------------------------------------------------------------------------- 1 | function layout(toplevel) 2 | local cell = -- get the layout from somewhere 3 | toplevel:merge_into(cell) 4 | toplevel:merge_into(cell:flatten()) 5 | toplevel:merge_into(cell:copy():flatten()) 6 | end 7 | -------------------------------------------------------------------------------- /doc/src/celldesign/code/ringoscillator.lua: -------------------------------------------------------------------------------- 1 | function layout(toplevel) 2 | local inverter = -- create inverter layout 3 | -- copy inverter and translate it 4 | local width = 1000 -- the width needs to be known 5 | local inverter1 = inverter:copy():translate(0 * width, 0) 6 | local inverter2 = inverter:copy():translate(1 * width, 0) 7 | local inverter3 = inverter:copy():translate(2 * width, 0) 8 | -- merge into toplevel 9 | toplevel:merge_into(inverter1) 10 | toplevel:merge_into(inverter2) 11 | toplevel:merge_into(inverter3) 12 | end 13 | -------------------------------------------------------------------------------- /doc/src/celldesign/code/ringoscillator_anchor.lua: -------------------------------------------------------------------------------- 1 | function layout(toplevel) 2 | local inverter = -- create inverter layout 3 | -- copy inverters 4 | local inverter1 = inverter:copy() 5 | local inverter2 = inverter:copy() 6 | local inverter3 = inverter:copy() 7 | 8 | -- get required displacement for inverter2 9 | local output1 = inverter1:get_anchor("output") 10 | local input2 = inverter2:get_anchor("input") 11 | -- translate inverter2 12 | local inverter2 = inverter2:translate(output1 - input2) 13 | 14 | -- get required displacement for inverter3 15 | local output2 = inverter2:get_anchor("output") 16 | local input3 = inverter3:get_anchor("input") 17 | -- translate inverter3 18 | local inverter3 = inverter3:translate(output2 - input3) 19 | 20 | -- merge inverters into toplevel 21 | toplevel:merge_into(inverter1) 22 | toplevel:merge_into(inverter2) 23 | toplevel:merge_into(inverter3) 24 | end 25 | -------------------------------------------------------------------------------- /doc/src/celldesign/code/ringoscillator_move_point.lua: -------------------------------------------------------------------------------- 1 | function layout(toplevel) 2 | local inverter = -- create inverter layout 3 | -- copy inverter and move it to the origin 4 | local inverter1 = inverter:copy() 5 | inverter1:move_point( 6 | inverter1:get_anchor("input"), 7 | point.create(0, 0) 8 | ) 9 | -- copy and translate inverter2 10 | local inverter2 = inverter:copy() 11 | inverter2:move_point( 12 | inverter2:get_anchor("input"), 13 | inverter1:get_anchor("output") 14 | ) 15 | -- copy and translate inverter3 16 | local inverter3 = inverter:copy() 17 | inverter3:move_point( 18 | inverter3:get_anchor("input"), 19 | inverter2:get_anchor("output") 20 | ) 21 | -- merge inverters into toplevel 22 | toplevel:merge_into(inverter1) 23 | toplevel:merge_into(inverter2) 24 | toplevel:merge_into(inverter3) 25 | end 26 | -------------------------------------------------------------------------------- /doc/src/celldesign/code/ringoscillator_nocopy.lua: -------------------------------------------------------------------------------- 1 | function layout(toplevel) 2 | local inverter = -- create inverter layout 3 | local width = 1000 -- the width needs to be known 4 | -- translate and merge into toplevel 5 | toplevel:merge_into(inverter) 6 | toplevel:merge_into(inverter:translate(width, 0)) 7 | toplevel:merge_into(inverter:translate(width, 0)) 8 | end 9 | -------------------------------------------------------------------------------- /doc/src/celldesign/code/simple_rectangle.lua: -------------------------------------------------------------------------------- 1 | -- define parameters 2 | function parameters() 3 | pcell.add_parameters( 4 | { "width", 100 }, 5 | { "height", 100 } 6 | ) 7 | end 8 | 9 | -- define layout 10 | function layout(obj, _P) 11 | -- create the shape and add it to the main object 12 | geometry.rectanglebltr( 13 | obj, 14 | generics.metal(1), 15 | point.create(0, 0), 16 | point.create(_P.width, _P.height) 17 | ) 18 | end 19 | -------------------------------------------------------------------------------- /doc/src/export/Makefile: -------------------------------------------------------------------------------- 1 | main.pdf: main.tex 2 | lualatex -shell-escape main.tex 3 | 4 | .PHONY: clean 5 | clean: 6 | latexmk -C 7 | -------------------------------------------------------------------------------- /doc/src/presentation/Makefile: -------------------------------------------------------------------------------- 1 | ../Makefile -------------------------------------------------------------------------------- /doc/src/presentation/main.auxlock: -------------------------------------------------------------------------------- 1 | \def \tikzexternallocked {0} 2 | -------------------------------------------------------------------------------- /doc/src/presentation/main.snm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patrickschulz/openPCells/14f34e0a04d0e87ac7ac1027ab7522b20e90d074/doc/src/presentation/main.snm -------------------------------------------------------------------------------- /doc/src/techdoc/Makefile: -------------------------------------------------------------------------------- 1 | ../Makefile -------------------------------------------------------------------------------- /doc/src/techfiles/Makefile: -------------------------------------------------------------------------------- 1 | ../Makefile -------------------------------------------------------------------------------- /doc/src/userguide/Makefile: -------------------------------------------------------------------------------- 1 | ../Makefile -------------------------------------------------------------------------------- /doc/techdoc.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patrickschulz/openPCells/14f34e0a04d0e87ac7ac1027ab7522b20e90d074/doc/techdoc.pdf -------------------------------------------------------------------------------- /doc/techfiles.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patrickschulz/openPCells/14f34e0a04d0e87ac7ac1027ab7522b20e90d074/doc/techfiles.pdf -------------------------------------------------------------------------------- /doc/userguide.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patrickschulz/openPCells/14f34e0a04d0e87ac7ac1027ab7522b20e90d074/doc/userguide.pdf -------------------------------------------------------------------------------- /examples/autofill/main.lua: -------------------------------------------------------------------------------- 1 | local cell = object.create("toplevel") 2 | 3 | -- create a few shapes to show the autofill 4 | geometry.path_polygon(cell, generics.metal(1), { 5 | point.create(2500, 0), 6 | point.create(2500, 2000), 7 | point.create(4500, 2000), 8 | point.create(4500, 4000), 9 | point.create(2500, 6000), 10 | point.create(2000, 6000), 11 | point.create(2000, 3000), 12 | point.create(1000, 3000), 13 | }, 200) 14 | geometry.rectanglebltr(cell, generics.metal(1), 15 | point.create(500, 500), 16 | point.create(1500, 1500) 17 | ) 18 | 19 | -- collect the shape outlines from the cell 20 | local excludes = cell:get_shape_outlines(generics.metal(1)) 21 | -- add an offset (spacing) 22 | local exclude_offset = 200 23 | for i = 1, #excludes do 24 | local exclude = excludes[i] 25 | local new = util.offset_polygon(exclude, exclude_offset) 26 | excludes[i] = new 27 | end 28 | 29 | -- show the excludes in the layout 30 | for i = 1, #excludes do 31 | geometry.polygon(cell, generics.special(), excludes[i]) 32 | end 33 | 34 | -- create the rectangular fill on M1 with excludes 35 | geometry.rectangle_fill_in_boundary(cell, generics.metal(1), 36 | 100, 100, -- width/height 37 | 200, 200, -- xpitch/ypitch 38 | 0, 0, -- start offsets (x/y) 39 | util.rectangle_to_polygon(point.create(0, 0), point.create(7000, 7000)), -- target area 40 | excludes -- table with exclusion polygons 41 | ) 42 | -- rectangular fill on M2 without excludes, uses a different start offset 43 | geometry.rectangle_fill_in_boundary(cell, generics.metal(2), 44 | 100, 100, -- width/height 45 | 200, 200, -- xpitch/ypitch 46 | 100, 100, -- start offsets (x/y) 47 | util.rectangle_to_polygon(point.create(0, 0), point.create(7000, 7000)) 48 | ) 49 | 50 | return cell 51 | -------------------------------------------------------------------------------- /examples/autofill/run.sh: -------------------------------------------------------------------------------- 1 | ../../opc --export gds --technology opc --cellscript main.lua 2 | -------------------------------------------------------------------------------- /examples/cells/LC_oscillator.lua: -------------------------------------------------------------------------------- 1 | return pcell.create_layout("LC_oscillator/toplevel", "oscillator", { 2 | resonator_inductor_turns = 2, 3 | resonator_inductor_metal = -2, 4 | resonator_dlfgroundshield = false, 5 | resonator_fillmetals = util.range(1, 7), 6 | disable_all_fill = true, 7 | ccp_fingersperside = 16, 8 | ccp_pmosfingerwidth = 1000, 9 | ccp_nmosfingerwidth = 624, 10 | ccp_middledummyfingers = 2, 11 | ccp_outerdummyfingers = 4, 12 | ccp_gatelength = 250, 13 | ccp_gatespace = 280, 14 | ccp_oxidetype = 1, 15 | ccp_mosfetmarker = 1, 16 | ccp_pvthtype = 1, 17 | ccp_nvthtype = 1, 18 | ccp_activedummywidth = 80, 19 | ccp_activedummyspace = 240, 20 | ccp_outputoffset = 200, 21 | ccp_gatestrapwidth = 250, 22 | ccp_gatestrapspace = 54, 23 | ccp_drainstrapspace = 400, 24 | ccp_powerwidth = 200, 25 | ccp_powerspace = 80, 26 | ccp_gateext = 10, 27 | ccp_sdwidth = 150, 28 | ccp_crossingoffset = 100, 29 | ccp_drawpsubguardring = true, 30 | ccp_inlinedrainstrap = false, 31 | ccp_topviawidth = 500, 32 | ccp_crossingmetal = 5, 33 | ccp_drainmetal = 7, 34 | ccp_vtailshift = 1000, 35 | ccp_vtailwidth = 1000, 36 | ccp_vtailmetal = 5, 37 | ccp_vtaillinewidth = 300, 38 | ccp_vtaillinespace = 300, 39 | ccp_fetpowermetal = 3, 40 | ccp_vssmetal = 5, 41 | ccp_vsslinewidth = 1000, 42 | ccp_vssshift = 1300, 43 | ccp_vsswidth = 1000, 44 | ccp_vsslinewidth = 300, 45 | ccp_vsslinespace = 300, 46 | guardring_width = 200, 47 | guardring_xspace = 200, 48 | guardring_yspace = 200, 49 | guardring_xspacetomosfet = 400, 50 | guardring_yspacetomosfet = 400, 51 | guardring_soiopenextension = 100, 52 | guardring_implantextension = 100, 53 | guardring_wellextension = 100, 54 | }) 55 | -------------------------------------------------------------------------------- /examples/cells/comparator.lua: -------------------------------------------------------------------------------- 1 | -- FIXME: the comparator cell is fairly complicated and not thoroughly checked 2 | -- this layout has some bugs 3 | return pcell.create_layout("analog/strongARM_comparator", "comparator", { 4 | gatelength = 500, 5 | gatespace = 320, 6 | clockfingers = 4, 7 | clockdummyfingers = 1, 8 | clockfingerwidth = 1000, 9 | clockinputgatewidth = 400, 10 | clockinputgatespace = 400, 11 | inputfingers = 4, 12 | inputfingerwidth = 1000, 13 | --inputdummyfingers = 1, 14 | latchfingers = 8, 15 | latchnfingerwidth = 1000, 16 | latchpfingerwidth = 1000, 17 | --latchcrossingoffset = 0, 18 | --latchgatewidth = 0, 19 | --latchgatespace = 0, 20 | --invdummyfingers = 1, 21 | --resetfingers = 2, 22 | --inputclocksdspace = 0, 23 | --invskip = 200, 24 | --resetgatewidth = 0, 25 | --resetgatespace = 0, 26 | --bufferfingers = 2, 27 | buffernfingerwidth = 1000, 28 | bufferpfingerwidth = 1000, 29 | rslatchnfingerwidth = 1000, 30 | rslatchpfingerwidth = 1000, 31 | --gstrwidth = 0, 32 | --sdwidth = 0, 33 | powerwidth = 800, 34 | powerspace = 300, 35 | outerdummyfingers = 4, 36 | --alternativeclockconnection = true, 37 | }) 38 | -------------------------------------------------------------------------------- /examples/cells/current_starved_ringoscillator.lua: -------------------------------------------------------------------------------- 1 | return pcell.create_layout("analog/current_starved_ringoscillator", "oscillator", { 2 | gatelength = 800, 3 | gatespace = 450, 4 | invfingers = 2, 5 | numinv = 5, 6 | pmosdiodefingers = 4, 7 | pmoszerofingers = 9, 8 | pmostunefingers = 2, 9 | pmosseparationfingers = 3, 10 | nmoscurrentfingers = 2, 11 | nmosdiodefingers = 4, 12 | mosdummieseverynth = 2, 13 | pfingerwidth = 2500, 14 | nfingerwidth = 1800, 15 | pfingercontactwidth = 1000, 16 | nfingercontactwidth = 1000, 17 | gstwidth = 400, 18 | gstspace = 600, 19 | powerwidth = 800, 20 | powerspace = 200, 21 | bufspacers = 2, 22 | buffingers = 4, 23 | drawguardrings = true, 24 | guardringwidth = 800, 25 | guardringspace = 800, 26 | }) 27 | -------------------------------------------------------------------------------- /examples/cells/mosfet.lua: -------------------------------------------------------------------------------- 1 | return pcell.create_layout("basic/mosfet", "mosfet", { 2 | channeltype = "pmos", 3 | flippedwell = false, 4 | vthtype = 1, 5 | oxidetype = 1, 6 | gatelength = 500, 7 | gatespace = 320, 8 | fingerwidth = 2000, 9 | fingers = 8, 10 | sdwidth = 200, 11 | drawtopgate = true, 12 | topgatewidth = 200, 13 | topgatespace = 200, 14 | sourcemetal = 1, 15 | connectsource = true, 16 | connectsourcewidth = 300, 17 | connectsourcespace = 200, 18 | drainmetal = 3, 19 | connectdrain = true, 20 | connectdrainwidth = 300, 21 | connectdrainspace = 200, 22 | extendall = 200, 23 | drawguardring = true, 24 | guardringsep = 1000, 25 | guardringfillwell = true, 26 | }) 27 | -------------------------------------------------------------------------------- /examples/cells/ringoscillator.lua: -------------------------------------------------------------------------------- 1 | local toplevel = object.create("toplevel") 2 | 3 | local oscillator1 = pcell.create_layout("analog/ringoscillator", "oscillator1", { 4 | invfingers = 4, 5 | numinv = 5, 6 | invdummies = 1, 7 | gatelength = 500, 8 | gatespace = 320, 9 | pfingerwidth = 2600, 10 | nfingerwidth = 1800, 11 | gatestrapwidth = 200, 12 | gatestrapspace = 200, 13 | sdwidth = 200, 14 | powerwidth = 800, 15 | powerspace = 200, 16 | connectionwidth = 200, 17 | feedbackmetal = 3, 18 | ngateext = 200, 19 | pgateext = 200, 20 | }) 21 | toplevel:add_child(oscillator1, "oscillator1") 22 | 23 | return toplevel 24 | -------------------------------------------------------------------------------- /examples/cells/run.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | ../../opc --technology opc --export gds --cellscript mosfet.lua --filename mosfet 4 | ../../opc --technology opc --export gds --cellscript ringoscillator.lua --filename ringoscillator 5 | ../../opc --technology opc --export gds --cellscript current_starved_ringoscillator.lua --filename current_starved_ringoscillator --enable-dprint 6 | ../../opc --technology opc --export gds --cellscript comparator.lua --filename comparator 7 | ../../opc --technology opc --export gds --cellscript LC_oscillator.lua --filename LC_oscillator --enable-fallback-vias 8 | -------------------------------------------------------------------------------- /examples/digital/run.sh: -------------------------------------------------------------------------------- 1 | lua generate.lua 2 | ../../opc --export gds --technology opc --cellscript digital.lua 3 | -------------------------------------------------------------------------------- /examples/place_and_route_automatic/generate_cell.lua: -------------------------------------------------------------------------------- 1 | local cellname = args[1] 2 | return pcell.create_layout(string.format("verilogimport/%s", cellname), "cell") 3 | -------------------------------------------------------------------------------- /examples/place_and_route_automatic/place_route_generate.lua: -------------------------------------------------------------------------------- 1 | if not args[1] then 2 | error("no target given") 3 | end 4 | 5 | local module = args[1] 6 | local exporttype = "gds" 7 | 8 | local netlist = verilog.read_parse_file(string.format("%s.v", module)) 9 | 10 | verilogprocessor.write_spice_netlist(string.format("%s_netlist.sp", module), netlist) 11 | 12 | local cellinfo = verilogprocessor.read_cellinfo_from_file("cellinfo.lua") 13 | local ignorednets = { -- insert names of nets that should be ignored 14 | "clk", 15 | } 16 | local circuit = verilogprocessor.collect_nets_cells(netlist, cellinfo, ignorednets) 17 | 18 | local utilization = 0.6 19 | local numrows = 12 20 | local floorplan = placement.create_floorplan_fixed_rows(circuit, utilization, numrows) 21 | local rows = placement.optimize(circuit, floorplan) 22 | --local plan = { 23 | -- { "inv", "nand1", "dff_out" }, 24 | -- { "nand2", "dff_buf" }, 25 | -- { "nand3", "dff_in" }, 26 | --} 27 | --local plan = { 28 | -- { "inv1", }, 29 | -- { "inv2" } 30 | --} 31 | --local rows = placement.manual(circuit, plan) 32 | placement.insert_filler_names(rows, floorplan.floorplan_width) 33 | 34 | -- hack: insert fill at the left side 35 | -- this is done to ensure that routing works if a dff is there, since their gates extend to the left 36 | -- this will be fixed and removed at some point 37 | for i in ipairs(rows) do 38 | table.insert(rows[i], 1, { 39 | reference = "isogate", 40 | instance = string.format("hackfill_%i", i), 41 | width = 1 42 | }) 43 | end 44 | floorplan.floorplan_width = floorplan.floorplan_width + 1 45 | 46 | -- this value can be (at least in theory) changed in the generated layout, but the router assumes this many tracks 47 | -- this means that reducing this value CAN work, but only increasing it will work certainly 48 | local pnumtracks = 4 49 | local nnumtracks = 4 50 | local numinnertracks = 3 51 | 52 | local routes = routing.basic(circuit, rows, numinnertracks, pnumtracks, nnumtracks, floorplan) 53 | 54 | local filename = generator.get_cell_filename("verilogimport", "verilogimport", module) 55 | print(string.format("writing to file '%s'", filename)) 56 | local file = io.open(filename, "w") 57 | generator.digital(file, rows, routes, numinnertracks, pnumtracks, nnumtracks) 58 | file:close() 59 | -------------------------------------------------------------------------------- /examples/place_and_route_automatic/run.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | CELL=serial_ctrl 4 | 5 | ../../opc --import-verilog place_route_generate.lua ${CELL} 6 | ../../opc --technology GF22FDSOI --export gds --cellscript generate_cell.lua --cellpath verilogimport ${CELL} 7 | -------------------------------------------------------------------------------- /examples/svg/gilfoyle.lua: -------------------------------------------------------------------------------- 1 | local cell = object.create("gilfoyle") 2 | 3 | cell:merge_into(pcell.create_layout("auxiliary/svg2layout", "_svg", { 4 | filename = "gilfoyle.svg", 5 | scale = 10, 6 | grid = 1, 7 | allow45 = true, 8 | inverty = true, 9 | })) 10 | 11 | return cell 12 | -------------------------------------------------------------------------------- /examples/svg/pineapple.lua: -------------------------------------------------------------------------------- 1 | local cell = object.create("pineapple") 2 | 3 | cell:merge_into(pcell.create_layout("auxiliary/svg2layout", "_svg", { 4 | filename = "pineapple.svg", 5 | scale = 1, 6 | grid = 1, 7 | allow45 = true, 8 | })) 9 | 10 | return cell 11 | -------------------------------------------------------------------------------- /examples/svg/run.sh: -------------------------------------------------------------------------------- 1 | OPC=../../opc 2 | 3 | ${OPC} --technology opc --export gds --cellscript pineapple.lua --filename pineapple 4 | ${OPC} --technology opc --export gds --cellscript talentandsweat.lua --filename talentandsweat 5 | ${OPC} --technology opc --export gds --cellscript gilfoyle.lua --filename gilfoyle 6 | -------------------------------------------------------------------------------- /examples/svg/talentandsweat.lua: -------------------------------------------------------------------------------- 1 | local cell = object.create("talentandsweat") 2 | 3 | cell:merge_into(pcell.create_layout("auxiliary/svg2layout", "_svg", { 4 | filename = "talentandsweat.svg", 5 | scale = 120, 6 | grid = 1, 7 | allow45 = true, 8 | inverty = true, 9 | })) 10 | 11 | return cell 12 | -------------------------------------------------------------------------------- /export/debug/init.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local __content = {} 4 | 5 | function M.finalize() 6 | return table.concat(__content, "\n") 7 | end 8 | 9 | function M.get_techexport() 10 | return "raw" 11 | end 12 | 13 | function M.get_extension() 14 | return "debug" 15 | end 16 | 17 | function M.get_layer(S) 18 | return S:get_lpp():str() 19 | end 20 | 21 | function M.write_rectangle(layer, bl, tr) 22 | local xbot, ybot = bl:unwrap() 23 | local xtop, ytop = tr:unwrap() 24 | table.insert(__content, string.format("rect (%s): (%d, %d) (%d, %d)", layer, xbot, ybot, xtop, ytop)) 25 | end 26 | 27 | function M.write_polygon(layer, pts) 28 | local t = {} 29 | for _, pt in ipairs(pts) do 30 | local x, y = pt:unwrap() 31 | table.insert(t, string.format("(%d, %d)", x, y)) 32 | end 33 | table.insert(__content, string.format("poly (%s): %s", layer, table.concat(t, " "))) 34 | end 35 | 36 | function M.write_cell_reference(identifier, instname, origin) 37 | table.insert(__content, string.format("ref (%s): (%d, %d)", identifier, origin:getx(), origin:gety())) 38 | end 39 | 40 | function M.at_begin_cell(cellname) 41 | table.insert(__content, string.format("cell (%s) >", cellname)) 42 | end 43 | 44 | function M.at_end_cell() 45 | table.insert(__content, "<\n") 46 | end 47 | 48 | return M 49 | -------------------------------------------------------------------------------- /export/magic/init.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | function M.get_extension() 4 | return "mag" 5 | end 6 | 7 | local __technology = "DUMMYTECH" 8 | 9 | function M.set_options(opt) 10 | for i = 1, #opt do 11 | local arg = opt[i] 12 | if arg == "-T" or arg == "--technology" then 13 | if i < #opt then 14 | __technology = opt[i + 1] 15 | else 16 | error("magic export: --technology: argument expected") 17 | end 18 | i = i + 1 19 | end 20 | end 21 | end 22 | 23 | local __content = {} 24 | 25 | function M.finalize() 26 | return table.concat(__content, "\n") 27 | end 28 | 29 | function M.at_begin() 30 | table.insert(__content, string.format("%s", "magic")) 31 | table.insert(__content, string.format("tech %s", __technology)) 32 | table.insert(__content, string.format("timestamp %s", os.time())) 33 | end 34 | 35 | function M.at_end() 36 | table.insert(__content, string.format("%s", "<< end >>")) 37 | end 38 | 39 | function M.write_rectangle(layer, bl, tr) 40 | local grid = 1000 41 | bl.x = bl.x * grid 42 | bl.y = bl.y * grid 43 | tr.x = tr.x * grid 44 | tr.y = tr.y * grid 45 | table.insert(__content, string.format("<< %s >>", layer.layer)) 46 | table.insert(__content, string.format("rect %d %d %d %d", math.floor(bl.x), math.floor(bl.y), math.floor(tr.x), math.floor(tr.y))) 47 | end 48 | 49 | function M.write_triangle(layer, pt1, pt2, pt3) 50 | print("write_triangle is not finished, as at that time I did not know the exact required format. This should be trivial to fix") 51 | end 52 | 53 | function M.write_port(name, layer, where, sizehint) 54 | print("write_port is not finished, as at that time I did not know the exact required format. This should be trivial to fix") 55 | end 56 | 57 | return M 58 | -------------------------------------------------------------------------------- /interface/virtuoso/backup.il: -------------------------------------------------------------------------------- 1 | procedure(OPCCreateCellBackup() 2 | let( 3 | ( 4 | (path lsprintf("%s/%s" getShellEnvVar("HOME") "opcbackups")) 5 | ) 6 | unless(isDir(path) 7 | createDir(path) 8 | ) 9 | let( 10 | ( 11 | (cv geGetEditCellView()) 12 | ) 13 | OPCExportCell(lsprintf("%s/%s_%s.lua" path cv->libName cv->cellName)) 14 | ) 15 | ) 16 | ) 17 | 18 | procedure(OPCRestoreCellBackup() 19 | let( 20 | ( 21 | (path lsprintf("%s/%s" getShellEnvVar("HOME") "opcbackups")) 22 | ) 23 | if(isDir(path) 24 | then 25 | let( 26 | ( 27 | (cv geGetEditCellView()) 28 | filename 29 | ) 30 | filename = lsprintf("%s/%s_%s.lua" path cv->libName cv->cellName) 31 | if(isFile(filename) 32 | then 33 | OPCUpdateCellscriptCallback(filename ?hierarchical nil) 34 | else 35 | hiDisplayAppDBox( 36 | ?name 'OPCInfoDialog 37 | ?dboxBanner "openPCells" 38 | ?dboxText lsprintf("no opc backup for this cell (%s) found" filename) 39 | ?dialogType hicWarningDialog 40 | ?dialogStyle 'modeless 41 | ?buttonLayout 'Close 42 | ) 43 | ) 44 | ) 45 | else 46 | ) 47 | ) 48 | ) 49 | -------------------------------------------------------------------------------- /interface/virtuoso/cdsinit.il.sample: -------------------------------------------------------------------------------- 1 | ; this is a sample .cdsinit that shows how to set up openPCells with cadence virtuoso 2 | 3 | ; the used technology has to be defined, this will be passed verbatim to opc 4 | ; so if you call opc like this: opc --technology tech42 ... 5 | ; then OPCTech should be "tech42" 6 | OPCTech = "tech42" 7 | ; for this to work you also need to make sure that opc can find the technology files 8 | ; the easiest way to do this is to add the location to the config file at ~/.opcconfig.lua: 9 | ; please note that the path to the parent directory of the technology files, not the actual directory 10 | ; return { 11 | ; techpaths = { 12 | ; "/path/to/technology_files" 13 | ; } 14 | ; } 15 | 16 | ; the installation DIRECTORY of openPCells has to be given: 17 | OPCPath = "/path/to/opc" 18 | 19 | ; the name of the executable (which will be 'opc' if you don't change this manually during compiling) 20 | OPCExec = "opc" 21 | 22 | ; lastly, we load the opc interface for virtuoso 23 | load(lsprintf("%s/interface/virtuoso/init.il" OPCPath)) 24 | -------------------------------------------------------------------------------- /interface/virtuoso/init.il: -------------------------------------------------------------------------------- 1 | foreach(file list("backup" "call" "edit_update" "export" "menu" "misc" "settings" "subcell" "cells") 2 | load(lsprintf("%s/interface/virtuoso/%s.il" OPCPath file)) 3 | ) 4 | 5 | ; initialize forms 6 | unless(boundp('OPCSettingsForm) 7 | OPCCreateSettingsForm() 8 | ) 9 | -------------------------------------------------------------------------------- /interface/virtuoso/misc.il: -------------------------------------------------------------------------------- 1 | procedure(OPCAboutCallback() 2 | let( 3 | (OPCAboutForm) 4 | OPCAboutForm = hiCreateAppForm( 5 | ?name 'OPCAboutForm 6 | ?formTitle "openPCells About" 7 | ?buttonLayout 'OKCancel 8 | ?fields list( 9 | hiCreateHypertextField( 10 | ?name 'OPCHTMLField 11 | ?title "" 12 | ?value "
openPCells (opc) 0.1.0 – ©Patrick Kurth 2020–2021
Website" 13 | ) 14 | ) 15 | ) 16 | hiDisplayForm(OPCAboutForm 100:100) 17 | ) 18 | ) ; procedure 19 | -------------------------------------------------------------------------------- /logo/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all: 3 | lualatex logo.tex 4 | -------------------------------------------------------------------------------- /logo/logo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patrickschulz/openPCells/14f34e0a04d0e87ac7ac1027ab7522b20e90d074/logo/logo.pdf -------------------------------------------------------------------------------- /logo/logo.tex: -------------------------------------------------------------------------------- 1 | \documentclass{standalone} 2 | 3 | \usepackage{tikz} 4 | \usepackage{fontspec} 5 | \setmainfont{Linux Libertine} 6 | 7 | \begin{document} 8 | \begin{tikzpicture} 9 | \def\radius{1} 10 | \def\angle{60} 11 | %\path[use as bounding box] ({-1 * \radius}, {sin(180 + \angle) * \radius}) rectangle ({1 * \radius}, {1 * \radius}); 12 | \begin{scope} 13 | \draw[clip] ({\radius * cos(180 + \angle)}, {\radius * sin(180 + \angle)}) arc[start angle = 180 + \angle, end angle = -\angle, radius = \radius] -- cycle; 14 | \draw[black!60] ({-2 * \radius}, {-2 * \radius}) grid[step = 1mm] ({2 * \radius}, {2 * \radius}); 15 | \draw ({\radius * cos(180 + \angle)}, {\radius * sin(180 + \angle)}) arc[start angle = 180 + \angle, end angle = -\angle, radius = \radius] -- cycle; 16 | \end{scope} 17 | \node[font = \Huge\bfseries] {OPC}; 18 | \node[anchor = north] at (0, {sin(180 + \angle) * \radius}) {openPCells}; 19 | \end{tikzpicture} 20 | \end{document} 21 | -------------------------------------------------------------------------------- /resources/extract_pinoffsets.lua: -------------------------------------------------------------------------------- 1 | local celllist = { 2 | "buf", 3 | "cinv", 4 | "not_gate", 5 | "nand_gate", 6 | "nor_gate", 7 | "or_gate", 8 | "and_gate", 9 | --"tbuf", 10 | "xor_gate", 11 | "dffpq", 12 | "dffnq", 13 | "dffprq", 14 | "dffnrq", 15 | "dffpsq", 16 | "dffnsq", 17 | --"dffprsq", 18 | --"dffnrsq", 19 | } 20 | 21 | local gatelength = 200 22 | local gatespace = 300 23 | local routingwidth = 200 24 | local routingspace = 300 25 | 26 | pcell.push_overwrites("stdcells/base", { 27 | glength = gatelength, 28 | gspace = gatespace, 29 | routingwidth = routingwidth, 30 | routingspace = routingspace, 31 | powerwidth = 480, 32 | pnumtracks = 3, 33 | nnumtracks = 3, 34 | }) 35 | 36 | local toplevel = object.create("opctoplevel") 37 | local lastanchor 38 | 39 | local lines = {} 40 | table.insert(lines, "return {") 41 | for i, cellname in ipairs(celllist) do 42 | local cell = pcell.create_layout(string.format("stdcells/%s", cellname), cellname) 43 | local child = toplevel:add_child(cell, cellname) 44 | child:move_anchor_y("bottom", lastanchor) 45 | lastanchor = child:get_anchor("top") 46 | 47 | local left = child:get_anchor("left") 48 | local right = child:get_anchor("right") 49 | local width = (right:getx() - left:getx()) / (gatelength + gatespace) 50 | table.insert(lines, string.format(" %s = {", cellname)) 51 | table.insert(lines, string.format(" width = %d,", width)) 52 | local ports = cell:get_ports() 53 | table.insert(lines, " pinoffsets = {") 54 | for _, port in ipairs(ports) do 55 | if port.name ~= "VDD" and port.name ~= "VSS" then 56 | local x, y = port.where:unwrap() 57 | local xoffset = x / (gatelength + gatespace) 58 | local yoffset = y / (routingwidth + routingspace) 59 | --table.insert(lines, string.format(" %s = { x = %d, y = %d },", port.name, math.floor(xoffset), math.floor(yoffset))) 60 | table.insert(lines, string.format(" %s = { x = %.1f, y = %.1f },", port.name, xoffset, yoffset)) 61 | end 62 | end 63 | table.insert(lines, " },") 64 | table.insert(lines, " },") 65 | end 66 | table.insert(lines, "}") 67 | print(table.concat(lines, "\n")) 68 | 69 | return toplevel 70 | -------------------------------------------------------------------------------- /resources/extract_stdcells_netlists.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | FILENAMES=$(ls ../cells/stdcells/*.lua) 4 | OUTPUTPATH="spice/stdcells" 5 | 6 | mkdir -p ../${OUTPUTPATH} 7 | for FILE in $FILENAMES 8 | do 9 | cellname=$(basename ${FILE%.lua}) 10 | (cd .. && 11 | echo stdcells/${cellname} 12 | ./opc --technology opc --export gds --cell stdcells/${cellname} && 13 | klayout openPCells.gds -rd filename=${cellname}.sp -z -nc -rx -n opc -r resources/opc.lylvs && 14 | sed -i "s/opctoplevel/${cellname}/" *.sp && 15 | mv *.sp $OUTPUTPATH 16 | ) 17 | done 18 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/1_inv_gate.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell 1_inv_gate 4 | * pin VSS 5 | * pin A 6 | * pin O 7 | * pin B 8 | * pin VDD 9 | * pin SUBSTRATE 10 | .SUBCKT 1_inv_gate VSS A O B VDD SUBSTRATE 11 | * device instance $1 r0 *1 0,1.2 slvtpfet 12 | M$1 VDD A \$6 \$9 slvtpfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 13 | * device instance $2 r0 *1 0.5,1.2 slvtpfet 14 | M$2 \$6 B VDD \$9 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 15 | * device instance $3 r0 *1 1,1.2 slvtpfet 16 | M$3 VDD VDD VDD \$9 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 17 | * device instance $4 r0 *1 1.5,1.2 slvtpfet 18 | M$4 VDD \$6 O \$9 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 19 | * device instance $5 r0 *1 2,1.2 slvtpfet 20 | M$5 O VDD VDD \$9 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 21 | * device instance $6 r0 *1 0,-1.2 slvtnfet 22 | M$6 VSS A \$8 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 23 | * device instance $7 r0 *1 0.5,-1.2 slvtnfet 24 | M$7 \$8 B \$6 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 25 | * device instance $8 r0 *1 1,-1.2 slvtnfet 26 | M$8 \$6 VSS VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 27 | * device instance $9 r0 *1 1.5,-1.2 slvtnfet 28 | M$9 VSS \$6 O SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 29 | * device instance $10 r0 *1 2,-1.2 slvtnfet 30 | M$10 O VSS VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 31 | .ENDS 1_inv_gate 32 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/21_gate.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell 21_gate 4 | * pin A 5 | * pin B1 6 | * pin B2 7 | * pin O 8 | * pin VDD 9 | * pin VSS 10 | * pin SUBSTRATE 11 | .SUBCKT 21_gate A B1 B2 O VDD VSS SUBSTRATE 12 | * device instance $1 r0 *1 0,1.2 slvtpfet 13 | M$1 VDD B1 \$1 \$I1 slvtpfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 14 | * device instance $2 r0 *1 0.5,1.2 slvtpfet 15 | M$2 \$1 B2 VDD \$I1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 16 | * device instance $3 r0 *1 1,1.2 slvtpfet 17 | M$3 VDD VDD VDD \$I1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 18 | * device instance $4 r0 *1 1.5,1.2 slvtpfet 19 | M$4 VDD A \$I14 \$I1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 20 | * device instance $5 r0 *1 2,1.2 slvtpfet 21 | M$5 \$I14 \$1 O \$I1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 22 | * device instance $6 r0 *1 2.5,1.2 slvtpfet 23 | M$6 O VDD VDD \$I1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 24 | * device instance $7 r0 *1 0,-1.2 slvtnfet 25 | M$7 VSS B1 \$I19 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 26 | * device instance $8 r0 *1 0.5,-1.2 slvtnfet 27 | M$8 \$I19 B2 \$1 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U 28 | + PD=1.3U 29 | * device instance $9 r0 *1 1,-1.2 slvtnfet 30 | M$9 \$1 VSS VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 31 | * device instance $10 r0 *1 1.5,-1.2 slvtnfet 32 | M$10 VSS A O SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 33 | * device instance $11 r0 *1 2,-1.2 slvtnfet 34 | M$11 O \$1 VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 35 | * device instance $12 r0 *1 2.5,-1.2 slvtnfet 36 | M$12 VSS VSS VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 37 | .ENDS 21_gate 38 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/and_gate.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell and_gate 4 | * pin VSS 5 | * pin A 6 | * pin O 7 | * pin B 8 | * pin VDD 9 | * pin SUBSTRATE 10 | .SUBCKT and_gate VSS A O B VDD SUBSTRATE 11 | * device instance $1 r0 *1 0,1.2 slvtpfet 12 | M$1 VDD A \$6 \$9 slvtpfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 13 | * device instance $2 r0 *1 0.5,1.2 slvtpfet 14 | M$2 \$6 B VDD \$9 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 15 | * device instance $3 r0 *1 1,1.2 slvtpfet 16 | M$3 VDD VDD VDD \$9 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 17 | * device instance $4 r0 *1 1.5,1.2 slvtpfet 18 | M$4 VDD \$6 O \$9 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 19 | * device instance $5 r0 *1 2,1.2 slvtpfet 20 | M$5 O VDD VDD \$9 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 21 | * device instance $6 r0 *1 0,-1.2 slvtnfet 22 | M$6 VSS A \$8 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 23 | * device instance $7 r0 *1 0.5,-1.2 slvtnfet 24 | M$7 \$8 B \$6 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 25 | * device instance $8 r0 *1 1,-1.2 slvtnfet 26 | M$8 \$6 VSS VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 27 | * device instance $9 r0 *1 1.5,-1.2 slvtnfet 28 | M$9 VSS \$6 O SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 29 | * device instance $10 r0 *1 2,-1.2 slvtnfet 30 | M$10 O VSS VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 31 | .ENDS and_gate 32 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/buf.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell buf 4 | * pin I 5 | * pin VSS 6 | * pin VDD 7 | * pin O 8 | * pin SUBSTRATE 9 | .SUBCKT buf I VSS VDD O SUBSTRATE 10 | * device instance $1 r0 *1 0,1.2 slvtpfet 11 | M$1 VDD I \$5 \$1 slvtpfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 12 | * device instance $2 r0 *1 0.5,1.2 slvtpfet 13 | M$2 \$5 VDD VDD \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 14 | * device instance $3 r0 *1 1,1.2 slvtpfet 15 | M$3 VDD \$5 O \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 16 | * device instance $4 r0 *1 1.5,1.2 slvtpfet 17 | M$4 O VDD VDD \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 18 | * device instance $5 r0 *1 0,-1.2 slvtnfet 19 | M$5 VSS I \$5 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 20 | * device instance $6 r0 *1 0.5,-1.2 slvtnfet 21 | M$6 \$5 VSS VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 22 | * device instance $7 r0 *1 1,-1.2 slvtnfet 23 | M$7 VSS \$5 O SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 24 | * device instance $8 r0 *1 1.5,-1.2 slvtnfet 25 | M$8 O VSS VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 26 | .ENDS buf 27 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/cinv.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell cinv 4 | * pin I 5 | * pin EN 6 | * pin EP 7 | * pin VDD 8 | * pin VSS 9 | * pin SUBSTRATE 10 | .SUBCKT cinv I EN EP VDD VSS SUBSTRATE 11 | * device instance $1 r0 *1 0,1.2 slvtpfet 12 | M$1 \$5 I \$13 \$1 slvtpfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 13 | * device instance $2 r0 *1 0.5,1.2 slvtpfet 14 | M$2 \$13 EP VDD \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 15 | * device instance $3 r0 *1 0,-1.2 slvtnfet 16 | M$3 \$5 I \$14 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 17 | * device instance $4 r0 *1 0.5,-1.2 slvtnfet 18 | M$4 \$14 EN VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 19 | .ENDS cinv 20 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/colstop.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell colstop 4 | * pin SUBSTRATE 5 | .SUBCKT colstop SUBSTRATE 6 | * device instance $1 r0 *1 0,1.2 slvtpfet 7 | M$1 \$2 \$2 \$7 \$4 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 8 | * device instance $2 r0 *1 0,-1.2 slvtnfet 9 | M$2 \$1 \$1 \$8 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 10 | .ENDS colstop 11 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/endcell.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/generic2bit.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/harness.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell harness 4 | * pin SUBSTRATE 5 | .SUBCKT harness SUBSTRATE 6 | * device instance $1 r0 *1 0,1.2 slvtpfet 7 | M$1 \$8 \$1 \$7 \$2 slvtpfet L=0.2U W=1U AS=0.4P AD=0.4P PS=2.8U PD=2.8U 8 | * device instance $2 r0 *1 0,-1.2 slvtnfet 9 | M$2 \$10 \$1 \$9 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.4P PS=2.8U PD=2.8U 10 | .ENDS harness 11 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/isogate.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell isogate 4 | * pin SUBSTRATE 5 | .SUBCKT isogate SUBSTRATE 6 | * device instance $1 r0 *1 0.25,1.2 slvtpfet 7 | M$1 \$5 \$2 \$4 \$3 slvtpfet L=0.2U W=1U AS=0.4P AD=0.4P PS=2.8U PD=2.8U 8 | * device instance $2 r0 *1 0.25,-1.2 slvtnfet 9 | M$2 \$7 \$1 \$6 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.4P PS=2.8U PD=2.8U 10 | .ENDS isogate 11 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/latch_cell.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell latch_cell 4 | * pin SUBSTRATE 5 | .SUBCKT latch_cell SUBSTRATE 6 | * device instance $1 r0 *1 0,1.2 slvtpfet 7 | M$1 \$9 \$2 \$2 \$1 slvtpfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 8 | * device instance $2 r0 *1 0.5,1.2 slvtpfet 9 | M$2 \$2 \$3 \$10 \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 10 | * device instance $3 r0 *1 1,1.2 slvtpfet 11 | M$3 \$10 \$4 \$10 \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 12 | * device instance $4 r0 *1 1.5,1.2 slvtpfet 13 | M$4 \$10 \$5 \$8 \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 14 | * device instance $5 r0 *1 2,1.2 slvtpfet 15 | M$5 \$8 \$6 \$22 \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 16 | * device instance $6 r0 *1 2.5,1.2 slvtpfet 17 | M$6 \$22 \$8 \$21 \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 18 | * device instance $7 r0 *1 0,-1.2 slvtnfet 19 | M$7 \$9 \$2 \$2 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 20 | * device instance $8 r0 *1 0.5,-1.2 slvtnfet 21 | M$8 \$2 \$3 \$24 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U 22 | + PD=1.3U 23 | * device instance $9 r0 *1 1,-1.2 slvtnfet 24 | M$9 \$24 \$4 \$7 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U 25 | + PD=1.3U 26 | * device instance $10 r0 *1 1.5,-1.2 slvtnfet 27 | M$10 \$7 \$5 \$7 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U 28 | + PD=1.3U 29 | * device instance $11 r0 *1 2,-1.2 slvtnfet 30 | M$11 \$7 \$6 \$23 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U 31 | + PD=1.3U 32 | * device instance $12 r0 *1 2.5,-1.2 slvtnfet 33 | M$12 \$23 \$7 \$25 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U 34 | + PD=2.8U 35 | .ENDS latch_cell 36 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/leftcolstop.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell leftcolstop 4 | * pin SUBSTRATE 5 | .SUBCKT leftcolstop SUBSTRATE 6 | * device instance $1 r0 *1 0,1.2 slvtpfet 7 | M$1 \$2 \$2 \$7 \$4 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 8 | * device instance $2 r0 *1 0,-1.2 slvtnfet 9 | M$2 \$1 \$1 \$8 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 10 | .ENDS leftcolstop 11 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/mux.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell mux 4 | * pin A,B 5 | * pin O 6 | * pin VDD 7 | * pin VSS 8 | * pin SUBSTRATE 9 | .SUBCKT mux A|B O VDD VSS SUBSTRATE 10 | * device instance $1 r0 *1 0,1.2 slvtpfet 11 | M$1 VDD A|B \$7 \$1 slvtpfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 12 | * device instance $2 r0 *1 0.5,1.2 slvtpfet 13 | M$2 \$7 \$3 \$9 \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 14 | * device instance $3 r0 *1 1,1.2 slvtpfet 15 | M$3 \$9 O VDD \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 16 | * device instance $4 r0 *1 0,-1.2 slvtnfet 17 | M$4 VSS A|B \$8 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 18 | * device instance $5 r0 *1 0.5,-1.2 slvtnfet 19 | M$5 \$8 \$3 \$10 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U 20 | + PD=1.3U 21 | * device instance $6 r0 *1 1,-1.2 slvtnfet 22 | M$6 \$10 O VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 23 | .ENDS mux 24 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/nand_gate.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell nand_gate 4 | * pin A 5 | * pin B 6 | * pin VSS 7 | * pin VDD 8 | * pin O 9 | * pin SUBSTRATE 10 | .SUBCKT nand_gate A B VSS VDD O SUBSTRATE 11 | * device instance $1 r0 *1 0,1.2 slvtpfet 12 | M$1 VDD A O \$1 slvtpfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 13 | * device instance $2 r0 *1 0.5,1.2 slvtpfet 14 | M$2 O B VDD \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 15 | * device instance $3 r0 *1 1,1.2 slvtpfet 16 | M$3 VDD VDD VDD \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 17 | * device instance $4 r0 *1 0,-1.2 slvtnfet 18 | M$4 VSS A \$11 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 19 | * device instance $5 r0 *1 0.5,-1.2 slvtnfet 20 | M$5 \$11 B O SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 21 | * device instance $6 r0 *1 1,-1.2 slvtnfet 22 | M$6 O VSS VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 23 | .ENDS nand_gate 24 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/nand_nor_layout_base.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell nand_nor_layout_base 4 | * pin A 5 | * pin B 6 | * pin VSS 7 | * pin VDD 8 | * pin O 9 | * pin SUBSTRATE 10 | .SUBCKT nand_nor_layout_base A B VSS VDD O SUBSTRATE 11 | * device instance $1 r0 *1 0,1.2 slvtpfet 12 | M$1 VDD A O \$1 slvtpfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 13 | * device instance $2 r0 *1 0.5,1.2 slvtpfet 14 | M$2 O B VDD \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 15 | * device instance $3 r0 *1 1,1.2 slvtpfet 16 | M$3 VDD VDD VDD \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 17 | * device instance $4 r0 *1 0,-1.2 slvtnfet 18 | M$4 VSS A \$11 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 19 | * device instance $5 r0 *1 0.5,-1.2 slvtnfet 20 | M$5 \$11 B O SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 21 | * device instance $6 r0 *1 1,-1.2 slvtnfet 22 | M$6 O VSS VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 23 | .ENDS nand_nor_layout_base 24 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/nor_gate.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell nor_gate 4 | * pin A 5 | * pin B 6 | * pin VSS 7 | * pin VDD 8 | * pin O 9 | * pin SUBSTRATE 10 | .SUBCKT nor_gate A B VSS VDD O SUBSTRATE 11 | * device instance $1 r0 *1 0,1.2 slvtpfet 12 | M$1 VDD A \$11 \$1 slvtpfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 13 | * device instance $2 r0 *1 0.5,1.2 slvtpfet 14 | M$2 \$11 B O \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 15 | * device instance $3 r0 *1 1,1.2 slvtpfet 16 | M$3 O VDD VDD \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 17 | * device instance $4 r0 *1 0,-1.2 slvtnfet 18 | M$4 VSS A O SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 19 | * device instance $5 r0 *1 0.5,-1.2 slvtnfet 20 | M$5 O B VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 21 | * device instance $6 r0 *1 1,-1.2 slvtnfet 22 | M$6 VSS VSS VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 23 | .ENDS nor_gate 24 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/not_gate.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell not_gate 4 | * pin I 5 | * pin VSS 6 | * pin VDD 7 | * pin O 8 | * pin SUBSTRATE 9 | .SUBCKT not_gate I VSS VDD O SUBSTRATE 10 | * device instance $1 r0 *1 0,1.2 slvtpfet 11 | M$1 VDD I O \$1 slvtpfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 12 | * device instance $2 r0 *1 0.5,1.2 slvtpfet 13 | M$2 O VDD VDD \$1 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 14 | * device instance $3 r0 *1 0,-1.2 slvtnfet 15 | M$3 VSS I O SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 16 | * device instance $4 r0 *1 0.5,-1.2 slvtnfet 17 | M$4 O VSS VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 18 | .ENDS not_gate 19 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/or_gate.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell or_gate 4 | * pin VSS 5 | * pin A 6 | * pin O 7 | * pin B 8 | * pin VDD 9 | * pin SUBSTRATE 10 | .SUBCKT or_gate VSS A O B VDD SUBSTRATE 11 | * device instance $1 r0 *1 0,1.2 slvtpfet 12 | M$1 VDD A \$12 \$6 slvtpfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 13 | * device instance $2 r0 *1 0.5,1.2 slvtpfet 14 | M$2 \$12 B \$7 \$6 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 15 | * device instance $3 r0 *1 1,1.2 slvtpfet 16 | M$3 \$7 VDD VDD \$6 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 17 | * device instance $4 r0 *1 1.5,1.2 slvtpfet 18 | M$4 VDD \$7 O \$6 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 19 | * device instance $5 r0 *1 2,1.2 slvtpfet 20 | M$5 O VDD VDD \$6 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 21 | * device instance $6 r0 *1 0,-1.2 slvtnfet 22 | M$6 VSS A \$7 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 23 | * device instance $7 r0 *1 0.5,-1.2 slvtnfet 24 | M$7 \$7 B VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 25 | * device instance $8 r0 *1 1,-1.2 slvtnfet 26 | M$8 VSS VSS VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 27 | * device instance $9 r0 *1 1.5,-1.2 slvtnfet 28 | M$9 VSS \$7 O SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 29 | * device instance $10 r0 *1 2,-1.2 slvtnfet 30 | M$10 O VSS VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 31 | .ENDS or_gate 32 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/rightcolstop.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell rightcolstop 4 | * pin SUBSTRATE 5 | .SUBCKT rightcolstop SUBSTRATE 6 | * device instance $1 r0 *1 0,1.2 slvtpfet 7 | M$1 \$7 \$2 \$2 \$4 slvtpfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 8 | * device instance $2 r0 *1 0,-1.2 slvtnfet 9 | M$2 \$8 \$1 \$1 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 10 | .ENDS rightcolstop 11 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/tbuf.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell tbuf 4 | * pin VSS 5 | * pin EN 6 | * pin I 7 | * pin VDD 8 | * pin SUBSTRATE 9 | .SUBCKT tbuf VSS EN I VDD SUBSTRATE 10 | * device instance $1 r0 *1 0,1.2 slvtpfet 11 | M$1 VDD EN \$6 \$10 slvtpfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 12 | * device instance $2 r0 *1 0.5,1.2 slvtpfet 13 | M$2 \$6 VDD VDD \$10 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 14 | * device instance $3 r0 *1 1,1.2 slvtpfet 15 | M$3 VDD VDD \$7 \$10 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 16 | * device instance $4 r0 *1 1.5,1.2 slvtpfet 17 | M$4 \$7 I \$13 \$10 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 18 | * device instance $5 r0 *1 2,1.2 slvtpfet 19 | M$5 \$13 \$6 VDD \$10 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 20 | * device instance $6 r0 *1 0,-1.2 slvtnfet 21 | M$6 VSS EN \$6 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.15P PS=2.8U PD=1.3U 22 | * device instance $7 r0 *1 0.5,-1.2 slvtnfet 23 | M$7 \$6 VSS VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 24 | * device instance $8 r0 *1 1,-1.2 slvtnfet 25 | M$8 VSS VSS \$7 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 26 | * device instance $9 r0 *1 1.5,-1.2 slvtnfet 27 | M$9 \$7 I \$8 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 28 | * device instance $10 r0 *1 2,-1.2 slvtnfet 29 | M$10 \$8 EN VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 30 | .ENDS tbuf 31 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/tgate.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell tgate 4 | * pin EN 5 | * pin EP 6 | * pin I 7 | * pin O 8 | * pin SUBSTRATE 9 | .SUBCKT tgate EN EP I O SUBSTRATE 10 | * device instance $1 r0 *1 0,1.2 slvtpfet 11 | M$1 I EP O \$7 slvtpfet L=0.2U W=1U AS=0.4P AD=0.4P PS=2.8U PD=2.8U 12 | * device instance $2 r0 *1 0,-1.2 slvtnfet 13 | M$2 I EN O SUBSTRATE slvtnfet L=0.2U W=1U AS=0.4P AD=0.4P PS=2.8U PD=2.8U 14 | .ENDS tgate 15 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/xnor_gate.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell xnor_gate 4 | * pin VSS 5 | * pin A,B,O 6 | * pin VDD 7 | * pin SUBSTRATE 8 | .SUBCKT xnor_gate VSS A|B|O VDD SUBSTRATE 9 | * device instance $1 r0 *1 -1,1.2 slvtpfet 10 | M$1 VDD A|B|O A|B|O \$14 slvtpfet L=0.2U W=2U AS=0.55P AD=0.3P PS=4.1U PD=2.6U 11 | * device instance $2 r0 *1 -0.5,1.2 slvtpfet 12 | M$2 A|B|O VDD VDD \$14 slvtpfet L=0.2U W=2U AS=0.3P AD=0.3P PS=2.6U PD=2.6U 13 | * device instance $5 r0 *1 1,1.2 slvtpfet 14 | M$5 VDD A|B|O \$16 \$14 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 15 | * device instance $6 r0 *1 1.5,1.2 slvtpfet 16 | M$6 \$16 A|B|O \$16 \$14 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 17 | * device instance $7 r0 *1 2,1.2 slvtpfet 18 | M$7 \$16 A|B|O \$12 \$14 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 19 | * device instance $8 r0 *1 2.5,1.2 slvtpfet 20 | M$8 \$12 A|B|O \$22 \$14 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 21 | * device instance $9 r0 *1 3,1.2 slvtpfet 22 | M$9 \$22 A|B|O VDD \$14 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 23 | * device instance $10 r0 *1 3.5,1.2 slvtpfet 24 | M$10 VDD A|B|O VDD \$14 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 25 | * device instance $11 r0 *1 -1,-1.2 slvtnfet 26 | M$11 VSS A|B|O A|B|O SUBSTRATE slvtnfet L=0.2U W=2U AS=0.55P AD=0.3P PS=4.1U 27 | + PD=2.6U 28 | * device instance $12 r0 *1 -0.5,-1.2 slvtnfet 29 | M$12 A|B|O VSS VSS SUBSTRATE slvtnfet L=0.2U W=2U AS=0.3P AD=0.3P PS=2.6U 30 | + PD=2.6U 31 | * device instance $15 r0 *1 1,-1.2 slvtnfet 32 | M$15 VSS A|B|O VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U 33 | + PD=1.3U 34 | * device instance $16 r0 *1 1.5,-1.2 slvtnfet 35 | M$16 VSS A|B|O \$13 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U 36 | + PD=1.3U 37 | * device instance $17 r0 *1 2,-1.2 slvtnfet 38 | M$17 \$13 A|B|O \$12 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U 39 | + PD=1.3U 40 | * device instance $18 r0 *1 2.5,-1.2 slvtnfet 41 | M$18 \$12 A|B|O \$10 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U 42 | + PD=1.3U 43 | * device instance $19 r0 *1 3,-1.2 slvtnfet 44 | M$19 \$10 A|B|O \$10 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U 45 | + PD=1.3U 46 | * device instance $20 r0 *1 3.5,-1.2 slvtnfet 47 | M$20 \$10 A|B|O VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U 48 | + PD=2.8U 49 | .ENDS xnor_gate 50 | -------------------------------------------------------------------------------- /resources/stdcells_netlists/xor_gate.sp: -------------------------------------------------------------------------------- 1 | * Created by KLayout 2 | 3 | * cell xor_gate 4 | * pin VSS 5 | * pin A,B,O 6 | * pin VDD 7 | * pin SUBSTRATE 8 | .SUBCKT xor_gate VSS A|B|O VDD SUBSTRATE 9 | * device instance $1 r0 *1 0,1.2 slvtpfet 10 | M$1 VDD A|B|O A|B|O \$14 slvtpfet L=0.2U W=2U AS=0.55P AD=0.3P PS=4.1U PD=2.6U 11 | * device instance $2 r0 *1 0.5,1.2 slvtpfet 12 | M$2 A|B|O VDD VDD \$14 slvtpfet L=0.2U W=2U AS=0.3P AD=0.3P PS=2.6U PD=2.6U 13 | * device instance $5 r0 *1 2,1.2 slvtpfet 14 | M$5 VDD A|B|O \$16 \$14 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 15 | * device instance $6 r0 *1 2.5,1.2 slvtpfet 16 | M$6 \$16 A|B|O \$16 \$14 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 17 | * device instance $7 r0 *1 3,1.2 slvtpfet 18 | M$7 \$16 A|B|O \$12 \$14 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 19 | * device instance $8 r0 *1 3.5,1.2 slvtpfet 20 | M$8 \$12 A|B|O \$22 \$14 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 21 | * device instance $9 r0 *1 4,1.2 slvtpfet 22 | M$9 \$22 A|B|O VDD \$14 slvtpfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U PD=1.3U 23 | * device instance $10 r0 *1 4.5,1.2 slvtpfet 24 | M$10 VDD A|B|O VDD \$14 slvtpfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U PD=2.8U 25 | * device instance $11 r0 *1 0,-1.2 slvtnfet 26 | M$11 VSS A|B|O A|B|O SUBSTRATE slvtnfet L=0.2U W=2U AS=0.55P AD=0.3P PS=4.1U 27 | + PD=2.6U 28 | * device instance $12 r0 *1 0.5,-1.2 slvtnfet 29 | M$12 A|B|O VSS VSS SUBSTRATE slvtnfet L=0.2U W=2U AS=0.3P AD=0.3P PS=2.6U 30 | + PD=2.6U 31 | * device instance $15 r0 *1 2,-1.2 slvtnfet 32 | M$15 VSS A|B|O VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U 33 | + PD=1.3U 34 | * device instance $16 r0 *1 2.5,-1.2 slvtnfet 35 | M$16 VSS A|B|O \$13 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U 36 | + PD=1.3U 37 | * device instance $17 r0 *1 3,-1.2 slvtnfet 38 | M$17 \$13 A|B|O \$12 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U 39 | + PD=1.3U 40 | * device instance $18 r0 *1 3.5,-1.2 slvtnfet 41 | M$18 \$12 A|B|O \$10 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U 42 | + PD=1.3U 43 | * device instance $19 r0 *1 4,-1.2 slvtnfet 44 | M$19 \$10 A|B|O \$10 SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.15P PS=1.3U 45 | + PD=1.3U 46 | * device instance $20 r0 *1 4.5,-1.2 slvtnfet 47 | M$20 \$10 A|B|O VSS SUBSTRATE slvtnfet L=0.2U W=1U AS=0.15P AD=0.4P PS=1.3U 48 | + PD=2.8U 49 | .ENDS xor_gate 50 | -------------------------------------------------------------------------------- /saradc/caparray.lua: -------------------------------------------------------------------------------- 1 | local cell = object.create("toplevel") 2 | 3 | -- basic mos parameters 4 | local gatelength = 20 5 | local gatespace = 84 6 | local fingerwidth = 500 7 | local nfetvthtype = 1 8 | local pfetvthtype = 3 9 | local sdwidth = 40 10 | local sdspace = 80 11 | local powerwidth = 3 * sdwidth 12 | local powerspace = 3 * sdspace 13 | 14 | -- switch_network parameters 15 | local buffingers = 2 16 | local switchfingers = 8 17 | 18 | -- buf_array parameters 19 | local buff1ingers = 4 20 | local buff2ingers = 2 21 | 22 | -- cap_array parameters 23 | local bits = 8 24 | local rwidth = 100 25 | 26 | -- cap array up 27 | local cap_array_up = pcell.create_layout("SAR_ADC/cap_array", "cap_array_up", { 28 | bits = bits, 29 | rwidth = rwidth 30 | }) 31 | cell:merge_into(cap_array_up) 32 | 33 | return cell 34 | -------------------------------------------------------------------------------- /saradc/sample_and_hold.lua: -------------------------------------------------------------------------------- 1 | local cell = object.create("toplevel") 2 | 3 | local buffingers = 2 4 | local gatelength = 20 5 | local gatespace = 84 6 | local fingerwidth = 500 7 | local nfetvthtype = 1 8 | local pfetvthtype = 3 9 | local sdwidth = 40 10 | local sdspace = 80 11 | 12 | pcell.push_overwrites("basic/mosfet", { actext = 100 }) 13 | 14 | local sample_and_hold = pcell.create_layout("SAR_ADC/sample_and_hold", "sample_and_hold", { 15 | buffingers = buffingers, 16 | gatelength = gatelength, 17 | gatespace = gatespace, 18 | fingerwidth = fingerwidth, 19 | nfetvthtype = nfetvthtype, 20 | pfetvthtype = pfetvthtype, 21 | sdwidth = sdwidth, 22 | sdspace = sdspace, 23 | gstrwidth = sdwidth, 24 | gstrspace = sdspace, 25 | powerwidth = 3 * sdwidth, 26 | powerspace = 3 * sdspace 27 | 28 | }) 29 | cell:merge_into(sample_and_hold) 30 | 31 | pcell.pop_overwrites("basic/mosfet") 32 | 33 | return sample_and_hold 34 | -------------------------------------------------------------------------------- /saradc/switch_network_up.lua: -------------------------------------------------------------------------------- 1 | local cell = object.create("toplevel") 2 | 3 | local buffingers = 2 4 | local switchfingers = 8 5 | local gatelength = 20 6 | local gatespace = 84 7 | local fingerwidth = 500 8 | local nfetvthtype = 1 9 | local pfetvthtype = 3 10 | local sdwidth = 40 11 | local sdspace = 80 12 | 13 | 14 | local swup7 = pcell.create_layout("SAR_ADC/switch_network_up", "swup7", { 15 | buffingers = buffingers, 16 | switchfingers = switchfingers, 17 | gatelength = gatelength, 18 | gatespace = gatespace, 19 | fingerwidth = fingerwidth, 20 | nfetvthtype = nfetvthtype, 21 | pfetvthtype = pfetvthtype, 22 | sdwidth = sdwidth, 23 | sdspace = sdspace, 24 | gstrwidth = sdwidth, 25 | gstrspace = sdspace, 26 | powerwidth = 3 * sdwidth, 27 | powerspace = 3 * sdspace 28 | }) 29 | 30 | cell:merge_into_shallow(swup7:flatten()) 31 | 32 | --[[ 33 | 34 | cell:add_port("VDD", generics.metalport(1), swup7:get_anchor("VDD")) 35 | cell:add_port("VSS", generics.metalport(1), swup7:get_anchor("VSS")) 36 | cell:add_port("sample", generics.metalport(1), swup7:get_anchor("sample")) 37 | cell:add_port("vin", generics.metalport(2), swup7:get_anchor("vin")) 38 | cell:add_port("vout", generics.metalport(3), swup7:get_anchor("vout")) 39 | cell:add_port("data", generics.metalport(1), swup7:get_anchor("data")) 40 | cell:add_port("REF", generics.metalport(1), swup7:get_anchor("REF")) 41 | cell:add_port("GND", generics.metalport(1), swup7:get_anchor("GND")) 42 | cell:add_port("VSS", generics.otherport("nwell"), point.create(0, -1500)) 43 | 44 | 45 | --]] 46 | 47 | 48 | return swup7 49 | 50 | -------------------------------------------------------------------------------- /src/bltrshape.c: -------------------------------------------------------------------------------- 1 | #include "bltrshape.h" 2 | 3 | #include