def _generate_group_checker(model, models, templates): global _cached_members groupname = model.get('name') checktype = _get_group_members_recursively(model, models) if checktype: checktype = (' &&\n' + (' ' * 6)).join( [f'(uhdmtype != uhdm{member})' for member in sorted(checktype)]) else: checktype = 'false' files = { 'group_header.h': config.get_output_header_filepath(f'{groupname}.h'), 'group_header.cpp': config.get_output_source_filepath(f'{groupname}.cpp'), } for input, output in files.items(): file_content = templates[input] file_content = file_content.replace('<GROUPNAME>', groupname) file_content = file_content.replace('<UPPER_GROUPNAME>', groupname.upper()) file_content = file_content.replace('<CHECKTYPE>', checktype) file_utils.set_content_if_changed(output, file_content) return True
def generate(models): with open(config.get_template_filepath('clone_tree.cpp'), 'r+t') as strm: file_content = strm.read() file_content = file_content.replace('<CLONE_IMPLEMENTATIONS>', '') file_utils.set_content_if_changed( config.get_output_source_filepath('clone_tree.cpp'), file_content) return True
def generate(models): module_listeners = _generate_module_listeners(models) class_listeners = _generate_class_listeners(models) with open(config.get_template_filepath('ElaboratorListener.cpp'), 'r+t') as strm: file_content = strm.read() file_content = file_content.replace( '<MODULE_ELABORATOR_LISTENER>', (' ' * 10) + ('\n' + (' ' * 10)).join(module_listeners)) file_content = file_content.replace( '<CLASS_ELABORATOR_LISTENER>', (' ' * 4) + ('\n' + (' ' * 4)).join(class_listeners)) file_utils.set_content_if_changed( config.get_output_source_filepath('ElaboratorListener.cpp'), file_content) return True
def generate(models): vpi_get_value_classes = set() vpi_get_delay_classes = set() for model in models.values(): modeltype = model['type'] if modeltype != 'obj_def': continue classname = model['name'] baseclass = classname while baseclass: for key, value in models[baseclass].allitems(): if key == 'property' and value.get('card') == '1': type = value.get('type') if type == 'value': vpi_get_value_classes.add(classname) if type == 'delay': vpi_get_delay_classes.add(classname) baseclass = models[baseclass]['extends'] # headers = [ f"#include <uhdm/{model['name']}.h>" for model in models.values() ] headers = [ f"#include <uhdm/{name}.h>" for name in sorted( set.union(vpi_get_value_classes, vpi_get_delay_classes)) ] vpi_handle_by_name_body = [ f' if (object->GetSerializer()->symbolMaker.GetId(name) == static_cast<SymbolFactory::ID>(-1)) {{', ' return nullptr;', ' }', ' const BaseClass *const ref = object->GetByVpiName(std::string_view(name));', ' return (ref != nullptr) ? NewVpiHandle(ref) : nullptr;' ] vpi_handle_body = [ ' auto [ref, ignored1, ignored2] = object->GetByVpiType(type);', ' return (ref != nullptr) ? NewHandle(ref->UhdmType(), ref) : nullptr;' ] vpi_iterate_body = [ ' auto [ignored, refType, refVector] = object->GetByVpiType(type);', ' return (refVector != nullptr) ? NewHandle(refType, refVector) : nullptr;' ] vpi_get_body = [ ' BaseClass::vpi_property_value_t value = obj->GetVpiPropertyValue(property);', ' return std::holds_alternative<int64_t>(value) ? std::get<int64_t>(value) : 0;' ] vpi_get_str_body = [ ' BaseClass::vpi_property_value_t value = obj->GetVpiPropertyValue(property);', ' return std::holds_alternative<const char *>(value) ? const_cast<char *>(std::get<const char *>(value)) : nullptr;' ] vpi_get_value_body = [ f' const s_vpi_value* v = nullptr;', f' switch (handle->type) {{' ] + [ f' case uhdm{classname}: v = String2VpiValue((({classname}*)obj)->VpiValue()); break;' for classname in sorted(vpi_get_value_classes) ] + [ ' default: break;', f' }}', f' if (v != nullptr) *value_p = *v;' ] if vpi_get_value_classes else [] vpi_get_delay_body = [ f' const s_vpi_delay* v = nullptr;', f' switch (handle->type) {{', ] + [ f' case uhdm{classname}: v = String2VpiDelays((({classname}*)obj)->VpiDelay()); break;' for classname in sorted(vpi_get_delay_classes) ] + [ ' default: break;', f' }}', f' if (v != nullptr) *delay_p = *v;' ] if vpi_get_delay_classes else [] # vpi_user.cpp with open(config.get_template_filepath('vpi_user.cpp'), 'r+t') as strm: file_content = strm.read() file_content = file_content.replace('<HEADERS>', '\n'.join(headers)) file_content = file_content.replace('<VPI_HANDLE_BY_NAME_BODY>', '\n'.join(vpi_handle_by_name_body)) file_content = file_content.replace('<VPI_HANDLE_BODY>', '\n'.join(vpi_handle_body)) file_content = file_content.replace('<VPI_ITERATE_BODY>', '\n'.join(vpi_iterate_body)) file_content = file_content.replace('<VPI_SCAN_BODY>', '') file_content = file_content.replace('<VPI_GET_BODY>', '\n'.join(vpi_get_body)) file_content = file_content.replace('<VPI_GET_STR_BODY>', '\n'.join(vpi_get_str_body)) file_content = file_content.replace('<VPI_GET_VALUE_BODY>', '\n'.join(vpi_get_value_body)) file_content = file_content.replace('<VPI_GET_DELAY_BODY>', '\n'.join(vpi_get_delay_body)) file_utils.set_content_if_changed( config.get_output_source_filepath('vpi_user.cpp'), file_content) return True
def _generate_one_class(model, models, templates): header_file_content = templates['class_header.h'] source_file_content = templates['class_source.cpp'] classname = model['name'] modeltype = model['type'] group_headers = set() declarations = [] data_members = [] implementations = [] forward_declares = set() Classname_ = classname[:1].upper() + classname[1:] Classname = Classname_.replace('_', '') if modeltype != 'class_def': # Builtin properties do not need to be specified in each models # Builtins: "vpiParent, Parent type, vpiFile, Id" method and field data_members.extend(_get_data_member('BaseClass', 'vpiParent', '1')) declarations.extend( _get_declaration(classname, 'BaseClass', 'vpiParent', '1')) implementations.extend( _get_implementation(classname, 'BaseClass', 'vpiParent', '1')) data_members.extend( _get_data_member('unsigned int', 'uhdmParentType', '1')) declarations.extend( _get_declaration(classname, 'unsigned int', 'uhdmParentType', '1')) implementations.extend( _get_implementation(classname, 'unsigned int', 'uhdmParentType', '1')) data_members.extend(_get_data_member('string', 'vpiFile', '1')) declarations.extend( _get_declaration(classname, 'string', 'vpiFile', '1')) implementations.extend( _get_implementation(classname, 'string', 'vpiFile', '1')) data_members.extend(_get_data_member('unsigned int', 'uhdmId', '1')) declarations.extend( _get_declaration(classname, 'unsigned int', 'uhdmId', '1')) implementations.extend( _get_implementation(classname, 'unsigned int', 'uhdmId', '1')) type_specified = False for key, value in model.allitems(): if key == 'property': name = value.get('name') vpi = value.get('vpi') type = value.get('type') card = value.get('card') Vpi = vpi[:1].upper() + vpi[1:] if name == 'type': type_specified = True declarations.append( f' {type} {Vpi}() const final {{ return {value.get("vpiname")}; }}' ) else: # properties are already defined in vpi_user.h, no need to redefine them data_members.extend(_get_data_member(type, vpi, card)) declarations.extend( _get_declaration(classname, type, vpi, card)) implementations.extend( _get_implementation(classname, type, vpi, card)) elif key == 'extends' and value: header_file_content = header_file_content.replace( '<EXTENDS>', value) source_file_content = source_file_content.replace( '<EXTENDS>', value) elif key in ['class', 'obj_ref', 'class_ref', 'group_ref']: name = value.get('name') vpi = value.get('vpi') type = value.get('type') card = value.get('card') if (card == 'any') and not name.endswith('s'): name += 's' real_type = type if key == 'group_ref': type = 'any' if type != 'any' and card == '1': forward_declares.add(f'class {type};') group_headers.update(_get_group_headers(type, real_type)) data_members.extend(_get_data_member(type, name, card)) declarations.extend( _get_declaration(classname, type, name, card, real_type)) implementations.extend( _get_implementation(classname, type, name, card, real_type)) if not type_specified and (modeltype == 'obj_def'): vpiclasstype = config.make_vpi_name(classname) declarations.append( f' virtual unsigned int VpiType() const final {{ return {vpiclasstype}; }}' ) if modeltype == 'class_def': # DeepClone() not implemented for class_def; just declare to narrow the covariant return type. declarations.append( f' virtual {classname}* DeepClone(Serializer* serializer, ElaboratorListener* elaborator, BaseClass* parent) const override = 0;' ) else: return_type = 'tf_call' if '_call' in classname else classname declarations.append( f' virtual {return_type}* DeepClone(Serializer* serializer, ElaboratorListener* elaborator, BaseClass* parent) const override;' ) declarations.append( ' virtual const BaseClass* GetByVpiName(std::string_view name) const override;' ) declarations.append( ' virtual std::tuple<const BaseClass*, UHDM_OBJECT_TYPE, const std::vector<const BaseClass*>*> GetByVpiType(int type) const override;' ) declarations.append( ' virtual vpi_property_value_t GetVpiPropertyValue(int property) const override;' ) implementations.extend(_get_clone_implementation(model, models)) implementations.extend(_get_GetByVpiName_implementation(model)) implementations.extend(_get_GetByVpiType_implementation(model)) implementations.extend(_get_GetVpiPropertyValue_implementation(model)) if modeltype == 'class_def': header_file_content = header_file_content.replace('<FINAL_CLASS>', '') header_file_content = header_file_content.replace( '<FINAL_DESTRUCTOR>', '') header_file_content = header_file_content.replace( '<VIRTUAL>', 'virtual ') header_file_content = header_file_content.replace( '<OVERRIDE_OR_FINAL>', 'override') header_file_content = header_file_content.replace( '<DISABLE_OBJECT_FACTORY>', '#if 0 // This class cannot be instantiated') header_file_content = header_file_content.replace( '<END_DISABLE_OBJECT_FACTORY>', '#endif') else: header_file_content = header_file_content.replace( '<FINAL_CLASS>', ' final') header_file_content = header_file_content.replace( '<FINAL_DESTRUCTOR>', ' final') header_file_content = header_file_content.replace( '<VIRTUAL>', 'virtual ') header_file_content = header_file_content.replace( '<OVERRIDE_OR_FINAL>', 'final') header_file_content = header_file_content.replace( '<DISABLE_OBJECT_FACTORY>', '') header_file_content = header_file_content.replace( '<END_DISABLE_OBJECT_FACTORY>', '') header_file_content = header_file_content.replace('<EXTENDS>', 'BaseClass') header_file_content = header_file_content.replace('<CLASSNAME>', classname) header_file_content = header_file_content.replace('<UPPER_CLASSNAME>', classname.upper()) header_file_content = header_file_content.replace( '<METHODS>', '\n\n'.join(declarations)) header_file_content = header_file_content.replace( '<MEMBERS>', '\n\n'.join(data_members)) header_file_content = header_file_content.replace( '<GROUP_HEADER_DEPENDENCY>', '\n'.join(sorted(group_headers))) header_file_content = header_file_content.replace( '<TYPE_FORWARD_DECLARE>', '\n'.join(sorted(forward_declares))) source_file_content = source_file_content.replace('<CLASSNAME>', classname) source_file_content = source_file_content.replace( '<METHODS>', '\n'.join(implementations)) file_utils.set_content_if_changed( config.get_output_header_filepath(f'{classname}.h'), header_file_content) file_utils.set_content_if_changed( config.get_output_source_filepath(f'{classname}.cpp'), source_file_content) return True
def generate(models): factory_declarations = [] factory_methods = [] factory_purge = [] factory_stats = [] factory_object_type_map = [] save_ids = [] save_objects = [] saves_adapters = [] restore_ids = [] restore_objects = [] restore_adapters = [] type_map = uhdm_types_h.get_type_map(models) for model in models.values(): modeltype = model['type'] if modeltype == 'group_def': continue classname = model['name'] Classname_ = classname[:1].upper() + classname[1:] Classname = Classname_.replace('_', '') baseclass = model.get('extends', 'BaseClass') or 'BaseClass' if modeltype != 'class_def': factory_declarations.append(f' {classname}Factory {classname}Maker;') factory_methods.append(f' {classname}* Make{Classname_}() {{ return Make<{classname}>(&{classname}Maker); }}') factory_object_type_map.append(f' case uhdm{classname} /* = {type_map["uhdm" + classname]} */: return {classname}Maker.objects_[index];') save_ids.append(f' SetSaveId_(&{classname}Maker);') save_objects.append(f' VectorOfanySaveAdapter<{classname}, {Classname}>()({classname}Maker.objects_, this, cap_root.initFactory{Classname}({classname}Maker.objects_.size()));') restore_ids.append(f' SetRestoreId_(&{classname}Maker, cap_root.getFactory{Classname}().size());') restore_objects.append(f' VectorOfanyRestoreAdapter<{classname}, {Classname}>()(cap_root.getFactory{Classname}(), this, {classname}Maker.objects_);') factory_purge.append(f' {classname}Maker.Purge();') factory_stats.append(f' stats.insert(std::make_pair("{classname}", {classname}Maker.objects_.size()));') factory_declarations.append(f' VectorOf{classname}Factory {classname}VectMaker;') factory_methods.append(f' std::vector<{classname}*>* Make{Classname_}Vec() {{ return Make<{classname}>(&{classname}VectMaker); }}') saves_adapters.append(f'template<typename U>') saves_adapters.append(f'struct Serializer::AnySaveAdapter<{classname}, U> {{') saves_adapters.append(f' void operator()(const {classname} *const obj, Serializer *const serializer, U builder) const {{') saves_adapters.append(f' AnySaveAdapter<{baseclass}, U>()(static_cast<const {baseclass}*>(obj), serializer, builder);') restore_adapters.append(f'template<typename U>') restore_adapters.append(f'struct Serializer::AnyRestoreAdapter<{classname}, U> {{') restore_adapters.append(f' void operator()(U reader, Serializer *const serializer, {classname} *const obj) const {{') restore_adapters.append(f' AnyRestoreAdapter<{baseclass}, U>()(reader, serializer, static_cast<{baseclass}*>(obj));') for key, value in model.allitems(): if key == 'property': name = value.get('name') vpi = value.get('vpi') type = value.get('type') card = value.get('card') if name == 'type': continue Vpi_ = vpi[:1].upper() + vpi[1:] Vpi = Vpi_.replace('_', '') if type in ['string', 'value', 'delay']: saves_adapters.append(f' builder.set{Vpi}(serializer->symbolMaker.Make(obj->{Vpi_}()));') restore_adapters.append(f' obj->{Vpi_}(serializer->symbolMaker.GetSymbol(reader.get{Vpi}()));') else: saves_adapters.append(f' builder.set{Vpi}(obj->{Vpi_}());') restore_adapters.append(f' obj->{Vpi_}(reader.get{Vpi}());') elif key in ['class', 'obj_ref', 'class_ref', 'group_ref']: name = value.get('name') type = value.get('type') card = value.get('card') id = value.get('id') Type_ = type[:1].upper() + type[1:] Type = Type_.replace('_', '') if (card == 'any') and not name.endswith('s'): name += 's' Name_ = name[:1].upper() + name[1:] Name = Name_.replace('_', '') real_type = type if key == 'group_ref': type = 'any' if card == '1': if key in ['class_ref', 'group_ref']: saves_adapters.append(f' if (obj->{Name_}() != nullptr) {{') saves_adapters.append(f' ::ObjIndexType::Builder tmp = builder.get{Name}();') saves_adapters.append(f' tmp.setIndex(serializer->GetId(obj->{Name_}()));') saves_adapters.append(f' tmp.setType((obj->{Name_}())->UhdmType());') saves_adapters.append( ' }') restore_adapters.append(f' obj->{Name_}(({type}*)serializer->GetObject(reader.get{Name}().getType(), reader.get{Name}().getIndex() - 1));') else: saves_adapters.append(f' builder.set{Name}(serializer->GetId(obj->{Name_}()));') restore_adapters.append(f' if (reader.get{Name}()) {{') restore_adapters.append(f' obj->{Name_}(serializer->{type}Maker.objects_[reader.get{Name}() - 1]);') restore_adapters.append( ' }') else: obj_key = '::ObjIndexType' if key in ['class_ref', 'group_ref'] else '::uint64_t' saves_adapters.append(f' if (obj->{Name_}() != nullptr) {{') saves_adapters.append(f' ::capnp::List<{obj_key}>::Builder {Name}s = builder.init{Name}(obj->{Name_}()->size());') saves_adapters.append(f' for (unsigned int i = 0, n = obj->{Name_}()->size(); i < n; ++i) {{') restore_adapters.append(f' if (reader.get{Name}().size() > 0) {{') restore_adapters.append(f' std::vector<{type}*>* vect = serializer->{type}VectMaker.Make();') restore_adapters.append(f' for (unsigned int i = 0, n = reader.get{Name}().size(); i < n; ++i) {{') if key in ['class_ref', 'group_ref']: saves_adapters.append(f' ::ObjIndexType::Builder tmp = {Name}s[i];') saves_adapters.append(f' tmp.setIndex(serializer->GetId((*obj->{Name_}())[i]));') saves_adapters.append(f' tmp.setType(((BaseClass*)((*obj->{Name_}())[i]))->UhdmType());') restore_adapters.append(f' vect->push_back(({type}*)serializer->GetObject(reader.get{Name}()[i].getType(), reader.get{Name}()[i].getIndex() - 1));') else: saves_adapters.append(f' {Name}s.set(i, serializer->GetId((*obj->{Name_}())[i]));') restore_adapters.append(f' vect->push_back(serializer->{type}Maker.objects_[reader.get{Name}()[i] - 1]);') saves_adapters.append(' }') saves_adapters.append(' }') restore_adapters.append( ' }') restore_adapters.append(f' obj->{Name_}(vect);') restore_adapters.append( ' }') saves_adapters.append(' }') saves_adapters.append('};') saves_adapters.append('') restore_adapters.append(' }') restore_adapters.append('};') restore_adapters.append('') uhdm_name_map = [ 'std::string UhdmName(UHDM_OBJECT_TYPE type) {', ' switch (type) {' ] uhdm_name_map.extend([ f' case {name} /* = {id} */: return "{name[4:]}";' for name, id in uhdm_types_h.get_type_map(models).items() ]) uhdm_name_map.append(' default: return "NO TYPE";') uhdm_name_map.append('}') uhdm_name_map.append('}') # Serializer.h with open(config.get_template_filepath('Serializer.h'), 'r+t') as strm: file_content = strm.read() file_content = file_content.replace('<FACTORIES>', '\n'.join(factory_declarations)) file_content = file_content.replace('<FACTORIES_METHODS>', '\n'.join(factory_methods)) file_utils.set_content_if_changed(config.get_output_header_filepath('Serializer.h'), file_content) # Serializer.cpp with open(config.get_template_filepath('Serializer.cpp'), 'r+t') as strm: file_content = strm.read() file_content = file_content.replace('<METHODS_CPP>', '') # Deprecated file_content = file_content.replace('<UHDM_NAME_MAP>', '\n'.join(uhdm_name_map)) file_content = file_content.replace('<FACTORY_PURGE>', '\n'.join(factory_purge)) file_content = file_content.replace('<FACTORY_STATS>', '\n'.join(factory_stats)) file_content = file_content.replace('<FACTORY_OBJECT_TYPE_MAP>', '\n'.join(factory_object_type_map)) file_utils.set_content_if_changed(config.get_output_source_filepath('Serializer.cpp'), file_content) # Serializer_save.cpp with open(config.get_template_filepath('Serializer_save.cpp'), 'r+t') as strm: file_content = strm.read() file_content = file_content.replace('<CAPNP_ID>', '\n'.join(save_ids)) file_content = file_content.replace('<CAPNP_SAVE>', '\n'.join(save_objects)) file_content = file_content.replace('<CAPNP_SAVE_ADAPTERS>', '\n'.join(saves_adapters)) file_utils.set_content_if_changed(config.get_output_source_filepath('Serializer_save.cpp'), file_content) # Serializer_restore.cpp with open(config.get_template_filepath('Serializer_restore.cpp'), 'r+t') as strm: file_content = strm.read() file_content = file_content.replace('<CAPNP_INIT_FACTORIES>', '\n'.join(restore_ids)) file_content = file_content.replace('<CAPNP_RESTORE_FACTORIES>', '\n'.join(restore_objects)) file_content = file_content.replace('<CAPNP_RESTORE_ADAPTERS>', '\n'.join(restore_adapters)) file_utils.set_content_if_changed(config.get_output_source_filepath('Serializer_restore.cpp'), file_content) return True
def _main(): parser = argparse.ArgumentParser() parser.add_argument('-output-dirpath', dest='output_dirpath', type=str, help='Output path') parser.add_argument('--parallel', dest='parallel', action='store_true', default=True) parser.add_argument('--source-dirpath', dest='source_dirpath', type=str, help='Path to UHDM source') args = parser.parse_args() config.configure(args) print('Generating UHDM models ...') print(' Loading models ...') models = loader.load_models() print(f' ... found {len(models)} models.') print(' Validating ordering ...') # Check validity index = 0 order = {} for name in models.keys(): order[name] = index index += 1 for name, model in models.items(): baseclass = model['extends'] if baseclass: thisIndex = order[name] baseIndex = order[baseclass] if baseIndex >= thisIndex: raise Exception( f'Model {name} should follow {baseclass} in listing.') print(' ... all good.') params = [ ('capnp', [models]), ('class_hierarchy', [models]), ('classes', [models]), ('clone_tree_cpp', [models]), ('containers_h', [models]), ('ElaboratorListener_cpp', [models]), ('Copier', [{ config.get_template_filepath('BaseClass.h'): config.get_output_header_filepath('BaseClass.h'), config.get_template_filepath('clone_tree.h'): config.get_output_header_filepath('clone_tree.h'), config.get_template_filepath('ElaboratorListener.h'): config.get_output_header_filepath('ElaboratorListener.h'), config.get_template_filepath('ExprEval.h'): config.get_output_header_filepath('ExprEval.h'), config.get_template_filepath('ExprEval.cpp'): config.get_output_source_filepath('ExprEval.cpp'), config.get_template_filepath('RTTI.h'): config.get_output_header_filepath('RTTI.h'), config.get_template_filepath('SymbolFactory.h'): config.get_output_header_filepath('SymbolFactory.h'), config.get_template_filepath('SymbolFactory.cpp'): config.get_output_source_filepath('SymbolFactory.cpp'), config.get_template_filepath('uhdm_vpi_user.h'): config.get_output_header_filepath('uhdm_vpi_user.h'), config.get_template_filepath('vpi_uhdm.h'): config.get_output_header_filepath('vpi_uhdm.h'), config.get_template_filepath('vpi_visitor.h'): config.get_output_header_filepath('vpi_visitor.h'), config.get_include_filepath('sv_vpi_user.h'): config.get_output_header_filepath('sv_vpi_user.h'), config.get_include_filepath('vhpi_user.h'): config.get_output_header_filepath('vhpi_user.h'), config.get_include_filepath('vpi_user.h'): config.get_output_header_filepath('vpi_user.h'), }]), ('serializer', [models]), ('uhdm_forward_decl_h', [models]), ('uhdm_h', [models]), ('uhdm_types_h', [models]), ('vpi_listener', [models]), ('vpi_user_cpp', [models]), ('vpi_visitor_cpp', [models]), ('VpiListener_h', [models]), ('VpiListenerTracer_h', [models]), ] if args.parallel: with concurrent.futures.ThreadPoolExecutor(max_workers=8) as executor: results = list(executor.map(_worker, params)) else: results = [_worker(args) for args in params] print('... all done!') result = sum([0 if r else 1 for r in results]) if result: print('ERROR: UHDM model generation FAILED!') else: print('UHDM Models generated successfully!.') return result
def generate(models): visit_object_body = [] private_visitor_bodies = [] ignored_objects = set(['vpiNet']) for model in models.values(): modeltype = model['type'] if modeltype == 'group_def': continue classname = model['name'] if classname in ['net_drivers', 'net_loads']: continue vpi_name = config.make_vpi_name(classname) if vpi_name not in ignored_objects: visit_object_body.append( f' case {vpi_name}: visit_{classname}(obj_h, indent, relation, visited, out, shallowVisit); break;' ) private_visitor_bodies.append( f'static void visit_{classname}(vpiHandle obj_h, int indent, const char *relation, VisitedContainer* visited, std::ostream& out, bool shallowVisit) {{' ) baseclass = model.get('extends', None) if baseclass: private_visitor_bodies.append( f' visit_{baseclass}(obj_h, indent, relation, visited, out, shallowVisit);' ) itr_required = False private_visitor_body = [] if classname == 'part_select': private_visitor_body.extend( _get_implementation(classname, 'vpiParent', '1')) itr_required = True if modeltype != 'class_def': private_visitor_body.extend( _get_vpi_xxx_visitor('string', 'vpiFile', '1')) type_specified = False for key, value in model.allitems(): if key == 'property': name = value.get('name') vpi = value.get('vpi') type = value.get('type') card = value.get('card') type_specified = name == 'type' or type_specified private_visitor_body.extend( _get_vpi_xxx_visitor(type, vpi, card)) elif key in ['class', 'obj_ref', 'class_ref', 'group_ref']: vpi = value.get('vpi') card = value.get('card') private_visitor_body.extend( _get_implementation(classname, vpi, card)) itr_required = True if not type_specified and (modeltype == 'obj_def'): private_visitor_body.extend( _get_vpi_xxx_visitor('unsigned int', 'vpiType', '1')) if private_visitor_body: if itr_required: private_visitor_bodies.append(f' vpiHandle itr;') private_visitor_bodies.extend(private_visitor_body) private_visitor_bodies.append(f'}}') private_visitor_bodies.append('') visitors = [f' switch (objectType) {{' ] + sorted(visit_object_body) + [f' }}'] # vpi_visitor.cpp with open(config.get_template_filepath('vpi_visitor.cpp'), 'r+t') as strm: file_content = strm.read() file_content = file_content.replace('<OBJECT_VISITORS>', '\n'.join(visitors)) file_content = file_content.replace('<PRIVATE_OBJECT_VISITORS>', '\n'.join(private_visitor_bodies)) file_utils.set_content_if_changed( config.get_output_source_filepath('vpi_visitor.cpp'), file_content) return True
def generate(models): individual_model_schemas = {} flattened_model_schemas = [] root_schema_index = 2 root_schema = [] for model in models.values(): modeltype = model['type'] if modeltype == 'group_def': continue classname = model['name'] individual_model_schemas[classname] = [] Classname_ = classname[:1].upper() + classname[1:] Classname = Classname_.replace('_', '') if modeltype != 'class_def': individual_model_schemas[classname].append(('uhdmId', 'UInt64')) individual_model_schemas[classname].append(('vpiParent', 'UInt64')) individual_model_schemas[classname].append(('uhdmParentType', 'UInt64')) individual_model_schemas[classname].append(('vpiFile', 'UInt64')) individual_model_schemas[classname].append(('vpiLineNo', 'UInt32')) individual_model_schemas[classname].append(('vpiEndLineNo', 'UInt32')) individual_model_schemas[classname].append(('vpiColumnNo', 'UInt16')) individual_model_schemas[classname].append(('vpiEndColumnNo', 'UInt16')) root_schema.append(f' factory{Classname} @{root_schema_index} :List({Classname});') root_schema_index += 1 for key, value in model.allitems(): if key == 'property': if value.get('name') != 'type': vpi = value.get('vpi') type = value.get('type') card = value.get('card') individual_model_schemas[classname].append(_get_schema(type, vpi, card)) elif key in ['class', 'obj_ref', 'class_ref', 'group_ref']: name = value.get('name') type = value.get('type') card = value.get('card') if (card == 'any') and not name.endswith('s'): name += 's' name = name.replace('_', '') obj_key = 'ObjIndexType' if key in ['class_ref', 'group_ref'] else 'UInt64' individual_model_schemas[classname].append(_get_schema(obj_key, name, card)) if modeltype != 'class_def': # Process the hierarchy tree top-down stack = [] baseclass = classname while (baseclass): stack.append(baseclass) baseclass = models[baseclass]['extends'] capnpIndex = 0 flattened_model_schemas.append(f'struct {Classname} {{') while stack: for name, type in individual_model_schemas[stack.pop()]: if name and type: flattened_model_schemas.append(f' {name} @{capnpIndex} :{type};') capnpIndex += 1 flattened_model_schemas.append('}') flattened_model_schemas.append('') with open(config.get_template_filepath('UHDM.capnp'), 'r+t') as strm: file_content = strm.read() file_content = file_content.replace('<CAPNP_SCHEMA>', '\n'.join(flattened_model_schemas)) file_content = file_content.replace('<CAPNP_ROOT_SCHEMA>', '\n'.join(root_schema)) file_utils.set_content_if_changed(config.get_output_source_filepath('UHDM.capnp'), file_content) return True