blob: 158d9ce29eff1b5a6ad540eefb34805f52156d68 [file] [log] [blame]
Rich Lanebdd8e292013-12-06 17:37:39 -08001# Copyright 2013, Big Switch Networks, Inc.
2#
3# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
4# the following special exception:
5#
6# LOXI Exception
7#
8# As a special exception to the terms of the EPL, you may distribute libraries
9# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
10# that copyright and licensing notices generated by LoxiGen are not altered or removed
11# from the LoxiGen Libraries and the notice provided below is (i) included in
12# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
13# documentation for the LoxiGen Libraries, if distributed in binary form.
14#
15# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
16#
17# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
18# a copy of the EPL at:
19#
20# http://www.eclipse.org/legal/epl-v10.html
21#
22# Unless required by applicable law or agreed to in writing, software
23# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
24# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
25# EPL for the specific language governing permissions and limitations
26# under the EPL.
27
28"""
29Code generation
30
31These functions extract data from the IR and render templates with it.
32"""
33
34from collections import namedtuple
35from itertools import groupby
36import template_utils
37import loxi_globals
38import loxi_ir.ir as ir
39import util
Rich Lanece2e4642013-12-15 12:05:45 -080040import c_code_gen
Rich Lane8c4c23f2013-12-15 13:22:13 -080041import c_gen.of_g_legacy as of_g
Rich Lanecce961d2013-12-15 14:20:42 -080042import c_gen.type_maps as type_maps
Rich Lanebdd8e292013-12-06 17:37:39 -080043
Rich Lane22811f52013-12-15 15:28:03 -080044PushWireTypesData = namedtuple('PushWireTypesData',
Rich Lanebdd8e292013-12-06 17:37:39 -080045 ['class_name', 'versioned_type_members'])
46PushWireTypesMember = namedtuple('PushWireTypesMember',
47 ['name', 'offset', 'length', 'value'])
48
Rich Lane22811f52013-12-15 15:28:03 -080049def push_wire_types_data(uclass):
50 if uclass.virtual or not uclass.has_type_members:
51 return None
Rich Lanebdd8e292013-12-06 17:37:39 -080052
Rich Lane22811f52013-12-15 15:28:03 -080053 # Generate a dict of version -> list of PushWireTypesMember
54 type_members_by_version = {}
55 for version, ofclass in sorted(uclass.version_classes.items()):
56 pwtms = []
57 for m in ofclass.members:
58 if isinstance(m, ir.OFTypeMember):
59 if m.name == "version" and m.value == version.wire_version:
60 # Special case for version
61 pwtms.append(PushWireTypesMember(m.name, m.offset, m.length, "obj->version"))
62 else:
63 pwtms.append(PushWireTypesMember(m.name, m.offset, m.length, m.value))
64 type_members_by_version[version] = pwtms
Rich Lanebdd8e292013-12-06 17:37:39 -080065
Rich Lane22811f52013-12-15 15:28:03 -080066 # Merge versions with identical type members
67 all_versions = sorted(type_members_by_version.keys())
68 versioned_type_members = []
69 for pwtms, versions in groupby(all_versions, type_members_by_version.get):
70 versioned_type_members.append((pwtms, list(versions)))
Rich Lanebdd8e292013-12-06 17:37:39 -080071
Rich Lane22811f52013-12-15 15:28:03 -080072 return PushWireTypesData(
73 class_name=uclass.name,
74 versioned_type_members=versioned_type_members)
Rich Lanece2e4642013-12-15 12:05:45 -080075
76def generate_classes(install_dir):
77 for uclass in loxi_globals.unified.classes:
78 with template_utils.open_output(install_dir, "loci/src/%s.c" % uclass.name) as out:
Rich Lane22811f52013-12-15 15:28:03 -080079 util.render_template(out, "class.c",
80 push_wire_types_data=push_wire_types_data(uclass))
Rich Lanece2e4642013-12-15 12:05:45 -080081 # Append legacy generated code
Rich Laneb604e332013-12-15 13:23:51 -080082 c_code_gen.gen_new_function_definitions(out, uclass.name)
Rich Lanece2e4642013-12-15 12:05:45 -080083 c_code_gen.gen_accessor_definitions(out, uclass.name)
Rich Lane8c4c23f2013-12-15 13:22:13 -080084
Rich Lane573d2b22013-12-15 13:31:27 -080085# TODO remove header classes and use the corresponding class instead
86def generate_header_classes(install_dir):
87 for cls in of_g.standard_class_order:
88 if cls.find("_header") < 0:
89 continue
90 with template_utils.open_output(install_dir, "loci/src/%s.c" % cls) as out:
Rich Lane22811f52013-12-15 15:28:03 -080091 util.render_template(out, "class.c",
92 push_wire_types_data=None)
Rich Lane573d2b22013-12-15 13:31:27 -080093 # Append legacy generated code
94 c_code_gen.gen_new_function_definitions(out, cls)
95 c_code_gen.gen_accessor_definitions(out, cls)
96
Rich Lane8c4c23f2013-12-15 13:22:13 -080097def generate_lists(install_dir):
98 for cls in of_g.ordered_list_objects:
99 with template_utils.open_output(install_dir, "loci/src/%s.c" % cls) as out:
Rich Lane22811f52013-12-15 15:28:03 -0800100 util.render_template(out, "class.c",
101 push_wire_types_data=None)
Rich Lane8c4c23f2013-12-15 13:22:13 -0800102 # Append legacy generated code
Rich Laneb604e332013-12-15 13:23:51 -0800103 c_code_gen.gen_new_function_definitions(out, cls)
Rich Lane8c4c23f2013-12-15 13:22:13 -0800104 c_code_gen.gen_list_accessors(out, cls)
Rich Lane8a822732013-12-15 14:06:32 -0800105
106def generate_strings(install_dir):
107 object_id_strs = []
108 object_id_strs.append("of_object")
109 object_id_strs.extend(of_g.ordered_messages)
110 object_id_strs.extend(of_g.ordered_non_messages)
111 object_id_strs.extend(of_g.ordered_list_objects)
112 object_id_strs.extend(of_g.ordered_pseudo_objects)
113 object_id_strs.append("of_unknown_object")
114
115 with template_utils.open_output(install_dir, "loci/src/loci_strings.c") as out:
116 util.render_template(out, "loci_strings.c", object_id_strs=object_id_strs)
Rich Lanecce961d2013-12-15 14:20:42 -0800117
118def generate_init_map(install_dir):
119 with template_utils.open_output(install_dir, "loci/src/loci_init_map.c") as out:
120 util.render_template(out, "loci_init_map.c", classes=of_g.standard_class_order)