[go: nahoru, domu]

Skip to content

Commit

Permalink
Few improvements to VpiListener and removing dead code
Browse files Browse the repository at this point in the history
* Introducing visited & callback to VpiListener (like UhdmListener)
  Also, merged the logic in vpi_listener into VpiListener itself to get
  access to both these containers easily in enter/leave callbacks.
* Removed parent and parentHandle parameters from VpiListener::enter/leave.
  The parameter itself was misleading since it was called 'parent' but
  it may not actually be the true parent of the object in the callback. The
  pointer was really the object right below the one on top of the callback
  hierarchy. The true parent is available via object->VpiParent() and access
  to the call hierarchy is available via callstack. Thus making both these
  parameters unnecessary.
* VpiListener also has a callback function (enter|leave)Any which gets
  called at most once for every visited object. For logic that's
  identical for a number of types, this is ideal place to implement it
  rather than having to override n number of functions and cloning the
  logic.
* Fixed up all VpiListener sub-classes like UhdmLint and SynthSubset
  • Loading branch information
hs-apotell committed Jun 8, 2022
1 parent db3298c commit ee1e456
Show file tree
Hide file tree
Showing 26 changed files with 686 additions and 1,727 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ set(uhdm-GENERATED_SRC
${GENDIR}/src/UHDM.capnp.c++
${GENDIR}/src/UhdmLint.cpp
${GENDIR}/src/UhdmListener.cpp
${GENDIR}/src/vpi_listener.cpp
${GENDIR}/src/VpiListener.cpp
${GENDIR}/src/vpi_user.cpp
${GENDIR}/src/vpi_visitor.cpp
)
Expand Down
4 changes: 2 additions & 2 deletions scripts/ElaboratorListener_cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ def _generate_module_listeners(models, classname):
listeners.append(f' auto clone_vec = serializer_->Make{Cast}Vec();')
listeners.append(f' inst->{method}(clone_vec);')
listeners.append( ' for (auto obj : *vec) {')
listeners.append( ' enterTask_func(obj, defMod, nullptr, nullptr);')
listeners.append( ' enterTask_func(obj, nullptr);')
listeners.append( ' auto* tf = obj->DeepClone(serializer_, this, inst);')
listeners.append( ' ComponentMap& funcMap = std::get<2>(instStack_.at(instStack_.size()-2).second);')
listeners.append( ' funcMap.erase(tf->VpiName());')
listeners.append( ' funcMap.insert(std::make_pair(tf->VpiName(), tf));')
listeners.append( ' leaveTask_func(obj, defMod, nullptr, nullptr);')
listeners.append( ' leaveTask_func(obj, nullptr);')
listeners.append( ' tf->VpiParent(inst);')
listeners.append( ' clone_vec->push_back(tf);')
listeners.append( ' }')
Expand Down
136 changes: 136 additions & 0 deletions scripts/VpiListener.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import config
import file_utils


def _get_listeners(classname, vpi, type, card):
listeners = []

if card == '1':
# upward vpiModule, vpiInterface relation (when card == 1, pointing to the parent object) creates loops in visitors
if vpi in ['vpiParent', 'vpiInstance', 'vpiModule', 'vpiInterface', 'vpiUse', 'vpiProgram', 'vpiClassDefn', 'vpiPackage', 'vpiUdp']:
return listeners

if 'func_call' in classname and vpi == 'vpiFunction':
# Prevent stepping inside functions while processing calls (func_call, method_func_call) to them
return listeners

if 'task_call' in classname and vpi == 'vpiTask':
# Prevent stepping inside tasks while processing calls (task_call, method_task_call) to them
return listeners

listeners.append(f' if (vpiHandle itr = vpi_handle({vpi}, handle)) {{')
listeners.append(f' listenAny(itr);')
listeners.append( ' vpi_free_object(itr);')
listeners.append( ' }')

