mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' into stable
This commit is contained in:
commit
9d438d9181
10
README.md
10
README.md
|
|
@ -1,12 +1,9 @@
|
|||

|
||||
# OpenRAM
|
||||
|
||||
[](https://www.python.org/)
|
||||
[](./LICENSE)
|
||||
|
||||
Master:
|
||||
[](https://github.com/VLSIDA/OpenRAM/archive/master.zip)
|
||||
|
||||
Dev:
|
||||
[](https://github.com/VLSIDA/OpenRAM/archive/stable.zip)
|
||||
[](https://github.com/VLSIDA/OpenRAM/archive/dev.zip)
|
||||
|
||||
An open-source static random access memory (SRAM) compiler.
|
||||
|
|
@ -34,8 +31,7 @@ things that need to be fixed.
|
|||
The OpenRAM compiler has very few dependencies:
|
||||
+ [Ngspice] 26 (or later) or HSpice I-2013.12-1 (or later) or CustomSim 2017 (or later)
|
||||
+ Python 3.5 or higher
|
||||
+ Python numpy (pip3 install numpy to install)
|
||||
+ Python scipy (pip3 install scipy to install)
|
||||
+ Various Python packages (pip install -r requirements.txt)
|
||||
|
||||
If you want to perform DRC and LVS, you will need either:
|
||||
+ Calibre (for [FreePDK45])
|
||||
|
|
|
|||
|
|
@ -123,6 +123,14 @@ class _wordline_driver:
|
|||
self.vertical_supply = vertical_supply
|
||||
|
||||
|
||||
class _bitcell_array:
|
||||
def __init__(self,
|
||||
wordline_layer,
|
||||
wordline_pitch_factor=2):
|
||||
self.wordline_layer = wordline_layer
|
||||
self.wordline_pitch_factor = wordline_pitch_factor
|
||||
|
||||
|
||||
class layer_properties():
|
||||
"""
|
||||
This contains meta information about the module routing layers. These
|
||||
|
|
@ -159,6 +167,10 @@ class layer_properties():
|
|||
|
||||
self._wordline_driver = _wordline_driver(vertical_supply=False)
|
||||
|
||||
self._local_bitcell_array = _bitcell_array(wordline_layer="m2")
|
||||
|
||||
self._global_bitcell_array = _bitcell_array(wordline_layer="m3")
|
||||
|
||||
@property
|
||||
def bank(self):
|
||||
return self._bank
|
||||
|
|
@ -191,3 +203,11 @@ class layer_properties():
|
|||
def wordline_driver(self):
|
||||
return self._wordline_driver
|
||||
|
||||
@property
|
||||
def global_bitcell_array(self):
|
||||
return self._global_bitcell_array
|
||||
|
||||
@property
|
||||
def local_bitcell_array(self):
|
||||
return self._local_bitcell_array
|
||||
|
||||
|
|
|
|||
|
|
@ -674,7 +674,8 @@ class layout():
|
|||
directions=None,
|
||||
size=[1, 1],
|
||||
implant_type=None,
|
||||
well_type=None):
|
||||
well_type=None,
|
||||
min_area=False):
|
||||
"""
|
||||
Punch a stack of vias from a start layer to a target layer by the center.
|
||||
"""
|
||||
|
|
@ -708,7 +709,7 @@ class layout():
|
|||
implant_type=implant_type,
|
||||
well_type=well_type)
|
||||
|
||||
if cur_layer != from_layer:
|
||||
if cur_layer != from_layer or min_area:
|
||||
self.add_min_area_rect_center(cur_layer,
|
||||
offset,
|
||||
via.mod.first_layer_width,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ from tech import layer_names
|
|||
import os
|
||||
import shutil
|
||||
from globals import OPTS
|
||||
from vector import vector
|
||||
from pin_layout import pin_layout
|
||||
|
||||
|
||||
class lef:
|
||||
|
|
@ -68,13 +70,63 @@ class lef:
|
|||
def lef_write(self, lef_name):
|
||||
""" Write the entire lef of the object to the file. """
|
||||
|
||||
if OPTS.drc_exe and OPTS.drc_exe[0] == "magic":
|
||||
self.magic_lef_write(lef_name)
|
||||
return
|
||||
if OPTS.detailed_lef:
|
||||
debug.info(3, "Writing detailed LEF to {0}".format(lef_name))
|
||||
self.detailed_lef_write(lef_name)
|
||||
else:
|
||||
debug.info(3, "Writing abstract LEF to {0}".format(lef_name))
|
||||
# Can possibly use magic lef write to create the LEF
|
||||
# if OPTS.drc_exe and OPTS.drc_exe[0] == "magic":
|
||||
# self.magic_lef_write(lef_name)
|
||||
# return
|
||||
self.abstract_lef_write(lef_name)
|
||||
|
||||
debug.info(3, "Writing detailed LEF to {0}".format(lef_name))
|
||||
def abstract_lef_write(self, lef_name):
|
||||
# To maintain the indent level easily
|
||||
self.indent = ""
|
||||
|
||||
self.indent = "" # To maintain the indent level easily
|
||||
self.lef = open(lef_name, "w")
|
||||
self.lef_write_header()
|
||||
|
||||
# Start with blockages on all layers the size of the block
|
||||
# minus the pin escape margin (hard coded to 4 x m3 pitch)
|
||||
# These are a pin_layout to use their geometric functions
|
||||
perimeter_margin = self.m3_pitch
|
||||
self.blockages = {}
|
||||
for layer_name in self.lef_layers:
|
||||
self.blockages[layer_name]=[]
|
||||
for layer_name in self.lef_layers:
|
||||
ll = vector(perimeter_margin, perimeter_margin)
|
||||
ur = vector(self.width - perimeter_margin, self.height - perimeter_margin)
|
||||
self.blockages[layer_name].append(pin_layout("",
|
||||
[ll, ur],
|
||||
layer_name))
|
||||
|
||||
# For each pin, remove the blockage and add the pin
|
||||
for pin_name in self.pins:
|
||||
pin = self.get_pin(pin_name)
|
||||
inflated_pin = pin.inflated_pin(multiple=1)
|
||||
for blockage in self.blockages[pin.layer]:
|
||||
if blockage.overlaps(inflated_pin):
|
||||
intersection_shape = blockage.intersection(inflated_pin)
|
||||
# If it is zero area, don't add the pin
|
||||
if intersection_shape[0][0]==intersection_shape[1][0] or intersection_shape[0][1]==intersection_shape[1][1]:
|
||||
continue
|
||||
# Remove the old blockage and add the new ones
|
||||
self.blockages[pin.layer].remove(blockage)
|
||||
intersection_pin = pin_layout("", intersection_shape, inflated_pin.layer)
|
||||
new_blockages = blockage.cut(intersection_pin)
|
||||
self.blockages[pin.layer].extend(new_blockages)
|
||||
|
||||
self.lef_write_pin(pin_name)
|
||||
|
||||
self.lef_write_obstructions(abstracted=True)
|
||||
self.lef_write_footer()
|
||||
self.lef.close()
|
||||
|
||||
def detailed_lef_write(self, lef_name):
|
||||
# To maintain the indent level easily
|
||||
self.indent = ""
|
||||
|
||||
self.lef = open(lef_name, "w")
|
||||
self.lef_write_header()
|
||||
|
|
@ -136,24 +188,29 @@ class lef:
|
|||
self.indent = self.indent[:-3]
|
||||
self.lef.write("{0}END {1}\n".format(self.indent, name))
|
||||
|
||||
def lef_write_obstructions(self):
|
||||
def lef_write_obstructions(self, abstracted=False):
|
||||
""" Write all the obstructions on each layer """
|
||||
self.lef.write("{0}OBS\n".format(self.indent))
|
||||
for layer in self.lef_layers:
|
||||
self.lef.write("{0}LAYER {1} ;\n".format(self.indent, layer_names[layer]))
|
||||
self.indent += " "
|
||||
blockages = self.get_blockages(layer, True)
|
||||
for b in blockages:
|
||||
self.lef_write_shape(b)
|
||||
if abstracted:
|
||||
blockages = self.blockages[layer]
|
||||
for b in blockages:
|
||||
self.lef_write_shape(b.rect)
|
||||
else:
|
||||
blockages = self.get_blockages(layer, True)
|
||||
for b in blockages:
|
||||
self.lef_write_shape(b)
|
||||
self.indent = self.indent[:-3]
|
||||
self.lef.write("{0}END\n".format(self.indent))
|
||||
|
||||
def lef_write_shape(self, rect):
|
||||
if len(rect) == 2:
|
||||
def lef_write_shape(self, obj):
|
||||
if len(obj) == 2:
|
||||
""" Write a LEF rectangle """
|
||||
self.lef.write("{0}RECT ".format(self.indent))
|
||||
for item in rect:
|
||||
# print(rect)
|
||||
for item in obj:
|
||||
# print(obj)
|
||||
self.lef.write(" {0} {1}".format(round(item[0],
|
||||
self.round_grid),
|
||||
round(item[1],
|
||||
|
|
@ -162,12 +219,10 @@ class lef:
|
|||
else:
|
||||
""" Write a LEF polygon """
|
||||
self.lef.write("{0}POLYGON ".format(self.indent))
|
||||
for item in rect:
|
||||
for item in obj:
|
||||
self.lef.write(" {0} {1}".format(round(item[0],
|
||||
self.round_grid),
|
||||
round(item[1],
|
||||
self.round_grid)))
|
||||
# for i in range(0,len(rect)):
|
||||
# self.lef.write(" {0} {1}".format(round(rect[i][0],self.round_grid), round(rect[i][1],self.round_grid)))
|
||||
self.lef.write(" ;\n")
|
||||
|
||||
|
|
|
|||
|
|
@ -139,13 +139,13 @@ class pin_layout:
|
|||
min_area = drc("{}_minarea".format(self.layer))
|
||||
pass
|
||||
|
||||
def inflate(self, spacing=None):
|
||||
def inflate(self, spacing=None, multiple=0.5):
|
||||
"""
|
||||
Inflate the rectangle by the spacing (or other rule)
|
||||
and return the new rectangle.
|
||||
"""
|
||||
if not spacing:
|
||||
spacing = 0.5*drc("{0}_to_{0}".format(self.layer))
|
||||
spacing = multiple*drc("{0}_to_{0}".format(self.layer))
|
||||
|
||||
(ll, ur) = self.rect
|
||||
spacing = vector(spacing, spacing)
|
||||
|
|
@ -154,15 +154,23 @@ class pin_layout:
|
|||
|
||||
return (newll, newur)
|
||||
|
||||
def inflated_pin(self, spacing=None, multiple=0.5):
|
||||
"""
|
||||
Inflate the rectangle by the spacing (or other rule)
|
||||
and return the new rectangle.
|
||||
"""
|
||||
inflated_area = self.inflate(spacing, multiple)
|
||||
return pin_layout(self.name, inflated_area, self.layer)
|
||||
|
||||
def intersection(self, other):
|
||||
""" Check if a shape overlaps with a rectangle """
|
||||
(ll, ur) = self.rect
|
||||
(oll, our) = other.rect
|
||||
|
||||
min_x = max(ll.x, oll.x)
|
||||
max_x = min(ll.x, oll.x)
|
||||
max_x = min(ur.x, our.x)
|
||||
min_y = max(ll.y, oll.y)
|
||||
max_y = min(ll.y, oll.y)
|
||||
max_y = min(ur.y, our.y)
|
||||
|
||||
return [vector(min_x, min_y), vector(max_x, max_y)]
|
||||
|
||||
|
|
@ -578,6 +586,30 @@ class pin_layout:
|
|||
|
||||
return None
|
||||
|
||||
def cut(self, shape):
|
||||
"""
|
||||
Return a set of shapes that are this shape minus the argument shape.
|
||||
"""
|
||||
# Make the unique coordinates in X and Y directions
|
||||
x_offsets = sorted([self.lx(), self.rx(), shape.lx(), shape.rx()])
|
||||
y_offsets = sorted([self.by(), self.uy(), shape.by(), shape.uy()])
|
||||
|
||||
new_shapes = []
|
||||
# Create all of the shapes
|
||||
for x1, x2 in zip(x_offsets[0:], x_offsets[1:]):
|
||||
if x1==x2:
|
||||
continue
|
||||
for y1, y2 in zip(y_offsets[0:], y_offsets[1:]):
|
||||
if y1==y2:
|
||||
continue
|
||||
new_shape = pin_layout("", [vector(x1, y1), vector(x2, y2)], self.lpp)
|
||||
# Don't add the existing shape in if it overlaps the pin shape
|
||||
if new_shape.contains(shape):
|
||||
continue
|
||||
new_shapes.append(new_shape)
|
||||
|
||||
return new_shapes
|
||||
|
||||
def same_lpp(self, lpp1, lpp2):
|
||||
"""
|
||||
Check if the layers and purposes are the same.
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from sram_factory import factory
|
|||
from vector import vector
|
||||
import debug
|
||||
from numpy import cumsum
|
||||
from tech import layer_properties as layer_props
|
||||
|
||||
|
||||
class global_bitcell_array(bitcell_base_array.bitcell_base_array):
|
||||
|
|
@ -223,11 +224,20 @@ class global_bitcell_array(bitcell_base_array.bitcell_base_array):
|
|||
new_name = "{0}_{1}".format(base_name, col + col_value)
|
||||
self.copy_layout_pin(inst, pin_name, new_name)
|
||||
|
||||
# Add the global word lines
|
||||
wl_layer = layer_props.global_bitcell_array.wordline_layer
|
||||
|
||||
for wl_name in self.local_mods[0].get_inputs():
|
||||
for local_inst in self.local_insts:
|
||||
wl_pin = local_inst.get_pin(wl_name)
|
||||
self.add_via_stack_center(from_layer=wl_pin.layer,
|
||||
to_layer=wl_layer,
|
||||
offset=wl_pin.center())
|
||||
|
||||
left_pin = self.local_insts[0].get_pin(wl_name)
|
||||
right_pin = self.local_insts[-1].get_pin(wl_name)
|
||||
self.add_layout_pin_segment_center(text=wl_name,
|
||||
layer=left_pin.layer,
|
||||
layer=wl_layer,
|
||||
start=left_pin.lc(),
|
||||
end=right_pin.rc())
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from globals import OPTS
|
|||
from sram_factory import factory
|
||||
from vector import vector
|
||||
import debug
|
||||
from tech import layer_properties as layer_props
|
||||
|
||||
|
||||
class local_bitcell_array(bitcell_base_array.bitcell_base_array):
|
||||
|
|
@ -190,6 +191,11 @@ class local_bitcell_array(bitcell_base_array.bitcell_base_array):
|
|||
|
||||
def route(self):
|
||||
|
||||
global_wl_layer = layer_props.global_bitcell_array.wordline_layer
|
||||
global_wl_pitch = getattr(self, "{}_pitch".format(global_wl_layer))
|
||||
global_wl_pitch_factor = layer_props.global_bitcell_array.wordline_pitch_factor
|
||||
local_wl_layer = layer_props.local_bitcell_array.wordline_layer
|
||||
|
||||
# Route the global wordlines
|
||||
for port in self.all_ports:
|
||||
if port == 0:
|
||||
|
|
@ -204,25 +210,27 @@ class local_bitcell_array(bitcell_base_array.bitcell_base_array):
|
|||
in_pin = self.wl_insts[port].get_pin(in_pin_name)
|
||||
|
||||
y_offset = in_pin.cy()
|
||||
|
||||
if port == 0:
|
||||
y_offset -= 2 * self.m3_pitch
|
||||
y_offset -= global_wl_pitch_factor * global_wl_pitch
|
||||
else:
|
||||
y_offset += 2 * self.m3_pitch
|
||||
|
||||
self.add_layout_pin_segment_center(text=wl_name,
|
||||
layer="m3",
|
||||
start=vector(self.wl_insts[port].lx(), y_offset),
|
||||
end=vector(self.wl_insts[port].lx() + self.wl_array.width, y_offset))
|
||||
|
||||
y_offset += global_wl_pitch_factor * global_wl_pitch
|
||||
mid = vector(in_pin.cx(), y_offset)
|
||||
self.add_path("m2", [in_pin.center(), mid])
|
||||
|
||||
# A short jog to the global line
|
||||
self.add_via_stack_center(from_layer=in_pin.layer,
|
||||
to_layer="m2",
|
||||
offset=in_pin.center())
|
||||
self.add_via_center(self.m2_stack,
|
||||
offset=mid)
|
||||
|
||||
to_layer=local_wl_layer,
|
||||
offset=in_pin.center(),
|
||||
min_area=True)
|
||||
self.add_path(local_wl_layer, [in_pin.center(), mid])
|
||||
self.add_via_stack_center(from_layer=local_wl_layer,
|
||||
to_layer=global_wl_layer,
|
||||
offset=mid,
|
||||
min_area=True)
|
||||
# Add the global WL pin
|
||||
self.add_layout_pin_rect_center(text=wl_name,
|
||||
layer=global_wl_layer,
|
||||
offset=mid)
|
||||
# Route the buffers
|
||||
for port in self.all_ports:
|
||||
driver_outputs = self.driver_wordline_outputs[port]
|
||||
|
|
|
|||
|
|
@ -153,6 +153,9 @@ class options(optparse.Values):
|
|||
# Route the input/output pins to the perimeter
|
||||
perimeter_pins = True
|
||||
|
||||
# Detailed or abstract LEF view
|
||||
detailed_lef = False
|
||||
|
||||
keep_temp = False
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -263,13 +263,18 @@ class sram_base(design, verilog, lef):
|
|||
|
||||
# Add it as an IO pin to the perimeter
|
||||
lowest_coord = self.find_lowest_coords()
|
||||
pin_width = pin.rx() - lowest_coord.x
|
||||
route_width = pin.rx() - lowest_coord.x
|
||||
pin_width = 2 * getattr(self, "{}_width".format(pin.layer))
|
||||
pin_offset = vector(lowest_coord.x, pin.by())
|
||||
self.add_layout_pin(pin_name,
|
||||
pin.layer,
|
||||
pin_offset,
|
||||
pin_width,
|
||||
pin.height())
|
||||
self.add_rect(pin.layer,
|
||||
pin_offset,
|
||||
route_width,
|
||||
pin.height())
|
||||
|
||||
def route_escape_pins(self):
|
||||
"""
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
|
|
@ -0,0 +1,236 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="605.40302"
|
||||
height="165.26472"
|
||||
viewBox="0 0 605.40301 165.26473"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
sodipodi:docname="OpenRAM_logo_yellow_transparent.svg"
|
||||
inkscape:export-filename="/home/mrg/openram/images/OpenRAM_logo_yellow_transparent.png"
|
||||
inkscape:export-xdpi="150"
|
||||
inkscape:export-ydpi="150">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="2634"
|
||||
inkscape:window-height="1333"
|
||||
id="namedview3551"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.8592481"
|
||||
inkscape:cx="232.75305"
|
||||
inkscape:cy="82.632362"
|
||||
inkscape:window-x="208"
|
||||
inkscape:window-y="96"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg2"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<defs
|
||||
id="defs4" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<text
|
||||
id="text3336"
|
||||
y="113.18625"
|
||||
x="173.17645"
|
||||
style="font-style:normal;font-weight:normal;font-size:22.5px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#003c6c;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4140"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:80px;font-family:Futura;-inkscape-font-specification:'Futura Bold';fill:#003c6c;fill-opacity:1"
|
||||
y="113.18625"
|
||||
x="173.17645">OpenRAM</tspan></text>
|
||||
<rect
|
||||
y="39.336884"
|
||||
x="36.581963"
|
||||
height="87.463478"
|
||||
width="89.973282"
|
||||
id="rect4144"
|
||||
style="fill:#003c6c;fill-opacity:1;stroke:#003c6c;stroke-width:8.3992691;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
id="path8080"
|
||||
d="m 53.960768,13.421563 v 21.96078"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#003c6c;stroke-width:3.69754982;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#003c6c;stroke-width:3.69754982;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 81.568617,13.421563 v 21.96078"
|
||||
id="path8112"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path8118"
|
||||
d="m 109.17646,13.421563 v 21.96078"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#003c6c;stroke-width:3.69754982;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#003c6c;stroke-width:3.69754982;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 53.960768,151.84317 V 129.88239"
|
||||
id="path8137"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path8143"
|
||||
d="M 81.568617,151.84317 V 129.88239"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#003c6c;stroke-width:3.69754982;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#003c6c;stroke-width:3.69754982;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 109.17646,151.84317 V 129.88239"
|
||||
id="path8149"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#003c6c;stroke-width:3.69754982;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 151.21568,56.715693 H 129.2549"
|
||||
id="path8157"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path8163"
|
||||
d="M 151.21568,84.323543 H 129.2549"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#003c6c;stroke-width:3.69754982;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#003c6c;stroke-width:3.69754982;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 151.21568,111.93138 H 129.2549"
|
||||
id="path8169"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path8177"
|
||||
d="m 13.421548,56.715693 h 21.96078"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#003c6c;stroke-width:3.69754982;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#003c6c;stroke-width:3.69754982;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 13.421548,84.323543 h 21.96078"
|
||||
id="path8183"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path8189"
|
||||
d="m 13.421548,111.93138 h 21.96078"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#003c6c;stroke-width:3.69754982;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<ellipse
|
||||
ry="5.9607844"
|
||||
rx="5.647059"
|
||||
cy="7.4607844"
|
||||
cx="53.96077"
|
||||
id="path8078"
|
||||
style="fill:#003c6c;fill-opacity:1;stroke:#003c6c;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<ellipse
|
||||
style="fill:#003c6c;fill-opacity:1;stroke:#003c6c;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse8110"
|
||||
cx="81.568619"
|
||||
cy="7.4607844"
|
||||
rx="5.647059"
|
||||
ry="5.9607844" />
|
||||
<ellipse
|
||||
ry="5.9607844"
|
||||
rx="5.647059"
|
||||
cy="7.4607844"
|
||||
cx="109.17645"
|
||||
id="ellipse8116"
|
||||
style="fill:#003c6c;fill-opacity:1;stroke:#003c6c;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<ellipse
|
||||
transform="scale(1,-1)"
|
||||
style="fill:#003c6c;fill-opacity:1;stroke:#003c6c;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse8135"
|
||||
cx="53.96077"
|
||||
cy="-157.80394"
|
||||
rx="5.647059"
|
||||
ry="5.9607844" />
|
||||
<ellipse
|
||||
transform="scale(1,-1)"
|
||||
ry="5.9607844"
|
||||
rx="5.647059"
|
||||
cy="-157.80394"
|
||||
cx="81.568619"
|
||||
id="ellipse8141"
|
||||
style="fill:#003c6c;fill-opacity:1;stroke:#003c6c;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<ellipse
|
||||
transform="scale(1,-1)"
|
||||
style="fill:#003c6c;fill-opacity:1;stroke:#003c6c;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse8147"
|
||||
cx="109.17645"
|
||||
cy="-157.80394"
|
||||
rx="5.647059"
|
||||
ry="5.9607844" />
|
||||
<ellipse
|
||||
transform="rotate(90)"
|
||||
style="fill:#003c6c;fill-opacity:1;stroke:#003c6c;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse8155"
|
||||
cx="56.715668"
|
||||
cy="-157.17644"
|
||||
rx="5.647059"
|
||||
ry="5.9607844" />
|
||||
<ellipse
|
||||
transform="rotate(90)"
|
||||
ry="5.9607844"
|
||||
rx="5.647059"
|
||||
cy="-157.17644"
|
||||
cx="84.323517"
|
||||
id="ellipse8161"
|
||||
style="fill:#003c6c;fill-opacity:1;stroke:#003c6c;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<ellipse
|
||||
transform="rotate(90)"
|
||||
style="fill:#003c6c;fill-opacity:1;stroke:#003c6c;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse8167"
|
||||
cx="111.93137"
|
||||
cy="-157.17644"
|
||||
rx="5.647059"
|
||||
ry="5.9607844" />
|
||||
<ellipse
|
||||
transform="matrix(0,1,1,0,0,0)"
|
||||
ry="5.9607844"
|
||||
rx="5.647059"
|
||||
cy="7.4607844"
|
||||
cx="56.715668"
|
||||
id="ellipse8175"
|
||||
style="fill:#003c6c;fill-opacity:1;stroke:#003c6c;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<ellipse
|
||||
transform="matrix(0,1,1,0,0,0)"
|
||||
style="fill:#003c6c;fill-opacity:1;stroke:#003c6c;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse8181"
|
||||
cx="84.323517"
|
||||
cy="7.4607844"
|
||||
rx="5.647059"
|
||||
ry="5.9607844" />
|
||||
<ellipse
|
||||
transform="matrix(0,1,1,0,0,0)"
|
||||
ry="5.9607844"
|
||||
rx="5.647059"
|
||||
cy="7.4607844"
|
||||
cx="111.93137"
|
||||
id="ellipse8187"
|
||||
style="fill:#003c6c;fill-opacity:1;stroke:#003c6c;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
style="fill:#fdc700;fill-opacity:1;stroke:none;stroke-width:4.87900019;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect3553"
|
||||
width="88.83606"
|
||||
height="86.559578"
|
||||
x="37.165073"
|
||||
y="39.245544"
|
||||
ry="4.3552427" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.7 KiB |
Loading…
Reference in New Issue