horizon-eda / horizon

Horizon is a free EDA package
https://horizon-eda.org/
GNU General Public License v3.0
1.09k stars 79 forks source link

Idea: Multiple MPNs/Manufactures per Part #285

Open carrotIndustries opened 5 years ago

carrotIndustries commented 5 years ago

For some parts, you'd want to make the final decision on manufacturer/MPN at the time of actually purchasing the parts instead of specifying the exact MPN in the schematic.

Some sample use cases:

Same part available with multiple MPNs

https://github.com/horizon-eda/horizon-pool/pull/111 the part TPIC6C595D is available with these MPNs

Regardless of which MPN you'll order, you'll always get the same physical thing.

Meta parts

For jellybean passives one usually doesn't care about the exact MPN at the time of design. Instead, one would pick the MPN at the time of exporting the BOM based on what's available on the market, perhaps aided by distributor's APIs. Leveraging octopart's CPL naming scheme for these meta parts seems reasonable.

Possible implementations

The easy way

Make it possible to specify alternate MPNs/Manufacturers for parts. The netlist/schematic/board will show the default MPN, only the BOM export will need to know of this. Perhaps add an option to components to specify that a particular MPN is desired.

The elaborate way

More or less the same as above, but instead of just specifying alternate manufacturers/MPNs, add these as regular parts and tell the base/meta part that these parts are equivalent.

I'm gravitating towards the easy way as it's less overhead for the user and doesn't introduce that much overall complexity.

fruchti commented 5 years ago

Very good point. Considering the case of my PR, I'd prefer the “easy way“ as well, since it's faster to create parts this way and the intent is clearer during PR review. As all fields except for the MPN would be obviously identical, the intended use would be easier to grasp, too.

It should be clarified which parts should be entered as “alternate MPNs“, though. The only sensible use case coming to my mind are different packaging variants, everything else won't be “the same physical thing”. IMHO, jelly bean parts where the exact manufacturer and MPN is chosen only later don't fit into this model very well, since at least the manufacturer would have to change, too.

Maybe the use cases generic part (10 kΩ 1% 0603 resistor of any manufacturer) and packaging variants (TPIC6C595DG4 vs. TPIC6C595DRG4) are different enough to justify different solutions. Generic/jelly bean parts produced by a lot of manufacturers can and will have subtle differences and I wouldn't consider them “the exact same part” while different packaging variants only matter during production.

carrotIndustries commented 5 years ago

, since at least the manufacturer would have to change, too.

I updated the title to better reflect my intent. Unfortunately, I haven't yet come across a short and catchy term for the MPN/Manufacturer pair. Some ERP/PLM systems call it "Manufacturer Equivalent Part" (MEP), but I don't think that this term does a good job at describing an MPN/Manufacturer pair.

Some background on jellybean parts:

In a commercial setting with the parts library linked to ERP/PLM systems, each part gets assigned a part number independent from the MPN and has a list of approved manufacturers/MPNs. For ICs and such that's usually just one item, but for jellybean passives, someone sat down and compiled a list of MPNs deemed suitable for this part.

That way, the designer more or less places a 0603 10k 1% resistor and it's up to the purchasing department / contract manufacturer which MPN is actually placed on the PCB.

Any different ideas on how to enable such workflow differently? Yes, the two problems aren't the same, but to me at least the "easy way" solution seems to be acceptable for both.

frmdstryr commented 5 years ago

What if you could define parametric search criteria (eg as metadata) with the part in the actual schematic/layout so a query can be run to find alternatives? The basic requirements is there already eg footprint, unit, but a more generic way would need added to define what a replacement can be.

Not sure how well it would work, but its a different way.

I would want the datasheets will be changed too if going with the easy way. A simple m2m part to part relation table would be sufficient.

fruchti commented 5 years ago

While the packaging variants guarantee that the part is exactly the same, the “generic part” use case offers concrete MPNs which are the same most of the time and, as you say, would have to be individually approved in a commercial setting, sometimes even individually per BOM. In other words, the alternative parts recommended via the community-driven pool could only be used after cross-checking with the approved list of alternatives. Which would limit its usefulness a lot.

It boils down that for me, both ways you describe communicate the intent “I have this concrete part, I want something alike”, which is different to “I want a concrete part for my generic need”.

IMHO, this intent would be best communicated with the solution @frmdstryr proposes. You could maybe even place a generic capacitor and specify what you need, e.g. package = 0603, capacity = 1 µF, voltage rating > 10 V and later query the parametric table for a concrete MPN.

atoav commented 5 years ago