else:
listeners.append(f' if (vpiHandle itr = vpi_iterate({vpi}, handle)) {{')
listeners.append( ' while (vpiHandle obj = vpi_scan(itr)) {')
listeners.append(f' listenAny(obj);')
listeners.append( ' vpi_free_object(obj);')
listeners.append( ' }')
listeners.append( ' vpi_free_object(itr);')
listeners.append( ' }')

return listeners


def generate(models):
private_declarations = []
private_implementations = []
public_implementations = []
classnames = set()

for model in models.values():
modeltype = model['type']
if modeltype == 'group_def':
continue

classname = model['name']
Classname_ = classname[:1].upper() + classname[1:]

baseclass = model.get('extends')

if model.get('subclasses') or modeltype == 'obj_def':
private_declarations.append(f' void listen{Classname_}_(vpiHandle handle);')
private_implementations.append(f'void VpiListener::listen{Classname_}_(vpiHandle handle) {{')
if baseclass:
Baseclass_ = baseclass[:1].upper() + baseclass[1:]
private_implementations.append(f' listen{Baseclass_}_(handle);')

for key, value in model.allitems():
if key in ['class', 'obj_ref', 'class_ref', 'group_ref']:
vpi = value.get('vpi')
type = value.get('type')
card = value.get('card')

if key == 'group_ref':
type = 'any'

private_implementations.extend(_get_listeners(classname, vpi, type, card))

private_implementations.append( '}')
private_implementations.append( '')

if modeltype != 'class_def':
classnames.add(classname)

public_implementations.append(f'void VpiListener::listen{Classname_}(vpiHandle handle) {{')
public_implementations.append(f' const {classname}* object = (const {classname}*) ((const uhdm_handle*)handle)->object;')
public_implementations.append(f' callstack.push_back(object);')
public_implementations.append(f' enter{Classname_}(object, handle);')
public_implementations.append( ' if (visited.insert(object).second) {')
public_implementations.append(f' listen{Classname_}_(handle);')
public_implementations.append( ' }')
public_implementations.append(f' leave{Classname_}(object, handle);')
public_implementations.append(f' callstack.pop_back();')
public_implementations.append(f'}}')
public_implementations.append( '')

any_implementation = []
enter_leave_declarations = []
public_declarations = []
for classname in sorted(classnames):
Classname_ = classname[:1].upper() + classname[1:]

any_implementation.append(f' case uhdm{classname}: listen{Classname_}(handle); break;')

enter_leave_declarations.append(f' virtual void enter{Classname_}(const {classname}* object, vpiHandle handle) {{}}')
enter_leave_declarations.append(f' virtual void leave{Classname_}(const {classname}* object, vpiHandle handle) {{}}')
enter_leave_declarations.append( '')

public_declarations.append(f' void listen{Classname_}(vpiHandle handle);')

# VpiListener.h
with open(config.get_template_filepath('VpiListener.h'), 'rt') as strm:
file_content = strm.read()

file_content = file_content.replace('<VPI_PUBLIC_LISTEN_DECLARATIONS>', '\n'.join(public_declarations))
file_content = file_content.replace('<VPI_PRIVATE_LISTEN_DECLARATIONS>', '\n'.join(private_declarations))
file_content = file_content.replace('<VPI_ENTER_LEAVE_DECLARATIONS>', '\n'.join(enter_leave_declarations))
file_utils.set_content_if_changed(config.get_output_header_filepath('VpiListener.h'), file_content)

# VpiListener.cpp
with open(config.get_template_filepath('VpiListener.cpp'), 'rt') as strm:
file_content = strm.read()

file_content = file_content.replace('<VPI_PRIVATE_LISTEN_IMPLEMENTATIONS>', '\n'.join(private_implementations))
file_content = file_content.replace('<VPI_PUBLIC_LISTEN_IMPLEMENTATIONS>', '\n'.join(public_implementations))
file_content = file_content.replace('<VPI_LISTENANY_IMPLEMENTATION>', '\n'.join(any_implementation))
file_utils.set_content_if_changed(config.get_output_source_filepath('VpiListener.cpp'), file_content)

