diff --git a/content/about.md b/content/about.md index 5679864..c8f5f84 100644 --- a/content/about.md +++ b/content/about.md @@ -15,7 +15,7 @@ some of the technical documentation however included in my repositories. ### Contact -You can reach me at `lieuwe at leene dot dev`. +You can reach me at `lieuwe at leene dot dev`. ## My Setup @@ -47,5 +47,3 @@ my long term projects which is related to image classification based on structural decomposition rather than textural features. The main idea here is to analyse and extract structure in an image before performing in-depth analysis such that said analysis is most specific to its context. - -![small_sip](/images/sip.gif) diff --git a/content/posts/building-svg.md b/content/posts/building-svg.md index 3b149eb..9ecde47 100644 --- a/content/posts/building-svg.md +++ b/content/posts/building-svg.md @@ -1,5 +1,5 @@ --- -title: "Building With SVG" +title: "Building With SVG 🖼" date: 2021-08-28T11:53:54+02:00 draft: false toc: true @@ -10,19 +10,17 @@ tags: - golang --- -# SVG Tools and Hugo Integration +SVG is generally my image format of choice having used it for illustrations, +chip diagrams, device specifications, and visual outputs generated by code. +SVG is plain text-baesd xml that is structured with some top level +object/properties followed by standardized objects that draw lines and shapes. -SVG is generally the image container of choice having used it for illustrations, -chip or device specifications, and visual outputs generated by code. SVG is -plain xml that is structured with some top level object/properties followed by -standardized objects that draw lines and shapes. -The hope here is that we can call a predefined go procedure that parses -some section of markdown source code and instantiates the corresponding svg file -under our static folder that is then referenced. - -``` go -{{/* a comment */}} -``` +On a few occasions, I have scripted the generation of some SVG illustration +where some parameters are extracted from a database that are then visualized. +These scripts are generally quite simple since you just define some +pre-formatted shapes and place them inside the drawing region. Besides this +I think it useful to highlight some of the automated tools and libraries +that are useful with similar functionality. ## KGT: Kate's Grammar Tool @@ -90,3 +88,59 @@ added directly to KGT as a feature in future releases. The final result is shown below. ![example_kgt.svg](/images/example_kgt.svg) + +## Tabatkins Railroad Diagrams + +On the topic of rail-road diagrams there is also a repository from +[tabatkins](https://github.com/tabatkins/railroad-diagrams) which is a python +based code-base for generating similar SVG diagrams as KGT but without having +to deal with building or running binaries. I prefer monochrome diagrams with +plan formatting so again we are overriding the default style. + +``` python +style = ( '' ++'\tsvg.railroad-diagram {\n\t\tbackground-color:none;\n\t}\n' ++'\tsvg.railroad-diagram path {\n\t\tstroke-width:1.5;\n\t\tstroke:white;\n\t\tfill:rgba(0,0,0,0);\n\t}\n' ++'\tsvg.railroad-diagram text {\n\t\tfont:bold 14px monospace;\n\t\tfill: white;\n\t\ttext-anchor:middle;\n\t}\n' ++'\tsvg.railroad-diagram text.label{\n\t\ttext-anchor:start;\n\t}\n' ++'\tsvg.railroad-diagram text.comment{\n\t\tfont:italic 12px monospace;\n\t}\n' ++'\tsvg.railroad-diagram rect{\n\t\tstroke-width:1.5;\n\t\tstroke:white;\n\t\tfill:none;\n\t}\n' ++'\tsvg.railroad-diagram rect.group-box {\n\t\tstroke: gray;\n\t\tstroke-dasharray: 10 5;\n\t\tfill: none;\n\t}\n' +) +``` + +Styling is best done on a case to case basis with various color-schemes such as +using white text/lines for dark themes. Since this is all handeled in python +the overall interface. Possibly including some kind of command-line utility +here would be quite good but it depends on the final flow for figure generation. +Using the style definition shown above, generating a similar example as before +would look like this: + +``` python +import railroad +with open("./test.svg","w+") as file: + obj = railroad.Diagram("foo", railroad.Choice(0, "bar", "baz"), css=style) + obj.writeSvg(file.write) +``` + +The final result is shown below. + +![example_kgt.svg](/images/example_trd.svg) + +Note that this figure is quite a bit more compact but adding additional labels +or customizations outside the scope of the library will probably require +quite a bit of manual work. This could be a fun side project though. + +## Mermaid CLI + + + +# Hugo Integration + +The hope here is that we can call a predefined go procedure that parses +some section of markdown source code and instantiates the corresponding svg file +under our static folder that is then referenced. + +``` go +{{/* a comment */}} +``` diff --git a/content/posts/calibre.md b/content/posts/calibre.md index a7dda1c..52b9902 100644 --- a/content/posts/calibre.md +++ b/content/posts/calibre.md @@ -1,5 +1,5 @@ --- -title: "Calibre Physical Verification Hacks" +title: "Calibre Physical Verification Hacks 🐛🐛" date: 2021-09-14T11:30:11+02:00 draft: false toc: true @@ -9,42 +9,74 @@ tags: - verification --- -This is a list of 'modifications' to the standard Calibre verification flow I -have used in the past to either modify the checks performed by Calibre or input -data bases. - -# DRC +This page details a variety of 'modifications' to the standard Calibre +verification flow I have used in the past to either modify the checks performed +tools in the physical verification flow. None of which are particularly clean +since they depart from what is usually an approved rule deck / verification +flow. Designs do need to pass the verification process in a meaningful way at +the end of the day so your mileage may vary. ## Extended Device Checks +It is generally good practice to be able to check for internal design +conventions when it comes to layout. Making a custom set of rules that does +exactly this is highly advised to yield better quality designs. For example +it could be required that varactor or mosfet primitives should never have +overlapping shapes with other devices of the same type. The rule below +will check for exactly this and report it as a "NVA0.VAR_OVLP" violation. + ```tvf NVA0.VAR_OVLP { @ Varactors / Tiles should not overlap VARi AND > 1 } ``` +There are other rules that are required or suggested by the DRM that simply +don't have a good DRC rule. For example requiring tear-shaped geometries on +the RDL layer near flip-chip balls. Getting an approximate rule check that +catches the more obvious issues is worthwhile including. + ```tvf -NVA1.Cu_PPI.TEAR { @ Shape of Cu_PP I pad (under PM2 area): tear shape required - X0 = EXT Cu_PPIi <1 ABUT <125 INTERSECTING ONLY REGION - X1 = EXT Cu_PPIi <1 ABUT <180 INTERSECTING ONLY REGION - X2 = INT Cu_PPIi <1 ABUT <180 INTERSECTING ONLY REGION +NVA0.RDL.TEAR { @ Shape of RDL near pad: tear shape required + X0 = EXT RDL <1 ABUT <125 INTERSECTING ONLY REGION + X1 = EXT RDL <1 ABUT <180 INTERSECTING ONLY REGION + X2 = INT RDL <1 ABUT <180 INTERSECTING ONLY REGION X3 = EXPAND EDGE (X1 NOT TOUCH INSIDE EDGE X0) BY 1 EXTEND BY 50 X4 = EXPAND EDGE (X2 NOT TOUCH INSIDE EDGE X0) BY 1 EXTEND BY 50 (X3 AND X0) OR (X4 AND X0) } ``` +The above rule finds regions with acute angles (internal and external) +near regions with obtuse angles where the latter is generally the rounded +RDL landing pad for the ball. ## Layer / Device Aliasing +Layer aliasing or remapping is another way to add indirection to the DRC rule +deck that will allow you to both run your own checks and device recognition +without interfering with the standard flow. + ```tvf LAYER MAP 107 DATATYPE 0 746 ``` -# LVS +In the above scenario we allocated an additional layer in the Cadence design +to designate inductor recognition beside the standard inductors. This was +required since the standard inductors also implied metallization free regions +which is not always be acceptable. By adding this layer and mapping it to +the same inductor recognition data type during LVS these inductors would still +be recognized but did not trigger the associated metallization rules during DRC. ## Adding New Device Primitives +Another good know how is the process behind device recognition when you run +the Calibre LVS process. The code snippets below take us through a process of +defining a new device for LVS recognition that is bound together with a spice +definition to produce the extracted netlist. This should allow you to define +custom layers and define custom devices on those layers while still getting +LVS clean at the end of the day. This example will define a custom resistor. + ```tvf LAYER RESLYR 450 LAYER MAP 215 DATATYPE 21 450 // layer to form memresistor @@ -54,10 +86,18 @@ CONNECT metal4 MEMRESLYRT DEVICE XDEVICE XCDTR XTERM(PORT1) XTERM(PORT2) netlist model xdevice ``` -```spice -.SUBCKT xdevice PORT1 PORT2 -.ENDS -``` +The section of code above are LVS rule statements that first define a named +layer `RESLYR` and then map a data type onto that layer. The data type should +correspond to what ever you new layer you used to define the device in the +layout editor. Then we define the terminals of this device when ever this layer +overlaps and connects with metal 4 otherwise it is the resistive section. +Finally you specify a device in terms of the relevant layers and how they map +to the actual model. + +Notice the device maps to a netlist model called `xdevice` with named ports. +This model is defined below. Note that we haven´t extracted any parameters +but this could be done in the rule deck definition. Also note that here +we also specify the mapping of this `xdevice` to a cell in the design library. ```lisp (xdevice @@ -73,8 +113,24 @@ DEVICE XDEVICE XCDTR XTERM(PORT1) XTERM(PORT2) netlist model xdevice ) ``` +Finally a spice definition must also be included in order to run the netlist +comparison. Assuming the cell in the design library correctly netlists with a +auCDL view. The spice definition below presumes both the layout and schematic +perform black-boxed comparison of this new resistor. + +```spice +.SUBCKT xdevice PORT1 PORT2 +.ENDS +``` + ## Extending Connectivity Layers +In some occasions it could be that certain extra layers are defined in the DRC +deck but not in the LVS deck. For example there are optional metallization +layers for your process. Adding connectivity is rather strait forward. +The main challenge here is to choose the correct data type mappings as to +avoid conflicts with the original rule statements. + ```tvf LAYER PM1i 5001 LAYER MAP 5 DATATYPE 1 5001 @@ -88,6 +144,15 @@ VIA8 = COPY CB2 metal9 = COPY Cu_PPIi VIA9 = COPY PM2i metal10 = COPY UBM +``` + +Once these layers are defined we can go ahead and specify the order of +connectivity. Notice that we can´t directly operate / manipulate layer +definitions so simply running a `COPY` statement resolves this. Below we +see also that adding ports and text labels connectivity for the relevant +layers is also needed for your pins to connect. + +``` tvf CONNECT metal9 metal8 BY VIA8 CONNECT metal10 metal9 BY VIA9 TEXT LAYER 140 ATTACH 140 metal9 @@ -100,70 +165,14 @@ PORT LAYER TEXT 125 ## Hot fixing LVS comparison +Finally the rule statements below are global deck adjustments. They are +for the most part self explanatory except for `CULL` which actually +removes empty spice sub-circuits that are identified by a hierarchical LVS run +but does not actually contain active devices (i.e. a dummy digital filler cell). + ```tvf LVS SPICE CULL PRIMITIVE SUBCIRCUITS YES VIRTUAL CONNECT NAME "POWER" -TEXT "POWER" LOCX LOCY DATATYPE +TEXT "NET_NAME" LOCX LOCY DATATYPE LAYOUT RENAME TEXT "/DATA\\[(.*)\\]/DATA<-1>/M-" ``` - - - -# SPICE - -## Port Order Reshuffling - -```bash -function getSortedOrder() { - local SOURCE="" - local SORTED="" - read -a SOURCE <<< "$1" - SORTED="${SOURCE[@]}" - if [ -z "${SORTED//*\[*}" ] ; then - SORTED=($(echo "${SOURCE[@]:2}" | tr " " "\n" | sed -r "s/\[([0-9]+)\]/ \1 /g" \ - | sort -k 1,1 -k2,2nr | sed -r "s/ ([0-9]+) /\[\1\]/g" )) - else - SORTED=($(echo "${SOURCE[@]:2}" | tr " " "\n" | sed -r "s/<([0-9]+)>/ \1 /g" \ - | sort -k 1,1 -k2,2nr | sed -r "s/ ([0-9]+) /<\1>/g" )) - fi - echo "${SOURCE[@]:0:2} ${SORTED[@]}" -} -function updatePortOrder() { - local TARGET="$1" - local CDL_FILE="$2" - local PORTORDER="$(awk -v target="subckt ${TARGET} " -f "catch.awk" "$CDL_FILE")" - local PORTREF=$(getSortedOrder "$PORTORDER") - local SWPDELIMITER="" - echo $TARGET - if [ -z "${PORTREF//*\[*}" ] ; then SWPDELIMITER="TRUE" ; fi - awk -v target="subckt ${TARGET} " -v release="$PORTREF" -v swpdelim="$SWPDELIMITER" \ - -f "release.awk" "$CDL_FILE" > "${TARGET}.cdl" - [ ! -z "$(grep -m 1 "\[" "${TARGET}.cdl")" ] && [ ! -z "$(grep -m 1 "<" "${TARGET}.cdl")" ] \ - && echo "Error $CDL_FILE uses mixed delimiters" -} -``` - -```awk -BEGIN{ hold = ""; IGNORECASE = 1 } -NF { - if( $1 == "+" && hold != "") - { for(i=2;i<=NF;i++) hold=hold " " $i } - else if( hold != "") { print hold; hold=""; exit } - }; -$0 ~ target { hold = $0 }; -``` - -```awk -BEGIN{output="";hold="";IGNORECASE=1}; -NF{if($1!="+")hold=""} -$0~target{ - hold=$0 - n=split(release,ports," ") - for(i=n;i>0;i--){ - if(swpdelim!=""){ - gsub("<","[",ports[i]) - gsub(">","]",ports[i])} - output=ports[i]" "output} - print output} -NF{if(hold=="")print $0} -``` diff --git a/content/posts/pyside.md b/content/posts/pyside.md index a5e565a..738dc30 100644 --- a/content/posts/pyside.md +++ b/content/posts/pyside.md @@ -1,5 +1,5 @@ --- -title: "Binding QML with Python: PyViewer" +title: "Binding QML with Python: PyViewer 👾" date: 2021-08-29T12:53:19+02:00 draft: false toc: true diff --git a/content/posts/spice-monkey.md b/content/posts/spice-monkey.md new file mode 100644 index 0000000..577b189 --- /dev/null +++ b/content/posts/spice-monkey.md @@ -0,0 +1,69 @@ +--- +title: "Spice Monkey 💻🐒" +date: 2021-10-29T18:54:32+02:00 +draft: false +toc: false +images: +tags: + - spice + - code + - verification +--- + + +## Port Order Reshuffling + +```bash +function getSortedOrder() { + local SOURCE="" + local SORTED="" + read -a SOURCE <<< "$1" + SORTED="${SOURCE[@]}" + if [ -z "${SORTED//*\[*}" ] ; then + SORTED=($(echo "${SOURCE[@]:2}" | tr " " "\n" | sed -r "s/\[([0-9]+)\]/ \1 /g" \ + | sort -k 1,1 -k2,2nr | sed -r "s/ ([0-9]+) /\[\1\]/g" )) + else + SORTED=($(echo "${SOURCE[@]:2}" | tr " " "\n" | sed -r "s/<([0-9]+)>/ \1 /g" \ + | sort -k 1,1 -k2,2nr | sed -r "s/ ([0-9]+) /<\1>/g" )) + fi + echo "${SOURCE[@]:0:2} ${SORTED[@]}" +} +function updatePortOrder() { + local TARGET="$1" + local CDL_FILE="$2" + local PORTORDER="$(awk -v target="subckt ${TARGET} " -f "catch.awk" "$CDL_FILE")" + local PORTREF=$(getSortedOrder "$PORTORDER") + local SWPDELIMITER="" + echo $TARGET + if [ -z "${PORTREF//*\[*}" ] ; then SWPDELIMITER="TRUE" ; fi + awk -v target="subckt ${TARGET} " -v release="$PORTREF" -v swpdelim="$SWPDELIMITER" \ + -f "release.awk" "$CDL_FILE" > "${TARGET}.cdl" + [ ! -z "$(grep -m 1 "\[" "${TARGET}.cdl")" ] && [ ! -z "$(grep -m 1 "<" "${TARGET}.cdl")" ] \ + && echo "Error $CDL_FILE uses mixed delimiters" +} +``` + +```awk +BEGIN{ hold = ""; IGNORECASE = 1 } +NF { + if( $1 == "+" && hold != "") + { for(i=2;i<=NF;i++) hold=hold " " $i } + else if( hold != "") { print hold; hold=""; exit } + }; +$0 ~ target { hold = $0 }; +``` + +```awk +BEGIN{output="";hold="";IGNORECASE=1}; +NF{if($1!="+")hold=""} +$0~target{ + hold=$0 + n=split(release,ports," ") + for(i=n;i>0;i--){ + if(swpdelim!=""){ + gsub("<","[",ports[i]) + gsub(">","]",ports[i])} + output=ports[i]" "output} + print output} +NF{if(hold=="")print $0} +``` diff --git a/static/images/example_trd.svg b/static/images/example_trd.svg new file mode 100644 index 0000000..3baa8f6 --- /dev/null +++ b/static/images/example_trd.svg @@ -0,0 +1,40 @@ + + + + +foo + +bar +baz \ No newline at end of file diff --git a/static/images/sip.gif b/static/images/sip.gif deleted file mode 100644 index 3dc107c..0000000 Binary files a/static/images/sip.gif and /dev/null differ