Multiple Manufacturers/MPNs per Part

I like the simple solution when it comes to the multi manufacturer proposal. Why shouldn't this be a field similar to the tag field if there are indeed parts with the same MPN that share multiple manufacturers? I think the only question is how to display it within the existing list system? One entry with a list of manufacturers? Two seperate entries that point to the same thing?

When I think more about this, we already solved a similar problem with your great idea to split parts into modular components (Symbol, Unit, Entity, Package). I wonder if there would be some way to stay true to that concept..? No ideas from my side..

Edit: another thought – Multiple MPNs could be avoided with inheritance. If we allow parent parts without manufacturer and then inherit multiple different manufacturers/MPNs from it it would solve that problem elegantly.

Jellybeans

I have the feeling that a legit Pick generic part → Pick more specialized variant workflow could be a good solution to this. So first for example you select a Resistor 0805 with a certain value/tolerance and then you can (if you like) specific specimen that fit that variant (e.g. a RT0805FRE0768KL Thin film with 50ppm/C° etc.) and if you don't select a specific variant, you just go with the generic one.

This would have some great advantages:

I'd see this as a big chance to improve the user experience if implemented right.

The challenge here is how to link the specific parts to the generic ones, but I think it is a problem that can be managed.

frmdstryr's proposal

Edit: Adding a bit about the proposal of @frmdstryr : I believe a simple relationship table is too rigid and hard to maintain in a decentralized fashion (which obviously is the current mode of contribution). Maybe it would be better to relate attributes to each other.

Think something like:

This part takes all parts as an alternative that match these criteria:
- Tags: resistor, smd
- Package: 0805
- value: 100k
- tolerance: 1%

By this way you could define in your part what the alternative should be.

Generic Parts

Alternatively you go the other route as proposed by me above: generic parts. Each specific part (e.g. RT0805FRE0768KL) has to link a generic part (e.g. Resistor 0805 68k) and that way you would get alternatives just by looking who has the same "parent". You could then additionally compare by other attributes from the parametric table.

This is probably easier to maintain than the parts-centric approach, I think. But I didn't really give it a long hard think, so don't hessitate to disagree.

carrotIndustries commented 5 years ago

First of all, we need too figure out if we want to have a set of generic parts in the pool that can somehow be mapped to orderable parts or if we want to only one part for each entity/package combination and allow the user to specify parametric data on each component in the schematic.

I much prefer the first option as it makes keeping the schematic consistent a lot easier.

That way we need a method of associating Manufacturer and MPN to a generic part. Based on the previous comments we have these options

In other words, the alternative parts recommended via the community-driven pool could only be used after cross-checking with the approved list of alternatives. Which would limit its usefulness a lot.

So perhaps store the list of oderable parts for generic part separately from the part itself so it's easier to have a custom list in place?

atoav commented 5 years ago

Add orderable part as usual and tell it that it can be used in place of a specific generic part

This is roughly what I imagined. So each orderable part references one (or more) generic parts and can be exchanged – either for this generic part – or for other orderable parts that reference the same generic part.

My idea would be you can either:

This process of replacement should be one, where the user can select from the list of orderable parts that fit the parent. So if you placed the generic part TL072 SOIC-8 can then select from the list of parts who reference TL072 SOIC-8 as a generic parent part, so TL072ACD, TL072ID and so on.

So perhaps store the list of oderable parts for generic part separately from the part itself so it's easier to have a custom list in place?

So basically the question is whether we describe the relationship as Orderable Part → Generic Parts, as the inversion of the thing before Generic Part → Orderable Parts or as some unrelated list that just references these relations completely independent of the parts.

I think the independent list solution is flexible (allows users to override it etc), but could ultimatly require more work to maintain compared to a part-centric approach. Mostly based on intuition I'd favour the Orderable Part → Generic Parts solution over all the others.

If we want to take @fruchti concerns serious, we could add user-tags to parts that allow users to flag parts as approved to be able to filter the list of alternative lists based on the status of these flags.

fruchti commented 5 years ago
  • Use parametric data for linkage (too fragile IMO)

