@@ -1470,22 +1470,17 @@ def wire_struct(wire_struct_spec):
14701470
14711471 1. Provide a driver for *each* component wire, for example::
14721472
1473- >>> byte = Byte(high=0xA, low=0xB)
1473+ >>> byte = Byte(high=0xA, low=0xB)
14741474
14751475 Note how the component names (``high``, ``low``) are used as keyword args for the
14761476 constructor. Drivers must be provided for *all* components.
14771477
14781478 2. Provide a driver for the entire ``@wire_struct``, for example::
14791479
1480- >>> byte = Byte(Byte=0xAB)
1480+ >>> byte = Byte(Byte=0xAB)
14811481
14821482 Note how the class name (``Byte``) is used as a keyword arg for the constructor.
14831483
1484- If the class name is not known, the special name ``_value`` can be used instead::
1485-
1486- >>> UnknownDynamicType = Byte
1487- >>> unknown_dynamic_type = UnknownDynamicType(_value=0xAB)
1488-
14891484 Accessing Slices
14901485 ----------------
14911486
@@ -1620,6 +1615,41 @@ class CacheLine:
16201615
16211616 No values are specified for ``input_byte`` because its value is not known until
16221617 simulation time.
1618+
1619+ Generic Usage
1620+ -------------
1621+
1622+ .. doctest only::
1623+
1624+ >>> import pyrtl
1625+ >>> pyrtl.reset_working_block()
1626+
1627+ Functions can work with ``@wire_struct`` instances generically. For example, we can
1628+ define a function that accepts any ``@wire_struct`` and returns the same type of
1629+ ``@wire_struct``, with all of the argument's fields bitwise-inverted::
1630+
1631+ >>> def invert_all_fields(output_name, any_wire_struct):
1632+ ... # Retrieve the argument wire_struct's class.
1633+ ... OutputClass = type(any_wire_struct)
1634+ ... # Instantiate that class, specifying its full value.
1635+ ... return OutputClass(name=output_name, _value=~any_wire_struct)
1636+
1637+ >>> input_byte = Byte(name="input_byte", concatenated_type=pyrtl.Input)
1638+ >>> output_byte = invert_all_fields("output_byte", input_byte)
1639+
1640+ >>> sim = pyrtl.Simulation()
1641+ >>> sim.step({"input_byte": 0})
1642+ >>> hex(sim.inspect("output_byte"))
1643+ '0xff'
1644+
1645+ ``invert_all_fields`` uses ``type(any_wire_struct)`` to retrieve the argument
1646+ ``@wire_struct``'s class, and instantiates that class for the function's return
1647+ value.
1648+
1649+ This uses the special constructor ``kwarg`` ``_value``, rather than the name of the
1650+ class, to specify the full value for the returned ``@wire_struct`` object. In this
1651+ example, we must use ``_value`` instead of the name of the class (``Byte``) because
1652+ ``any_wire_struct`` might not be a ``Byte``.
16231653 """
16241654 # Convert the decorated class' annotations (dict of attr_name: attr_value)
16251655 # to a list of _ComponentMetas.
0 commit comments