final gds & drc results
diff --git a/Makefile.master b/Makefile.master index f6b5af4..baf8c26 100644 --- a/Makefile.master +++ b/Makefile.master
@@ -47,8 +47,8 @@ STD_CELL_LIBRARY ?= sky130_fd_sc_hd SPECIAL_VOLTAGE_LIBRARY ?= sky130_fd_sc_hvl IO_LIBRARY ?= sky130_fd_io -SKYWATER_COMMIT ?= 3d7617a1acb92ea883539bcf22a632d6361a5de4 -OPEN_PDKS_COMMIT ?= 49fc7125db927de199d1f69e002beadc0a29881b +SKYWATER_COMMIT ?= f6f76f3dc99526c6fc2cfede19b5b1227d4ebde7 +OPEN_PDKS_COMMIT ?= 95c92cc563e00b3ee3ed9863b352304943e8ff8f .DEFAULT_GOAL := ship # We need portable GDS_FILE pointers... @@ -58,6 +58,7 @@ @echo "Generating Caravel GDS (sources are in the 'gds' directory)" @sleep 1 @echo "\ + random seed `scripts/set_user_id.py -report`; \ gds readonly true; \ gds rescale false; \ gds read ../gds/user_project_wrapper.gds; \ @@ -70,8 +71,6 @@ @mv -f ./gds/caravel.gds ./gds/caravel.old.gds mv ./mag/caravel.gds ./gds - - .PHONY: clean clean: cd ./verilog/dv/caravel/mgmt_soc/ && \ @@ -129,13 +128,39 @@ @echo "All files are uncompressed!" +# verify that the wrapper was respected +xor-wrapper: + # first erase the user's user_project_wrapper.gds + sh utils/erase_box.sh gds/user_project_wrapper.gds 0 0 2920 3520 + # do the same for the empty wrapper + sh utils/erase_box.sh gds/user_project_wrapper_empty.gds 0 0 2920 3520 + mkdir -p signoff/user_project_wrapper_xor + # XOR the two resulting layouts + sh utils/xor.sh \ + gds/user_project_wrapper_empty_erased.gds gds/user_project_wrapper_erased.gds \ + user_project_wrapper user_project_wrapper.xor.xml + sh utils/xor.sh \ + gds/user_project_wrapper_empty_erased.gds gds/user_project_wrapper_erased.gds \ + user_project_wrapper gds/user_project_wrapper.xor.gds > signoff/user_project_wrapper_xor/xor.log + rm gds/user_project_wrapper_empty_erased.gds gds/user_project_wrapper_erased.gds + mv gds/user_project_wrapper.xor.gds gds/user_project_wrapper.xor.xml signoff/user_project_wrapper_xor + python utils/parse_klayout_xor_log.py \ + -l signoff/user_project_wrapper_xor/xor.log \ + -o signoff/user_project_wrapper_xor/total.txt + # screenshot the result for convenience + sh utils/scrotLayout.sh \ + $(PDK_ROOT)/sky130A/libs.tech/klayout/sky130A.lyt \ + signoff/user_project_wrapper_xor/user_project_wrapper.xor.gds + # LVS BLOCKS = $(shell cd openlane && find * -maxdepth 0 -type d) LVS_BLOCKS = $(foreach block, $(BLOCKS), lvs-$(block)) $(LVS_BLOCKS): lvs-% : ./mag/%.mag ./verilog/gl/%.v echo "Extracting $*" mkdir -p ./mag/tmp - echo "load $* -dereference;\ + echo "addpath hexdigits;\ + addpath \$$PDKPATH/libs.ref/sky130_ml_xx_hd/mag;\ + load $* -dereference;\ select top cell;\ foreach cell [cellname list children] {\ load \$$cell -dereference;\ @@ -151,7 +176,9 @@ ext2spice $*.ext;\ feedback save extract_$*.log;\ exit;" > ./mag/extract_$*.tcl - cd mag && export MAGTYPE=maglef; magic -rcfile ${PDK_ROOT}/sky130A/libs.tech/magic/current/sky130A.magicrc -noc -dnull extract_$*.tcl < /dev/null + cd mag && \ + export MAGTYPE=maglef; \ + magic -rcfile ${PDK_ROOT}/sky130A/libs.tech/magic/current/sky130A.magicrc -noc -dnull extract_$*.tcl < /dev/null mv ./mag/$*.spice ./spi/lvs rm ./mag/*.ext mv -f ./mag/extract_$*.{tcl,log} ./mag/tmp @@ -264,11 +291,13 @@ rm -rf $(PDK_ROOT)/sky130A) || \ true cd $(PDK_ROOT)/open_pdks && \ - ./configure --enable-sky130-pdk=$(PDK_ROOT)/skywater-pdk/libraries --with-sky130-local-path=$(PDK_ROOT) && \ + ./configure --enable-alpha-lib --enable-sky130-pdk=$(PDK_ROOT)/skywater-pdk/libraries --with-sky130-local-path=$(PDK_ROOT) && \ cd sky130 && \ + sed -i 's/REPO_PATH = ~\/gits/REPO_PATH = \$$\(PDK_ROOT\)\/open_pdks\/libs/g' Makefile && \ $(MAKE) veryclean && \ $(MAKE) && \ - $(MAKE) install-local + $(MAKE) install-local && \ + $(MAKE) clean .RECIPE: manifest manifest: mag/ maglef/ verilog/rtl/ scripts/ Makefile @@ -277,7 +306,7 @@ find maglef/*.mag -type f ! -name "user_project_wrapper.mag" -exec shasum {} \; >> manifest && \ shasum mag/caravel.mag mag/.magicrc >> manifest shasum scripts/set_user_id.py scripts/generate_fill.py scripts/compositor.py >> manifest - + shasum lef/user_project_wrapper_empty.lef >> manifest check-env: ifndef PDK_ROOT
diff --git a/signoff/user_project_wrapper_xor/total.txt b/signoff/user_project_wrapper_xor/total.txt new file mode 100644 index 0000000..05b29a4 --- /dev/null +++ b/signoff/user_project_wrapper_xor/total.txt
@@ -0,0 +1 @@ +Total XOR differences = 0 \ No newline at end of file
diff --git a/signoff/user_project_wrapper_xor/user_project_wrapper.xor.gds b/signoff/user_project_wrapper_xor/user_project_wrapper.xor.gds new file mode 100644 index 0000000..a0d662a --- /dev/null +++ b/signoff/user_project_wrapper_xor/user_project_wrapper.xor.gds Binary files differ
diff --git a/signoff/user_project_wrapper_xor/user_project_wrapper.xor.gds.png b/signoff/user_project_wrapper_xor/user_project_wrapper.xor.gds.png new file mode 100644 index 0000000..7e6cc85 --- /dev/null +++ b/signoff/user_project_wrapper_xor/user_project_wrapper.xor.gds.png Binary files differ
diff --git a/signoff/user_project_wrapper_xor/user_project_wrapper.xor.xml b/signoff/user_project_wrapper_xor/user_project_wrapper.xor.xml new file mode 100644 index 0000000..2d3f47a --- /dev/null +++ b/signoff/user_project_wrapper_xor/user_project_wrapper.xor.xml
@@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<report-database> + <description>XOR gds/user_project_wrapper_empty_erased.gds vs. gds/user_project_wrapper_erased.gds</description> + <original-file/> + <generator>drc: script='utils/xor.drc'</generator> + <top-cell>user_project_wrapper</top-cell> + <tags> + </tags> + <categories> + <category> + <name>235/4</name> + <description>XOR results for layer 235/4 </description> + <categories> + </categories> + </category> + <category> + <name>69/20</name> + <description>XOR results for layer 69/20 </description> + <categories> + </categories> + </category> + <category> + <name>70/20</name> + <description>XOR results for layer 70/20 </description> + <categories> + </categories> + </category> + <category> + <name>71/20</name> + <description>XOR results for layer 71/20 </description> + <categories> + </categories> + </category> + <category> + <name>71/44</name> + <description>XOR results for layer 71/44 </description> + <categories> + </categories> + </category> + <category> + <name>72/20</name> + <description>XOR results for layer 72/20 </description> + <categories> + </categories> + </category> + <category> + <name>81/14</name> + <description>XOR results for layer 81/14 </description> + <categories> + </categories> + </category> + </categories> + <cells> + <cell> + <name>user_project_wrapper</name> + <variant/> + <references> + </references> + </cell> + </cells> + <items> + </items> +</report-database>
diff --git a/signoff/user_project_wrapper_xor/xor.log b/signoff/user_project_wrapper_xor/xor.log new file mode 100644 index 0000000..b8fc692 --- /dev/null +++ b/signoff/user_project_wrapper_xor/xor.log
@@ -0,0 +1,78 @@ +First Layout: gds/user_project_wrapper_empty_erased.gds +Second Layout: gds/user_project_wrapper_erased.gds +Design Name: user_project_wrapper +Output GDS will be: gds/user_project_wrapper.xor.gds +Reading gds/user_project_wrapper_empty_erased.gds .. +Reading gds/user_project_wrapper_erased.gds .. +--- Running XOR for 235/4 --- +"_input" in: xor.drc:38 +Elapsed: 0.000s +"_input" in: xor.drc:38 +Elapsed: 0.010s +"^" in: xor.drc:38 +Elapsed: 0.000s +XOR differences: 0 +"_output" in: xor.drc:41 +Elapsed: 0.010s +--- Running XOR for 69/20 --- +"_input" in: xor.drc:38 +Elapsed: 0.000s +"_input" in: xor.drc:38 +Elapsed: 0.010s +"^" in: xor.drc:38 +Elapsed: 0.000s +XOR differences: 0 +"_output" in: xor.drc:41 +Elapsed: 0.010s +--- Running XOR for 70/20 --- +"_input" in: xor.drc:38 +Elapsed: 0.000s +"_input" in: xor.drc:38 +Elapsed: 0.000s +"^" in: xor.drc:38 +Elapsed: 0.010s +XOR differences: 0 +"_output" in: xor.drc:41 +Elapsed: 0.000s +--- Running XOR for 71/20 --- +"_input" in: xor.drc:38 +Elapsed: 0.010s +"_input" in: xor.drc:38 +Elapsed: 0.000s +"^" in: xor.drc:38 +Elapsed: 0.000s +XOR differences: 0 +"_output" in: xor.drc:41 +Elapsed: 0.010s +--- Running XOR for 71/44 --- +"_input" in: xor.drc:38 +Elapsed: 0.000s +"_input" in: xor.drc:38 +Elapsed: 0.000s +"^" in: xor.drc:38 +Elapsed: 0.010s +XOR differences: 0 +"_output" in: xor.drc:41 +Elapsed: 0.010s +--- Running XOR for 72/20 --- +"_input" in: xor.drc:38 +Elapsed: 0.000s +"_input" in: xor.drc:38 +Elapsed: 0.000s +"^" in: xor.drc:38 +Elapsed: 0.010s +XOR differences: 0 +"_output" in: xor.drc:41 +Elapsed: 0.010s +--- Running XOR for 81/14 --- +"_input" in: xor.drc:38 +Elapsed: 0.000s +"_input" in: xor.drc:38 +Elapsed: 0.000s +"^" in: xor.drc:38 +Elapsed: 0.010s +XOR differences: 0 +"_output" in: xor.drc:41 +Elapsed: 0.000s +Writing layout file: gds/user_project_wrapper.xor.gds .. +Total run time: 0.130s
diff --git a/utils/erase_box.sh b/utils/erase_box.sh new file mode 100644 index 0000000..41ceb65 --- /dev/null +++ b/utils/erase_box.sh
@@ -0,0 +1,29 @@ +#!/bin/bash + +: ${1?"Usage: $0 file.gds llx lly urx ury"} +: ${2?"Usage: $0 file.gds llx lly urx ury"} +: ${3?"Usage: $0 file.gds llx lly urx ury"} +: ${4?"Usage: $0 file.gds llx lly urx ury"} +: ${5?"Usage: $0 file.gds llx lly urx ury"} +: ${PDK_ROOT?"You need to export PDK_ROOT"} + + +export PDK=sky130A + +export MAGIC_MAGICRC=$PDK_ROOT/$PDK/libs.tech/magic/$PDK.magicrc + +MAGTYPE=mag magic -rcfile $MAGIC_MAGICRC -dnull -noconsole <<EOF +echo $MAGTYPE +tech unlock * +gds read $1 +box $2um $3um $4um $5um +erase +select area +delete +#### REVISE THIS: +select top cell +erase labels +#### +gds write ${1%.*}_erased.gds +EOF +ls ${1%.*}_erased.gds
diff --git a/utils/parse_klayout_xor_log.py b/utils/parse_klayout_xor_log.py new file mode 100644 index 0000000..842b484 --- /dev/null +++ b/utils/parse_klayout_xor_log.py
@@ -0,0 +1,42 @@ +# Copyright 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import re + +parser = argparse.ArgumentParser( + description='extracts the total xor differnces from an xor log') + +parser.add_argument('--log_file', '-l',required=True, + help='log file') + +parser.add_argument('--output', '-o', required=True, + help='output file to store results') + +args = parser.parse_args() +log_file_name = args.log_file +out_file_name = args.output + +string = "XOR differences:" +pattern = re.compile(r'\s*%s\s*([\d+]+)' % string) +tot_cnt = 0 +with open(log_file_name, "r") as f: + for line in f: + m = pattern.match(line) + if m: + tot_cnt += int(m.group(1)) + +outFileOpener = open(out_file_name, "w") +outFileOpener.write("Total XOR differences = "+ str(tot_cnt)) +outFileOpener.close()
diff --git a/utils/scrotLayout.py b/utils/scrotLayout.py new file mode 100644 index 0000000..5469d19 --- /dev/null +++ b/utils/scrotLayout.py
@@ -0,0 +1,58 @@ +# Copyright 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pya +import re +import os + +WIDTH = 2048 +HEIGHT = 2048 + +app = pya.Application.instance() +win = app.main_window() + +# Load technology file +print('[INFO] Reading tech file: ' + str(tech_file)) +tech = pya.Technology() +tech.load(tech_file) + +layoutOptions = tech.load_layout_options + +# Load def file in the main window +print('[INFO] Reading Layout file: ' + str(input_layout)) +cell_view = win.load_layout(input_layout, layoutOptions, 0) +layout_view = cell_view.view() + +layout_view.load_layer_props(os.path.splitext(tech_file)[0]+'.lyp') + +layout_view.max_hier() +# layout_view.clear_layers() + +# Hide layers with these purposes +hidden_purposes = [0, 4, 5] + +li = layout_view.begin_layers() +while not li.at_end(): + lp = li.current() + if lp.source_datatype in hidden_purposes: + new_lp = lp.dup() + new_lp.visible = False + layout_view.set_layer_properties(li, new_lp) + + li.next() + +print("[INFO] Writing out PNG screenshot '{0}'".format(input_layout+".png")) +layout_view.save_image(input_layout+".png", WIDTH, HEIGHT) +print("Done") +app.exit(0)
diff --git a/utils/scrotLayout.sh b/utils/scrotLayout.sh new file mode 100644 index 0000000..d833783 --- /dev/null +++ b/utils/scrotLayout.sh
@@ -0,0 +1,31 @@ +#!/bin/sh +# Copyright 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +: ${1?"Usage: $0 tech_file input"} +: ${2?"Usage: $0 tech_file input"} + +echo "Using Techfile: $1" +echo "Using layout file: $2" + +# The -a here is necessary to handle race conditions. +# This limits the max number of possible jobs to 100. +xvfb-run -a klayout -z \ + -rd input_layout=$2 \ + -rd tech_file=$1 \ + -rm $(dirname $0)/scrotLayout.py + +exit 0
diff --git a/utils/xor.drc b/utils/xor.drc new file mode 100644 index 0000000..6caee91 --- /dev/null +++ b/utils/xor.drc
@@ -0,0 +1,42 @@ +# A general XOR script +# (https://www.klayout.de/forum/discussion/100/xor-vs-diff-tool) +# This script uses KLayout's DRC language to implement a generic +# XOR between two layouts. The name of the layouts is given +# in $a and $b. + +# For layout-to-layout XOR with multiple cores, run this script with +# ./klayout -r xor.drc -rd thr=NUM_CORES -rd top_cell=TOP_CELL_NAME -rd a=a.gds -rd b=b.gds -rd ol=xor.gds -zz +# (replace NUM_CORES by the desired number of cores to utilize + +# enable timing output +verbose + +# set up input a +a = source($a, $top_cell) + +# set up input b +b = source($b, $top_cell) + +$o && $ext != "gds" && report("XOR #{$a} vs. #{$b}", $o) +$ol && $ext == "gds" && target($ol, $co || "XOR") + +$thr && threads($thr) || threads(2) + +# collect all common layers +layers = {} +[ a.layout, b.layout ].each do |ly| + ly.layer_indices.each do |li| + i = ly.get_info(li) + layers[i.to_s] = i + end +end + +# perform the XOR's +layers.keys.sort.each do |l| + i = layers[l] + info("--- Running XOR for #{l} ---") + x = a.input(l) ^ b.input(l) + info("XOR differences: #{x.data.size}") + $o && $ext != "gds" && x.output(l, "XOR results for layer #{l} #{i.name}") + $ol && $ext == "gds" && x.output(i.layer, i.datatype, i.name) +end
diff --git a/utils/xor.sh b/utils/xor.sh new file mode 100644 index 0000000..3ea5176 --- /dev/null +++ b/utils/xor.sh
@@ -0,0 +1,35 @@ +#!/bin/sh +# Copyright 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +: ${1?"Usage: $0 file1.gds file2.gds <top_level_module_name> output.gds|markers.xml"} +: ${2?"Usage: $0 file1.gds file2.gds <top_level_module_name> output.gds|markers.xml"} +: ${3?"Usage: $0 file1.gds file2.gds <top_level_module_name> output.gds|markers.xml"} +: ${4?"Usage: $0 file1.gds file2.gds <top_level_module_name> output.gds|markers.xml"} + + +echo "First Layout: $1" +echo "Second Layout: $2" +echo "Design Name: $3" +echo "Output GDS will be: $4" + +xvfb-run -a klayout -r $(dirname $0)/xor.drc \ + -rd top_cell=$3 \ + -rd a=$1 \ + -rd b=$2 \ + -rd thr=$(nproc) \ + -rd ol=$4 \ + -rd o=$4 \ + -rd ext=${4##*.} \ + -zz