Could you elaborate why this would be fragile? I see the nice opportunity to link generic parts to parametric tables (and generic parts not associated to a parametric table wouldn't be allowed). Specifying the relevant parameters with a generic part would naturally convey the design intent and the parametric search used to place an orderable part would be flexibly restricted (more flexible than a fixed list of parts).

This would be limited to very few cases of parts, like passives and LEDs, though. But these cover the most important cases, IMHO, while generic parts for ICs like @atoav describes them

So if you placed the generic part TL072 SOIC-8 can then select from the list of parts who reference TL072 SOIC-8 as a generic parent part, so TL072ACD, TL072ID and so on.

sound (in a generalised case, to be fair) like a hierarchy of inheritances to me (Generic dual op ampGeneric TL072Generic TL072ATL072ACD by TI). While having such a hierarchy might be useful it'd be a reintroduction of categories. Consequently, I'd keep this list flat.

So perhaps store the list of oderable parts for generic part separately from the part itself so it's easier to have a custom list in place?

Additional thought: This list could even be overridden per project and be used for alternatives. I'm not sure, though, if this simple per-part alternative placement is useful in a professional context or a more generic solution would be needed for this use case.

My conclusion

I think there are three main use cases with their own “optimal” solution.

While I don't know if the last case is worth having, I think the first two are very important and should be kept separate.

carrotIndustries commented 5 years ago

While I don't know if the last case is worth having, I think the first two are very important and should be kept separate.

Yes, the last one is out of scope for this issue.

Packaging variants/different order numbers for the “same physical thing”.

Okay, I think we can agree on this one and I'll have a go at implementing it.

Most of the time, a generic part would be a capacitor or resistor for me, where I specify the capacitance/resistance (and maybe some other ratings) and am done for the present.

I think, we have two distinct use cases:

Having all of these reference a single generic 10k 0603 resistor that'll be mapped to an orderable part based on parametric data during BOM generation would be acceptable

atoav commented 5 years ago

Good analysis.

Would it be a viable solution to warn the user on BOM export that there are parts left that are non orderable? Or maybe we could mark these in a certain way? I come mostly from a DIY background and there often just some value and a package would be "enough". A proper orderable part is better – agreed, but if it is e.g. 100k 0805 1% I don't care too much, because there is a reel on my workbench and if I really need something special, I can just put it into the schematic.

I think we should make it as easy as possible to use proper orderable parts with MPNs, but we should allow for generic parts as well. The change between these two should be straightforward.

Going from a generic part to a orderable part means you want to do one of two things:

So having something automatically selected for you is obviously not a good idea at this point, because it is about beeing making specific choices and not about ticking the box of having selected a orderable part.

Basing that reference on a best-guess match based on parametric data isn't really viable, especially since one can arbitrarily modify each components data.

Maybe it would be enough to automatically set certain filters in the parametric search window based on the parametric data of the generic part. So let's say I have a generic 100k 0805 1% and I want to select a orderable part for it. It could look like this:

  1. I right-click the generic part and select "Replace Part" or so
  2. A window opens that looks like the parts browser. Because the generic part uses the resistor table it opens the resistor section and has some fields pre-selected: value is 100k, tolerance is 1%, package is 0805
  3. I select a fitting part, narrow down my search, widen it or even change the part completely.

Maybe this means we should think about what generic parts should look like. Should they be in the list like now? Or should you be able to set the values more freely in the schematic (maybe constraint to the E-Series)?

carrotIndustries commented 5 years ago

I right-click the generic part and select "Replace Part" or so

I've had in mind to keep the generic parts in the netlist and do the mapping to proper parts in the bom export, so each generic part only needs to be mapped once.

fruchti commented 5 years ago

Maybe it would be enough to automatically set certain filters in the parametric search window based on the parametric data of the generic part.

This is exactly how I imagined it, sorry if that wasn't clear. The parametric data used to “specify” a generic part could also be kept when replacing it with a concrete MPN and would be visible in the exported BOM. If the chosen part isn't available, finding a suitable alternative would be easier this way.

I've had in mind to keep the generic parts in the netlist and do the mapping to proper parts in the bom export, so each generic part only needs to be mapped once.

I assume because the schematic would capture the design intent and the choice of exact MPN might be arbitrary based on the relevant parameters? I don't know if we should break up the exact 1:1 correspondence between schematic and BOM for this, though.

carrotIndustries commented 5 years ago

I don't know if we should break up the exact 1:1 correspondence between schematic and BOM for this, though.

That was more or less the whole idea of this issue. Not having to change the netlist if one particular 100nF 0603 capacitor happens to be out of stock. Having an extra step that can optionally map generic parts to orderable ones during BOM generation would do it.

fruchti commented 5 years ago

Good point. This could also be @atoav's proposed warning dialogue “There are still some generic parts left in your BOM”, and be very constructive at that with the selection box “Here's a list of concrete MPNs for this part, do you want to select one MPN or multiple alternatives?”

The “concrete MPN” selection window could also be reused for the replacement of a generic by a concrete part in the schematic. This use case, where you'd first place a generic part but then the exact manufacturer/series turns out to matter for the circuit's function, would be way less frequent, though.

carrotIndustries commented 5 years ago

The “concrete MPN” selection window could also be reused for the replacement of a generic by a concrete part in the schematic.

For my purposes, that's out of scope for now.

“Here's a list of concrete MPNs for this part, do you want to select one MPN or multiple alternatives?

Ok, suppose we've placed a generic 10k 0603 0.1W resistor, how do we arrive at the real MPNs? List of approved parts or parametric match? From an implementation point of view, the first one would be easier and for passives, I don't think that anyone would object if the pool made some recommendations for real parts.

carrotIndustries commented 5 years ago

See https://github.com/horizon-eda/horizon/tree/orderable_MPNs for an idea on how the orderable MPN thing could look like.

atoav commented 5 years ago

Ok this is quite interesting. I tried to map my TL072 (by Ti, DIP-8, Base) to it's orderable MPNs for starters. I took some screenshots to speed up the discussion:

This is from the Pool's Part Editor Window:

2019-07-14 20_39_09-Part Editor

This is from within the Schematic Editor:

2019-07-14 20_41_18-Schematic - Interactive Manipulator

Thoughts

There is not much to complain about when it comes to the UI implementation of this for now. As far as I understood, this is basically just mapping orderable MPNs (not actual parts!) to the selected part. I like that, because it would reduce the weight of the pool by quite some margin and we would get rid of silly inheritance, where only the MPN differs from the base part (like with my TL072).

This means we would need a standard which MPNs should be allowed there. For that TL072 DIP-8 it is quite clear on first glance. Multiple Manufacturers would still be multiple parts here, but nevermind. What about a hypothetical 0805 resistor where one value has different MPNs depending on the tolerance? How would this go together with the parametric data? Or is the scope strictly for parts where only the MPN differs?

Organization

This would mean we would have the following "tools" at our disposal to organize parts:

Part Inheritance

Description: A (child) part can inherit attributes from a (parent) base part good for: parts where most things should be the same as with the base part, but differ in multiple aspects (e.g. tags, description, 3D-model, etc). bad for: parts where only the MPN changes

Orderable MPNs

Description: A part can specify a list of orderable MPNs which can be selected at BOM export good for: parts where the child-parts would only differ in MPN bad for: grouping parts with any differing parameter together, searchable?

Tags

Description: A part can have one or more tags, which allows for groups good for: any kind of ad hoc grouping of parts, good searchability bad for: anything that would require a ton of tags to be precise, easily forgotten by part creators

Parametric Data

Description: Parts can have parametric data as specified in the pools table .json, which allows for parametric searches and filtering good for: huge numbers of passives, that mostly differ in some parameters, sublime searchability bad for: easy to get wrong (units, no UI), requires more work to do "right" unless scripting is used

When I list them like that, they seem to cover many bases and I would probably miss any of these, were they gone. However I still have the gut feeling that there could be a more "unified" solution lurking somewhere in the deep, I am just not sure what it could be.

Goals

Maybe we should also think about this in terms of goals? Of course you also have speed, performance etc.

Goal Description
searchability How easy is it to find any given part?
browseability How easy is it to find parts, that you don't know about yet?
assignability How easy is it to find fitting alternative parts for a given part?
extendability How easy is it to add parts and keep them structured?
low cognitive overhead How hard are the concepts to grasp?
maintainability How easy is it to keep a consistent system, considering multiple contributers?
modularity How easy is it to reuse parts that already exist?
carrotIndustries commented 5 years ago

I tried to map my TL072 (by Ti, DIP-8, Base) to it's orderable MPNs

Watch out, the TL072BC and TL072AC are different parts (likely different binning, see offset voltages), so they still need to be individual parts in the pool.

Or is the scope strictly for parts where only the MPN differs?

Yes, only different packaging (as in tape vs tube) variants. In the case of a TL072ACP in PDIP, that'd be the TL072ACP and TL072ACPE4 listed as orderable MPNs.

The generic part feature (intended only for passives) is yet to come, most likely in the way that a specific part can specify that it's a substitute for a generic part. I still need to figure out if this is really a 1 to n relation or if an m to n relation could be useful (one specific part can be a substitute for more than one generic part).

atoav commented 5 years ago

Watch out, the TL072BC and TL072AC are different parts (likely different binning, see offset voltages), so they still need to be individual parts.

Good catch, but I did it just for testing purposes anyways, I already did a hard reset on it, because I suspected that I need to figure out how to use that feature.

Yes, only different packaging (as in tape vs tube) variants. In the case of a TL072ACP in PDIP, that'd be the TL072ACP and TL072ACPE4 listed as orderable MPNs.

Okay that is a little stricter than I would have guessed, but it makes sense from a clarity standpoint so I am okay with it.

I still need to figure out if this is really a 1 to n relation or if an m to n relation

My feeling is that a m to n relation could be useful alone for the reason of avoiding duplicate parts that only differ in the generic part they are mapped to. I have no good example where this really would be needed, but one example: generic parts with differing degree of specificity, e.g. Resistor, 0805 Resistor and 0805 Resistor Thin Film. Even if we would decide against allowing such a thing in the community pool, it could certainly be useful for other ideas of pool organization.

Maybe there are other examples that make even more sense..

fruchti commented 5 years ago

See https://github.com/horizon-eda/horizon/tree/orderable_MPNs for an idea on how the orderable MPN thing could look like.

Looks good! Minor nitpick: I would rename the “(default)” in the BOM export window to something like “(base)” to make clear this might actually not be a orderable MPN (e.g. if no orderable MPNs without packaging suffixes exist).

@atoav: Great summary! Something like this should be part of the documentation to help new users understand the different inter-part relation features.

Ok, suppose we've placed a generic 10k 0603 0.1W resistor, how do we arrive at the real MPNs? List of approved parts or parametric match?

Although I still think the parametric match approach has some beauty to it, I now think the simplicity and universality of a simple inheritance-like mechanism are preferable.

From a schematic entry viewpoint: Specifying “I need an electrolytic cap with > 100 µF, > 48 V and ESR < 1 Ω here” directly in the schematic is nice, but elaborating the considerations with a simple text field is just as quick and only misses the assistance for part filtering.

From a pool management viewpoint: Parametric filtering is inherently limited to passives with associated parametric tables, while a simple list-based approach could replace all “(base part)”s currently used for inheritance in the pool (which always struck me as a sign of a missing feature).

atoav commented 5 years ago

Something like this should be part of the documentation to help new users understand the different inter-part relation features.

Thanks I actually have a note that says exactly this sticking on the wall : )

