Example #1
0
    def __init__(self, symbol_dirs=None):
        """ Constuct a gEDA parser object. Specifying a list of symbol
            directories in *symbol_dir* will provide a symbol file
            lookup in the specified directories. The lookup will be
            generated instantly examining each directory (if it exists).

            Kwargs:
                symbol_dirs (list): List of directories containing .sym
                    files
        """
        self.offset = shape.Point(40000, 40000)
        ## Initialise frame size with largest possible size
        self.frame_width = 0
        self.frame_height = 0

        # initialise PIN counter
        self.pin_counter = itertools.count(0)
        # initialise  PATH counter
        self.path_counter = itertools.count(0)

        ## add flag to allow for auto inclusion
        if symbol_dirs is None:
            symbol_dirs = []

        symbol_dirs = symbol_dirs + \
            [os.path.join(os.path.dirname(__file__), '..', 'library', 'geda')]

        self.known_symbols = find_symbols(symbol_dirs)

        self.design = None
        self.segments = None
        self.net_points = None
        self.net_names = None
        self.geda_zip = None
Example #2
0
    def test_write_component_to_file(self):
        """ Tests writing a component to a symbol file. """
        sym_dir = '/tmp/sym'
        if os.path.exists(sym_dir):
            shutil.rmtree(sym_dir)

        os.mkdir(sym_dir)

        self.geda_writer.set_offset(shape.Point(-500, -500))

        self.geda_writer.component_library = dict()
        self.geda_writer.project_dirs['symbol'] = sym_dir

        simple_design = self.oj_parser.parse('test/openjson/simple.upv')

        library_id = '0000000000000001'
        component = simple_design.components.components[library_id]
        self.geda_writer.write_component_to_file(library_id, component)

        component_library = self.geda_writer.component_library
        self.assertEquals(len(component_library), 4)

        self.assertEquals(
            component_library, {
                (library_id, 0): 'Flag_1-0.sym',
                (library_id, 1): 'Flag_2-1.sym',
                (library_id, 2): 'GND-2.sym',
                (library_id, 3): 'VCC-3.sym'
            })
        self.assertEquals(
            sorted(os.listdir(sym_dir)),
            ['Flag_1-0.sym', 'Flag_2-1.sym', 'GND-2.sym', 'VCC-3.sym'])
Example #3
0
    def parse_component_data(self, stream, params):
        """ Creates a component from the component *params* and the
            following commands in the stream. If the component data
            is embedded in the schematic file, all coordinates will
            be translated into the origin first.
            Only a single symbol/body is created for each component
            since gEDA symbols contain exactly one description.

            Returns the newly created Component object.
        """
        # pylint: disable=R0912
        basename = os.path.splitext(params['basename'])[0]

        saved_offset = self.offset
        self.offset = shape.Point(0, 0)

        ## retrieve if component is mirrored around Y-axis
        mirror = self._is_mirrored_command(params)
        if mirror:
            basename += '_MIRRORED'

        move_to = None
        if basename.startswith('EMBEDDED'):
            move_to = (params['x'], params['y'])

        ## grab next line (should be '['
        typ, params = self._parse_command(stream, move_to)

        if typ == '[':
            typ, params = self._parse_command(stream, move_to)

        component = components.Component(basename)
        symbol = components.Symbol()
        component.add_symbol(symbol)
        body = components.Body()
        symbol.add_body(body)

        ##NOTE: adding this attribute to make parsing UPV data easier
        ## when using re-exported UPV.
        component.add_attribute('_geda_imported', 'true')
        self.pin_counter = itertools.count(0)

        while typ is not None:

            params['mirror'] = mirror
            objects = getattr(self, "_parse_%s" % typ)(stream, params)

            attributes = self._parse_environment(stream)
            component.attributes.update(attributes or {})

            self.add_objects_to_component(component, objects)

            typ, params = self._parse_command(stream, move_to)

        self.offset = saved_offset

        return component
