mirror of
				https://github.com/lleene/hugo-site.git
				synced 2025-10-31 03:09:03 +01:00 
			
		
		
		
	Content update Oct.
This commit is contained in:
		| @ -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. | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -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. | ||||
|  | ||||
|  | ||||
|  | ||||
| ## 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. | ||||
|  | ||||
|  | ||||
|  | ||||
| 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 */}} | ||||
| ``` | ||||
|  | ||||
| @ -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} | ||||
| ``` | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
							
								
								
									
										69
									
								
								content/posts/spice-monkey.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								content/posts/spice-monkey.md
									
									
									
									
									
										Normal file
									
								
							| @ -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} | ||||
| ``` | ||||
							
								
								
									
										40
									
								
								static/images/example_trd.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								static/images/example_trd.svg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| <svg class="railroad-diagram" height="92" viewBox="0 0 231.0 92" width="231.0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | ||||
| <g transform="translate(.5 .5)"> | ||||
| <style>/* <![CDATA[ */ | ||||
| 	svg.railroad-diagram { | ||||
| 		background-color:none; | ||||
| 	} | ||||
| 	svg.railroad-diagram path { | ||||
| 		stroke-width:1.5; | ||||
| 		stroke:white; | ||||
| 		fill:rgba(0,0,0,0); | ||||
| 	} | ||||
| 	svg.railroad-diagram text { | ||||
| 		font:bold 14px monospace; | ||||
| 		fill: white; | ||||
| 		text-anchor:middle; | ||||
| 	} | ||||
| 	svg.railroad-diagram text.label{ | ||||
| 		text-anchor:start; | ||||
| 	} | ||||
| 	svg.railroad-diagram text.comment{ | ||||
| 		font:italic 12px monospace; | ||||
| 	} | ||||
| 	svg.railroad-diagram rect{ | ||||
| 		stroke-width:1.5; | ||||
| 		stroke:white; | ||||
| 		fill:none; | ||||
| 	} | ||||
| 	svg.railroad-diagram rect.group-box { | ||||
| 		stroke: gray; | ||||
| 		stroke-dasharray: 10 5; | ||||
| 		fill: none; | ||||
| 	} | ||||
|  | ||||
| /* ]]> */ | ||||
| </style><g> | ||||
| <path d="M20 21v20m10 -20v20m-10 -10h20"></path></g><path d="M40 31h10"></path><g class="terminal "> | ||||
| <path d="M50 31h0.0"></path><path d="M95.5 31h0.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="50.0" y="20"></rect><text x="72.75" y="35">foo</text></g><path d="M95.5 31h10"></path><g> | ||||
| <path d="M105.5 31h0.0"></path><path d="M191.0 31h0.0"></path><path d="M105.5 31h20"></path><g class="terminal "> | ||||
| <path d="M125.5 31h0.0"></path><path d="M171.0 31h0.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="125.5" y="20"></rect><text x="148.25" y="35">bar</text></g><path d="M171.0 31h20"></path><path d="M105.5 31a10 10 0 0 1 10 10v10a10 10 0 0 0 10 10"></path><g class="terminal "> | ||||
| <path d="M125.5 61h0.0"></path><path d="M171.0 61h0.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="125.5" y="50"></rect><text x="148.25" y="65">baz</text></g><path d="M171.0 61a10 10 0 0 0 10 -10v-10a10 10 0 0 1 10 -10"></path></g><path d="M 191.0 31 h 20 m -10 -10 v 20 m 10 -20 v 20"></path></g></svg> | ||||
| After Width: | Height: | Size: 1.8 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 2.7 MiB | 
		Reference in New Issue
	
	Block a user