endofexclusive commented 5 years ago

I have tried the new MPN functionality in the branch, and believe it can be very useful. Did you consider the term MPN alias instead of Orderable MPNs?

carrotIndustries commented 5 years ago

while a simple list-based approach could replace all “(base part)”s currently used for inheritance in the pool (which always struck me as a sign of a missing feature).

Can you elaborate on that? Having a specific 10k 0603 resistor inherit from a generic 10k 0603 resistor is a bit too rigid as changing a part's base part isn't supported once the part has been created.

I would rename the “(default)” in the BOM export window to something like “(base)”

done in 782a4018895e6f67baaa63a3457bf9b25ac165fe

atoav commented 5 years ago

while a simple list-based approach could replace all “(base part)”s currently used for inheritance in the pool (which always struck me as a sign of a missing feature).

I am also curious, because the Base-Part stuff also strikes me as a bit unwieldy at times and I am not sure if it is the most elegant solution to the issue. But maybe it is just a UX issue? So what makes it feel weird is both how base parts look like and how we have to create them:

  1. Think about a hierarchy of parts
  2. For each package variant create a base part and add data to it
  3. For each base part create n child parts inheriting from it and select the fields it inherits or overwrite fields that are not meant to be inherited

Downsides of the current UX

Scripting

When I generate parts using scripts I get the ability to change many parts and their fields at once, for generation I use a mixture of template parts and a spec file, that lists the MPNs their hierarchy and additionally changed fields (e.g. a "tag append": ["foo", "bar"] or a "description prefix": "foo bar", for a example check below at ¹). The changed fields can act on a MPN's children and on individual MPNs. This way I can change the hierarchy and inheritance details with a high granularity basically in one place, while I can still just go and edit the template file in horizon if I like to.