Example #4
0
    def test_write_schematic_file(self):
        """ Reads the gEDA *simple_example* file into a design using the
            gEDA parser, writes the result to a gEDA file and reads it into
            a new design. Both designs are then compared regarding their
            respective components, instances and nets. """
        # pylint: disable=R0914
        # pylint: disable=R0915

        sym_dir = '/tmp/sym'

        if os.path.exists('/tmp/converted.sch'):
            os.remove('/tmp/converted.sch')

        if os.path.exists(sym_dir):
            shutil.rmtree(sym_dir)

        geda_parser = upconvert.parser.geda.GEDA(
            symbol_dirs=['test/geda/simple_example/symbols'])
        geda_parser.set_offset(shape.Point(0, 0))
        simple_design = geda_parser.parse(
            'test/geda/simple_example/simple_example.sch')

        geda_writer = GEDA()
        geda_writer.write(simple_design, '/tmp/converted.sch')

        converted_design = geda_parser.parse('/tmp/converted.sch')

        ## parse design again to make sure it is a clean slate
        geda_parser = upconvert.parser.geda.GEDA(
            symbol_dirs=['test/geda/simple_example/symbols'])
        geda_parser.set_offset(shape.Point(0, 0))
        simple_design = geda_parser.parse(
            'test/geda/simple_example/simple_example.sch')

        ##compare nets
        self.assertEquals(
            sorted([(net.net_id, len(net.points))
                    for net in simple_design.nets]),
            sorted([(net.net_id, len(net.points))
                    for net in converted_design.nets]))

        snets = dict([(net.net_id, net) for net in simple_design.nets])
        cnets = dict([(net.net_id, net) for net in converted_design.nets])

        for snet_id, snet in snets.items():
            cnet = cnets[snet_id]

            spoints = dict([(pt.point_id, pt) for pt in snet.points.values()])
            cpoints = dict([(pt.point_id, pt) for pt in cnet.points.values()])
            self.assertEqual(sorted(spoints.keys()), sorted(cpoints.keys()))

            for spoint_id, spoint in spoints.items():
                cpoint = cpoints[spoint_id]

                self.assertEquals(spoint.x, cpoint.x)
                self.assertEquals(spoint.y, cpoint.y)

        ## compare component library
        self.assertEqual(sorted(simple_design.components.components.keys()),
                         sorted(converted_design.components.components.keys()))

        for lib_id in simple_design.components.components:
            scomponent = simple_design.components.components[lib_id]
            ccomponent = converted_design.components.components[lib_id]

            self.assertEquals(scomponent.name, ccomponent.name)
            self.assertEquals(scomponent.attributes, ccomponent.attributes)

            self.assertEquals(len(scomponent.symbols), 1)
            self.assertEquals(len(scomponent.symbols), len(ccomponent.symbols))

            self.assertEquals(len(scomponent.symbols[0].bodies), 1)
            self.assertEquals(len(scomponent.symbols[0].bodies),
                              len(ccomponent.symbols[0].bodies))
            sbody = scomponent.symbols[0].bodies[0]
            cbody = ccomponent.symbols[0].bodies[0]

            ## skip the unassigned shapes component as it adds an additional
            ## text from the basename when importing GEDA
            if scomponent.name != 'UNASSIGNED_SHAPES':
                self.assertEquals(len(sbody.shapes), len(cbody.shapes))
            self.assertEquals(len(sbody.pins), len(cbody.pins))

            for spin, cpin in zip(sbody.pins, cbody.pins):
                self.assertEquals(spin.p1.x, cpin.p1.x)
                self.assertEquals(spin.p1.x, cpin.p1.x)
                self.assertEquals(spin.p2.y, cpin.p2.y)
                self.assertEquals(spin.p2.y, cpin.p2.y)
                if spin.label is None:
                    self.assertEquals(cpin.label, None)
                else:
                    self.assertEquals(spin.label.text, cpin.label.text)

            for sshape, cshape in zip(sbody.shapes, cbody.shapes):
                self.assertEquals(sshape.type, cshape.type)

        ## compare component instances
        scomp_instances = dict([(comp.instance_id, comp)
                                for comp in simple_design.component_instances])
        ccomp_instances = dict([
            (comp.instance_id, comp)
            for comp in converted_design.component_instances
        ])

        for instance_id in scomp_instances:
            sinst = scomp_instances[instance_id]
            cinst = ccomp_instances[instance_id]

            self.assertEquals(sinst.instance_id, cinst.instance_id)
            self.assertEquals(sinst.library_id, cinst.library_id)
            self.assertEquals(sinst.symbol_index, cinst.symbol_index)

            self.assertEquals(sinst.symbol_attributes[0].x,
                              cinst.symbol_attributes[0].x)
            self.assertEquals(sinst.symbol_attributes[0].y,
                              cinst.symbol_attributes[0].y)
            self.assertEquals(sinst.symbol_attributes[0].rotation,
                              cinst.symbol_attributes[0].rotation)
    def write_component_to_file(self, library_id, component):
        """ Writes a *component* to a local symbol file and adds it to
            the symbol lookup used for instantiating components. A component
            might have a special attribute 'geda_imported' assigned when
            converted with the upconverter parser. This allows for retrieving
            that a local symbol file can be referenced. If this attribute is
            not present, a new symbol file will be generated in the project
            directory's symbols directory.
        """
        # pylint: disable=R0914

        ##NOTE: extract and remove gEDA internal attribute
        geda_imported = component.attributes.get('_geda_imported', 'false')
        geda_imported = (geda_imported == "true")

        component.attributes['_refdes'] = '%s?%s' % (component.attributes.get(
            '_prefix', ''), component.attributes.get('_suffix', ''))

        symbol_filename = None
        ##NOTE: this attributed is used in the parser to mark at component
        ## as being imported using the upconverter. If this marker is found
        ## local .sym files will be referenced if available.
        if geda_imported:
            ##remove mirrored tag from name
            if '_MIRRORED' in component.name:
                component.name = component.name.replace('_MIRRORED', '')

            ##check if component is known sym file in OS dirs
            symbol_filename = "%s.sym" % component.name.replace('EMBEDDED', '')

            self.component_library[(library_id.replace('_MIRRORED', ''),
                                    0)] = symbol_filename

            if component.name.replace('EMBEDDED', '') in self.known_symbols:
                return

        ## symbol files should not use offset
        saved_offset = self.offset
        self.offset = shape.Point(0, 0)

        ## write symbol file for each symbol in component
        for sym_idx, symbol in enumerate(component.symbols):

            symbol_attr = "_symbol_%d_0" % sym_idx
            if symbol_attr in component.attributes:
                prefix = component.attributes[symbol_attr]
                del component.attributes[symbol_attr]
            else:
                prefix = component.name

            if not geda_imported:
                prefix = prefix.replace(' ', '_')
                symbol_filename = "%s-%d.sym" % (prefix, sym_idx)

            commands = []
            for body in symbol.bodies:
                commands += self.generate_body_commands(body)

            attr_y = 0
            for key, value in component.attributes.items():
                if not key.startswith('_symbol') \
                   and key not in self.ignored_attributes:
                    commands += self._create_attribute(
                        key,
                        value,
                        0,
                        attr_y,
                    )
                    attr_y = attr_y + 10

            ## write commands to file
            path = os.path.join(self.project_dirs['symbol'], symbol_filename)
            with codecs.open(path, encoding='utf-8', mode='w') as fout:
                fout.write(self.commands_to_string(commands))

            ## required for instantiating components later
            self.component_library[(library_id, sym_idx)] = symbol_filename

        ## restore offset
        self.offset = saved_offset