Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multipack support #116

Merged
merged 87 commits into from Jun 11, 2022
Merged

Multipack support #116

merged 87 commits into from Jun 11, 2022

Conversation

ducky64
Copy link
Collaborator

@ducky64 ducky64 commented May 21, 2022

Overview

Add multipack device (eg, 4-resistor array as a single board component), where individual blocks across the design tree can be packed into this multipack device. The multipack device is otherwise a normal Block and defined as such (including support for parameters, generators, and ports.

Internally, multipack is implemented through two tunneling (cross-hierarchy) constructs: export tunnel (where the port being exported to can be anywhere in the hierarchy - so for example we can have a resistor but the packed resistor is "inside" it). Typically, the packed device will be at the top of the design, while the element devices are across the design tree. The multipack device should enforce that the devices can be packed and export the relevant parameters (for example, a multipack resistor's resistance spec should be the intersection of all the element resistances, and once a part is selected should set the individual element's resistances to be the packed resistance).

Resolves #74
Resolves #115

Examples

Example multipack definition for a resistor array:

class ResistorArrayElement(Resistor): # to avoid an abstract part error
  pass

class ResistorArray(PassiveComponent, MultipackBlock):
  """An n-element resistor array, where all resistors have the same resistance and power rating."""
  def __init__(self, count: IntLike = 0) -> None:
    ...
    elements = self.PackedPart(PackedBlockArray(ResistorArrayElement()))
    self.a = self.PackedExport(self.elements.ports_array(lambda x: x.a))
    self.b = self.PackedExport(self.elements.ports_array(lambda x: x.b))
    self.resistances = self.PackedParameter(self.elements.params_array(lambda x: x.resistance))
    self.powers = self.PackedParameter(self.elements.params_array(lambda x: x.power))

    self.actual_resistance = self.Parameter(RangeExpr())
    self.actual_power_rating = self.Parameter(RangeExpr())  # per element
    self.unpacked_assign(self.elements.params(lambda x: x.actual_resistance), self.actual_resistance)
    self.unpacked_assign(self.elements.params(lambda x: x.actual_power_rating), self.actual_power_rating)

  # part selection and generator code omitted

Example top-level packing definition using that resistor array:

class LedMatrix(DesignTop):
  ...

  # generates both export and assign tunnels, as well as the Resistor -> ResistorArrayElement refinements
  def multipack(self) -> None:
    self.matrix_res1 = self.PackedBlock(ResistorArray())
    self.pack(self.matrix_res1.elements.allocate('0'), ['matrix', 'res[0]'])
    self.pack(self.matrix_res1.elements.allocate('1'), ['matrix', 'res[1]'])
    self.pack(self.matrix_res1.elements.allocate('2'), ['matrix', 'res[2]'])

    self.matrix_res2 = self.PackedBlock(ResistorArray())
    self.pack(self.matrix_res2.elements.allocate('0'), ['matrix', 'res[3]'])
    self.pack(self.matrix_res2.elements.allocate('1'), ['matrix', 'res[4]'])

Detailed changelog

Frontend changes:

  • Add multipack constructs to DesignTop. Since multipack is kind of in-between the design tree and refinements, it is defined in its own block / method.
    • multipack() adds packing data into an internal data structure, which is then generated into IR constructs (exported tunnel and assign tunnel) in proto generation and refinements (instance refinements for the element type).
    • self.PackedBlock is used to defined a multipack device at the top level (analogous to self.Block), then self.pack is used to set the multipack device's elements to anywhere in the design hierarchy (using List[str] / DesignPath).
    • I know the IR generation code is awful and could use serious refactoring.
  • Add MultipackBlock as an extension of Block - a block that is a packed device, can define packed elements (possibly n-element PackedBlockArray), and defines rules of how the packed elements export/assign into its ports and parameters.
    • Both assignment directions are supported, specs from the element to the multipack device (eg, resistance spec, "packed assign"), and results from the multipack device to the element (eg, actual selected part resistance, "unpacked assign")
  • Infrastructure: in the compiler, don't re-elaborate classes to get refinements. This is needed since multipack adds refinements, but the multipack method only runs as part of compilation (as opposed to on constructor).
  • Updates LED matrix example with a packed resistor array.
    • Add basic firmware that runs the LED matrix. It runs the ESP32-C3 in AP mode and serves up a webpage to change the display.
  • In refinements, add type alias for List[str] -> DesignPath
  • Add unit tests

IR & compiler changes:

  • Add ExportedTunnel, where the internal-side port must be a subblock port (like a typical export) but the external-side port can be anywhere within the subtree
    • Implement this in the compiler, both for where the internal-side port is a direct reference or an Allocated reference. This was surprisingly easy given the current compiler structure
    • Add an AllocatedTunnelExport PortConnection type, which is structured like AllocatedConnect but only supporting export connections.
    • Add support for this in the netlister, also surprisingly easy
  • Add AssignTunnel, where the expression can contain references arbitrarily deep in the subtree. (not that Assign currently checks for locality - but it may in the future)
  • Add Array ValueExpr, that takes a collection of ValueExprs and packs them into an array. This is needed for multipack array, eg to pack 4 resistors, this takes each one's resistance and packs it into the packed-resistor's resistances array-parameter.
  • Unit tests!

Library changes:

  • Add ResistorArray abstract type, for a packed resistor array.
  • Add JlcResistorArray, which parses (some) resistor arrays from the JLC parts tables. This matches on the part number, in part to determine whether it's concave or convex type.
  • Have the pin mapper also dump resource names for bundle element resources - which are closer to what is expected in firmware when defining the HAL.
  • Fix a bug in the ESP32-C3 definition where IO8 was pulled down (instead of up - needed to enter download mode). Note that the board was not updated, as the bug was only discovered from getting hardware back, and this did not seem to justify a board spin.

Future work:

  • Clean up frontend multipack implementation (Put out the various code style / structural dumpster fires #118) - perhaps make so that there is a unified type hierarchy (instead of supporting all of ConstraintExpr and PackedBlockParamArray and PackedBlockParam - and having all those if cases) once it gets to DesignTop?
  • Add a netlister construct that enforces the incoming ports are part of the same net - for example, if we had a packed opamp and needed to merge nets.
  • Maybe this could be a way to do things like multipack DACs or ADCs? Where the analog line is part of the design tree, but the digital line is through the multipack device? Much more thought needed here.
  • Is it possible to unify the exportedTunnel and (normal) exported paths in the compiler?

@ducky64 ducky64 mentioned this pull request May 22, 2022
@ducky64 ducky64 marked this pull request as ready for review June 1, 2022 19:59
@ducky64 ducky64 requested a review from rohit507 June 1, 2022 19:59
@ducky64
Copy link
Collaborator Author

ducky64 commented Jun 4, 2022

Latest set of changes add the self.PackedExport (combining self.Port(...) and self.packed_export(...) constructs - analogous to self.Export(...)) and the self.PackedParameter (like the above, but for parameters - required for generators, since generators require either ArgParameter or this).

This should be ready for review.

Copy link
Collaborator

@rohit507 rohit507 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable to me.

@ducky64 ducky64 merged commit 96b5a5d into master Jun 11, 2022
@ducky64 ducky64 deleted the multipack branch June 11, 2022 07:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

In refinements, add a DesignPath type-alias for List[str] Support multipack devices
2 participants