Single Parts vs Part Families

It boils down to the difference between editing single parts and editing a part family. Editing single parts works like a charm right now (except maybe the inability to change base parts after the fact), but editing part families defenitly needs some love.

This is my main issue I have right now with the pool editor: it is easy to edit one part, but time intensive to edit many and changing hierarchies is not really possible.

What do we do with base parts?

They can't be actual orderable parts. But wouldn't that mean they should be hidden in the Parts Chooser? Or should we treat them like the parts with Orderable MPN and use their kids as orderable MPN? What happens when somebody places a base part on a schematic?


¹ A stripped down example could look like this:

- Foo (Base): "tag append": "x", "description": "Base Foo part", "child description replace": ["Base", ""]
    - Foo 23
    - Foo 42
    - Foo 54: "tag append": "automotive"
- Bar (Base)
    - Bar 23
    - Bar 42
    - Bar 54

Here Foo (Base) gets a tag (x) and a description. The "Base" in the descriptions of the child parts gets replaced with an empty string. The child part "Foo 54" has an extra tag.

fruchti commented 5 years ago

Did you consider the term MPN alias instead of Orderable MPNs?

This would imply that the main MPN of the part is an orderable MPN. As I understood it, that might not be the case, e.g. when no order numbers without packaging suffixes exist.