return True


def _main():
import loader

config.configure()

models = loader.load_models()
return generate(models)


if __name__ == '__main__':
import sys
sys.exit(0 if _main() else 1)
12 changes: 10 additions & 2 deletions scripts/VpiListenerTracer_h.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import config
import file_utils
import VpiListener_h


def generate(models):
methods = VpiListener_h.get_methods(models, ' TRACE_ENTER; ', ' TRACE_LEAVE; ')
methods = []
for model in models.values():
if model['type'] not in ['class_def', 'group_def']:
classname = model['name']
Classname_ = classname[:1].upper() + classname[1:]

methods.append(f' virtual void enter{Classname_}(const {classname}* object, vpiHandle handle) {{ TRACE_ENTER; }}')
methods.append(f' virtual void leave{Classname_}(const {classname}* object, vpiHandle handle) {{ TRACE_LEAVE; }}')
methods.append('')

with open(config.get_template_filepath('VpiListenerTracer.h'), 'rt') as strm:
file_content = strm.read()
Expand Down
41 changes: 0 additions & 41 deletions scripts/VpiListener_h.py

This file was deleted.

6 changes: 3 additions & 3 deletions scripts/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,8 @@ def _get_DeepClone_implementation(model, models):
content.append(f'{classname}* {classname}::DeepClone(Serializer* serializer, ElaboratorListener* elaborator, BaseClass* parent) const {{')

if classname in ['begin', 'named_begin', 'fork', 'named_fork']:
content.append(f' elaborator->enter{Classname}(this, parent, nullptr, nullptr);')
content.append(f' elaborator->enter{Classname}(this, nullptr);')

if 'Net' in vpi_name:
includes.add('ElaboratorListener')
content.append(f' {classname}* clone = any_cast<{classname}*>(elaborator->bindNet(VpiName()));')
Expand All @@ -359,7 +359,7 @@ def _get_DeepClone_implementation(model, models):
content.append(' DeepCopy(clone, serializer, elaborator, parent);')

if classname in ['begin', 'named_begin', 'fork', 'named_fork']:
content.append(f' elaborator->leave{Classname}(this, parent, nullptr, nullptr);')
content.append(f' elaborator->leave{Classname}(this, nullptr);')

content.append(' return clone;')
content.append('}')
Expand Down
13 changes: 4 additions & 9 deletions scripts/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@
import uhdm_h
import uhdm_types_h
import UhdmListener
import vpi_listener
import vpi_user_cpp
import vpi_visitor_cpp
import VpiListener_h
import VpiListener
import VpiListenerTracer_h


Expand Down Expand Up @@ -63,17 +62,14 @@ def _worker(params):
elif key == 'UhdmListener':
return UhdmListener.generate(*args)

elif key == 'vpi_listener':
return vpi_listener.generate(*args)

elif key == 'vpi_user_cpp':
return vpi_user_cpp.generate(*args)

elif key == 'vpi_visitor_cpp':
return vpi_visitor_cpp.generate(*args)

elif key == 'VpiListener_h':
return VpiListener_h.generate(*args)
elif key == 'VpiListener':
return VpiListener.generate(*args)

elif key == 'VpiListenerTracer_h':
return VpiListenerTracer_h.generate(*args)
Expand Down Expand Up @@ -146,10 +142,9 @@ def _main():
('uhdm_h', [models]),
('uhdm_types_h', [models]),
('UhdmListener', [models]),
('vpi_listener', [models]),
('vpi_user_cpp', [models]),
('vpi_visitor_cpp', [models]),
('VpiListener_h', [models]),
('VpiListener', [models]),
('VpiListenerTracer_h', [models]),
]

Expand Down
Loading

0 comments on commit ee1e456

Please sign in to comment.