def generate(models): types = set() for model in models.values(): for key, value in model.allitems(): if key == 'property': name = value.get('name') type = value.get('type') card = value.get('card') if (name != 'type') and (type != 'any') and (card == 'any'): types.add(type) elif key in ['class', 'obj_ref', 'class_ref', 'group_ref']: card = value.get('card') if card == 'any': type = 'any' if key == 'group_ref' else value.get('type') types.add(type) containers = [] for type in sorted(types): containers.append(f' typedef std::vector<{type}*> VectorOf{type};') containers.append(f' typedef std::vector<{type}*>::iterator VectorOf{type}Itr;') containers.append('') containers = '\n'.join(containers) with open(config.get_template_filepath('containers.h'), 'r+t') as strm: file_content = strm.read() file_content = file_content.replace('<CONTAINERS>', containers) file_utils.set_content_if_changed(config.get_output_header_filepath('containers.h'), file_content) return True
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): types = '\n'.join([f' {name} = {id},' for name, id in get_type_map(models).items()]) with open(config.get_template_filepath('uhdm_types.h'), 'r+t') as strm: file_content = strm.read() file_content = file_content.replace('<DEFINES>', types) file_utils.set_content_if_changed(config.get_output_header_filepath('uhdm_types.h'), file_content) return True
def generate(models): methods = get_methods(models, '', '') with open(config.get_template_filepath('VpiListener.h'), 'r+t') as strm: file_content = strm.read() file_content = file_content.replace('<VPI_LISTENER_METHODS>', '\n'.join(methods)) file_utils.set_content_if_changed( config.get_output_header_filepath('VpiListener.h'), file_content) return True
def generate(models): classnames = [model['name'] for model in models.values()] headers = '\n'.join( [f'#include "uhdm/{classname}.h"' for classname in classnames]) with open(config.get_template_filepath('uhdm.h'), 'r+t') as strm: file_content = strm.read() file_content = file_content.replace('<INCLUDE_FILES>', headers) file_utils.set_content_if_changed( config.get_output_header_filepath('uhdm.h'), file_content) return True
def generate(models): classnames = [ model['name'] for model in models.values() if model['type'] != 'group_def' ] declarations = '\n'.join([ f'class {classname};' for classname in sorted(classnames) if classname != 'BaseClass' ]) with open(config.get_template_filepath('uhdm_forward_decl.h'), 'r+t') as strm: file_content = strm.read() file_content = file_content.replace('<UHDM_FORWARD_DECL>', declarations) file_utils.set_content_if_changed( config.get_output_header_filepath('uhdm_forward_decl.h'), file_content) return True
def generate(models): relationships = defaultdict(set) for model in models.values(): if model['type'] not in ['group_def']: thisclass = model['name'] baseclass = model.get('extends') or 'BaseClass' relationships[baseclass].add(thisclass) file_content = StringIO() stack = [('BaseClass', 0)] while stack: thisclass, indent = stack.pop() file_content.write(' ' * indent) file_content.write(thisclass) file_content.write('\n') stack.extend([(subclass, indent + 2) for subclass in sorted( relationships.get(thisclass, set()), reverse=True)]) file_utils.set_content_if_changed( config.get_output_header_filepath('class_hierarchy.txt'), file_content.getvalue()) 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