while a simple list-based approach could replace all “(base part)”s currently used for inheritance in the pool (which always struck me as a sign of a missing feature).

Can you elaborate on that? Having a specific 10k 0603 resistor inherit from a generic 10k 0603 resistor is a bit too rigid as changing a part's base part isn't supported once the part has been created.

I didn't know that the base part couldn't be changed after creating an inheriting part (never tried to do that). This is indeed limiting, but maybe the functionality could be extended here?

As the pool is otherwise composed of strictly orderable MPNs, the base parts don't really fit in, too. Could we promote the base parts with the inheritance relationships to generic parts?

Generic parts via inheritance

It would be a breaking change for the pool, but the choice to inherit field values could be shifted from the inheriting part to the base part. This would allow some neat UX:

I sometimes use the base parts in the pool where a generic part would be a better fit. I have lots of “base 0603 LED”s in my schematics, simply because the LED colour isn't decided yet. I often manually smash the parts and edit the value by hand to have something like a generic part.

Some of my parts use a not that great inheritance scheme. I didn't want to clutter the pool with a non-orderable base part, so I used one of the orderable MPNs as the base. In a lot of cases, the underlying relationship is less than obvious because all parts appear to have the same degree of specificity. The behaviour outlined above would naturally prevent a usage of inheritance like this.

carrotIndustries commented 5 years ago

repeated work during step 2 because you do the same thing for each package variant even if all fields except the package are the same (and even for many package variants the pin outs are essentially the same).

That should be fairly easy to fix by adding a button that imports the mapping from another part with the same entity.

repeated work during step 3 even if most of the time only the MPNs differ if you like to edit many parts at once, the only sane way is scripting or some text editor magic (which is comparedly easy thanks to the use of json) Inheritance gets less useful once all children need an additional tag or a changed description, because you need to change these for each child by hand

If I got this correctly, that's easy to solve by adding some kind of tabular part editor where each part is a row and MPN/Manufacturer/Description etc are columns.

Base parts are non-orderable and do not have any special indicator that they are base parts (e.g. we could write them in cursive, grey them out or something)

Okay, let's a add a 'is virtual' flag to parts.

and changing hierarchies is not really possible

This is indeed limiting, but maybe the functionality could be extended here?

To me changing a part's entity seems a bit silly as it completely breaks the netlist. So changing a base part would have to retain the entity.

All generic fields of a part can be freely edited in the schematic without smashing the part. This is IMHO the biggest plus of the approach.

That however breaks BOM export as it groups the components by part to arrive at a BOM row.

My main issue with generic parts by inheritance is that it doesn't deal well with a series of resistors for example inheriting from a common base part that already has manufacturer and datasheet filled in. With each resistor in a series inheriting from a different base part, one would need to specify the datasheet link for each part, resulting in redundancy.

Since everyone in here seems to be okay with the orderable MPN thing, I merged it.

atoav commented 5 years ago

If I got this correctly, that's easy to solve by adding some kind of tabular part editor where each part is a row and MPN/Manufacturer/Description etc are columns.

This was roughly what I had in mind. Something where you can create and organize a family of parts with a focus on beeing able to quickly edit fields of multiple parts at once and deciding which inherits what from which base part etc. And only once you are happy you "commit" them to the pool. As it is now, I am usually faster when I copy and edit the json files by hand instead of using the pool editor, which also has to do with the fact, that the pool needs to update after each edit, which takes a bit with the number of parts I currently have.

Okay, let's a add a 'is virtual' flag to parts.

I think this makes sense from the perspective of having only orderable parts. I am still curious how the idea @fruchti mentioned above would pan out in practise, I couldn't really wrap my head around it at the moment.

To me changing a part's entity seems a bit silly as it completely breaks the netlist. So changing a base part would have to retain the entity.

I think there is a misunderstanding. I never actually meant to change a parts entity, but the inheritance hierarchy between parts. E.g. moving children of a base part to another base part or adding a parent to two base parts so they have a common ancestor etc. Basically manipulating hierarchy easily without having to redo the whole thing again.

When I think about this, one thing that always bugged me was how inheritance works for parts with different packages. If we introduce a is_virtual flag anyways, we could also allow virtual parts to exist without package,

This would allow for inheritance patterns similar to this:

[TL072 (Base)]: virtual, specifies most tags, description and datasheet, no package
    |--- [TL072 (SOIC-8, Base)]: virtual, adds soic-8 tag and soic-8 package
    |         |-- [TL072CDR]: actual part
    |         |-- [TL072CDT]: actual part, add low-noise tag
    |         |-- ...
    |
    |--- [TL072 (DIP-8, Base)]: virtual, adds dip-8 tag and dip-8 package
    |         |-- [TL072IP]: actual part
    |         |-- [TL072CP]: actual part
    |         |-- ...
    |
    |--- ...

Rather than what one would have to do right now which is this:

[TL072 (SOIC-8, Base)]: specifies most tags, description and datasheet, package
     |-- [TL072CDR]: actual part
     |-- [TL072CDT]: actual part
     |-- ...

[TL072 (DIP-8, Base)]: specifies most tags, description and datasheet, package
     |-- [TL072IP]: actual part
     |-- [TL072CP]: actual part
     |-- ...

A similar thing could also potentially provide a solution to this issue:

With each resistor in a series inheriting from a different base part, one would need to specify the datasheet link for each part, resulting in redundancy.

You could then inherit the datasheets and the rest of the common stuff from a top level base part, while you could still have more specific base parts one level lower.

carrotIndustries commented 5 years ago

that the pool needs to update after each edit, which takes a bit with the number of parts I currently have.

That's one of the things on my todo list: After editing an item in the pool, updating from scratch is rarely necessary. Instead, the pool manager could figure out which items need to be updated after a particular item has been edited. E.g. editing an entity would only require updating the entity itself and all parts that depend on it. Editing a part that has no children would result in just the part being updated. That would dramatically speed up the usual pool update process.

we could also allow virtual parts to exist without package,

We'd then need to make sure that these ones don't end up in netlists as everything over there would break if there suddenly wasn't a package associated with a part.

I think there is a misunderstanding. I never actually meant to change a parts entity, but the inheritance hierarchy between parts. E.g. moving children of a base part to another base part or adding a parent to two base parts so they have a common ancestor etc.

The thing is that changing a part's base part can effectively change the part's entity. We'd need to make sure that changing the base part retains the entity.

You could then inherit the datasheets and the rest of the common stuff from a top level base part, while you could still have more specific base parts one level lower.

Could you draw a tree to illustrate that? If I got you correctly, we'd need multiple inheritance for this as we'd need to inherit the datasheet and manufacturer from the series base part and inherit (something?) form the generic base part to represent that this particular part is a fit for the generic part.

atoav commented 5 years ago

The thing is that changing a part's base part can effectively change the part's entity. We'd need to make sure that changing the base part retains the entity.

Ahh, didn't think about that. I only ever used that with Base Parts that reference the same Entity. This would be a limitation I'd have no problem with.

We'd then need to make sure that these ones don't end up in netlists as everything over there would break if there suddenly wasn't a package associated with a part.

Virtual parts should be non-placeable (in fact they shouldn't even show up in the parts search of the schematic editor). Additionally only virtual parts should be allowed to have no package.

Could you draw a tree to illustrate that? If I got you correctly, we'd need multiple inheritance for this as we'd need to inherit the datasheet and manufacturer from the series base part and inherit (something?) form the generic base part to represent that this particular part is a fit for the generic part.

I wasn't thinking with generic base parts in mind at all, to be honest. Maybe it doesn't actually need multiple inheritance, maybe it could work like this:

The generic parts for resistors could then look like this:

Generic Resistor
       |--Generic Resistor 0805
       |         |--Generic Resistor 0805 5%
       |         |--Generic Resistor 0805 1%
       |         |--...
       |--Generic Resistor 0602
       |--Generic Resistor 0402

Generic Thin Film Resistor
       |--...

(Note: Inheritance here only shows the relationships of the sets: Generic Resistor 0805 5% is a subset of Generic Resistor 0805 which in turn is a subset of Generic Resistor. Completely lateral Generic Parts that use a different selection logic could be allowed at the same time (e.g. Generic Thin Film Resistor in this case))

In practise you could then map a family of resistor parts to these generics like so:

[Foo Bar Resistors]: virtual, generic parts: "Generic Resistor", "Generic Thin Film Resistor"
    |-- [Foo Bar Resistors 0805] virtual, generic parts: (inherited), "Generic Resistor 0805", etc.
    |      |--[Foo Bar Resistors 0805 5%]: virtual, generic parts: (inherited), "Generic Resistor 0805 5%"
    |            |--[Actual MPN 0805 5% 33k]: generic parts: inherited
    |            |--[Actual MPN 0805 5% 68k]: generic parts: inherited
    |            |--...
    |      |--[Foo Bar Resistors 0805 1%]: virtual, generic parts: (inherited), "Generic Resistor 0805 1%"
    |            |--[Actual MPN 0805 1% 33k]: generic parts: inherited
    |            |--[Actual MPN 0805 1% 68k]: generic parts: inherited
    |            |--...
    |-- [Foo Bar Resistors 0603]: virtual, generic parts: (inherited), "Generic Resistor 0603", etc.
    |      |--...
    |-- [Foo Bar Resistors 0402]: virtual, generic parts: (inherited), "Generic Resistor 0402", etc.
    |      |--...

In Summary: Virtual Base Parts are mapped to their generic counterparts. The children of these virtual base parts inherit all the generics from their parents and can add their own. That way you could choose an Actual MPN 0805 5% 33 part whenever the generic part was one of the following:

One gotcha here: how to deal with virtual parts with unspecified package? In the schematic editor it doesn't matter too much except that we need to know there are two pins (in the case of the resistor). But as soon as you place it in the board view, you should specify sth there. Maybe these top level categories bring more pain than joy and we should just leave them out...?

However otherwise this method allows for very granular and nearly arbitrary generic-part mappings, and I can imagine this would work just well. I am just not sure about the places where this would lead the pool if we factor in user error. If we'd to go the fully parametric route with passives, a wrong part would be consistently wrong, because it's parameter is wrong. The error is in one place and that is good.

But with this solution it can and will happen that some parts just won't show up in the "propper" generic base parts because the user forgot it or was to lazy or whatnot.

But maybe I am overthinking this and it is just a question how granular these generic parts really should become? Or maybe one could make automatic generics for certain types of passives that come with parametric data.

carrotIndustries commented 5 years ago

That's one of the things on my todo list:

Not anymore: https://github.com/horizon-eda/horizon/tree/partial-pool-update If no one finds any obvious bugs, I'll merge it in the next few days.

atoav commented 5 years ago

For now I didn't find anything, however I couldn't also really feel a speedup (very likely I just didn't understood what you changed here). When I duplicate a part it still takes the same time to update the pool, when I save that duplicate, as it took before.

Maybe I am looking in the wrong place?

carrotIndustries commented 5 years ago

Maybe I am looking in the wrong place?

Currently, the fast pool update is only implemented for editing items.

atoav commented 5 years ago

Currently, the fast pool update is only implemented for editing items.

This is indeed much faster, wow.

carrotIndustries commented 5 years ago

When I duplicate a part it still takes the same time to update the pool, when I save that duplicate, as it took before.

The recent commits enable fast pool update for that as well.

atoav commented 5 years ago

Okay, this is a real improvement. For my pool it makes the difference between <1s and ~18s.

fruchti commented 5 years ago

Sorry for the late reply, I have been pretty busy lately.

My main issue with generic parts by inheritance is that it doesn't deal well with a series of resistors for example inheriting from a common base part that already has manufacturer and datasheet filled in. With each resistor in a series inheriting from a different base part, one would need to specify the datasheet link for each part, resulting in redundancy.

You're right, I overlooked that many cases would need multiple inheritance. Multiple inheritance would lead to a lot of edge cases and possible broken dependencies on part updates, so it's probably not worth it. I can't find any way to work around this need to make generics by inheritance work, either.

Okay, let's a add a 'is virtual' flag to parts.

This is already a big improvement to the current “base parts”. I really like the name virtual, so I'd vote we call those virtual parts instead of base parts in the future, and also encourage their use for creating parts with many different values. Being strictly pool-internal they don't add extra clutter for the pool user.

That's one of the things on my todo list:

Not anymore: https://github.com/horizon-eda/horizon/tree/partial-pool-update If no one finds any obvious bugs, I'll merge it in the next few days.

This is great! I didn't come across any obvious issues for now.

carrotIndustries commented 4 years ago

I can't find any way to work around this need to make generics by inheritance work, either.

Ok, so we're back to having a field 'concrete for' in parts?

My current plan goes like this: