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

[WIP] XML components #1242

Closed
wants to merge 59 commits into from
Closed

Conversation

andresmmera
Copy link
Collaborator

Based on the needs discussed in #849 and #876, this PR addresses the transition from hardcoded C++ components to their definition in XML.

To do this, Qucs-S parses the contents of the XML libraries located in share/qucs-s/components (as well as from the PDK directory, defined in Application Settings->Locations) and loads all library data into a QMap structure.

The Component class has been modified to behave like any other component. Basically, it gets the specific component information (symbol, netlist line template, etc.) through a struct ComponentInfo.

Also muParser was integrated in order to evaluate component properties based on expressions. Consequently, it is needed to install it before building this (sudo apt-get install libmuparser-dev).

This is WIP at an early stage. Only some standard components have been added, it'll take time to fill the libraries and do proper testing.

In order to avoid the complexities of the hardcoded components, a library containing XML structured data of the system components is defined.

Qucs-S needs to access the component information for:
1) Display the component in the palette
2) Create a component instance to be placed in the schematic.

In order to cover these cases, the XML file is loaded at the beginning of the program into a global variable.

The data from the XML file contains the device parameters as well as the symbol. In order to store the information properly, it is needed to have custom structs at top level.

A function to read the XML file is created in qucs.cpp as well as a function to translate the XML-defined symbol into Qucs-S display geometries.




The scope of this commit is to achieve 1).
The placement of the XML based devices is based on a modification of the generic component "component.cpp". In this commit, this class is modified to load the component information through a custom struct carrying the parameters and the symbol.
It is more appropiate than having the libraries at /home/user/ level
Added reading support for arcs, polylines, texts, rectangles and ellipses
It was duplicated in QucsApp and Component
There was a problem in the definition of the arc figure in the XML file.
In this commit, the component's bounding box is calculated at the beginning of the program when the XML component library is loaded.
For doing this, the coordinates of each geometry of the symbol are inspected and then stored into the "ComponentInfo" structure. This is information is passed to the generic "Component" object to define the bounding box.

The bounding box is required to select the component in the schematic and then modify its parameters.
This commit adds the possibility to define the component's symbol outside the XML file. For doing so, the <Symbol> tag includes a new field, "type" which specifies if the symbol is defined inside the XML file type="explicit" or if it points to an external file type="external"

The inductor component is defined externally just for reference. In the future, when PDK components will be included, the inductor symbol will be defined the same way as the rest of the lumped components
In order to test basic simulation capabilities, a source is needed.

The AC power source is defined ias XML
When a component is placed via copying+pasting or loaded from a schematic file, Qucs-S looks for the component in the regestry of hardcoded devices. In order to load static components from the QMap library, a patch is needed.

In favor of code simplicity another constructor is defined for the Component class, so it can create a component from a ComponentInfo structure
Also, it was removed the deg C unit in the power source. In the current state, that causes problems with the netlister
- Included in the "Lumped Components" library
- It was needed to tweak the "netlist()" function in "Component" to avoid its component declaration in the qucsator netlist
- Added a new field in the component XML definition to show or not the component name in the schematic
- Modified "void QucsApp::slotInsertGround(bool on)" function, which is triggered by pressing the GND button in the toolbar to look for the Ground component in the QMap library
In the old component loading system the DC voltage and the AC power sources were rotated. In this commit the sources were defined without the rotation, as it is simpler. This might be a problem for backwards compatibility, but it could be handled using a conversion script
- Added $PDK path to QucsSettings
- Load .xml files in the $PDK directory
- Added default values in "void QucsApp::readXML(QFile & library_file)" for the "show_name" and "symbol type" fields
In Qt6 QString must be created using the QString() constructor. Before this, the code had some explicit declarations, specially inside if conditions
Before this commit, the netlist were built from the hardcoded definition of the component. In this commit, it were added netlists lines in the component definition that Qucs-S use to build the schematic netlist.

Now "Component" includes a "netlist()" function that generates the corresponding netline from the information on the XML by parsing the string. In this sense, the variables, enclosed by braces (like "{V}") are replaced by the actual parameter to build the netling.
…One() placement

It was found that the netlist generated from components placed using the Component::newOne() function was wrong. This was caused by the copy constructor.

This type of placement ocurrs when the user picks a component from the palette, place the component in the schematic and Qucs-S automatically puts another one, grayed, waiting to be placed.

Also, it was found some minor error with the XML component definition and a problem with the placement of the GND.

At this point, Qucs-S works well for the example of a voltage divider (at least with Qucsator)
A patch was done for fixing Ngspice netlisting. Basically, units are removed from the parameters while preserving the k, M, G-like suffixes.

An special treatment is done for the ground component to skip it from the Qucs-S check
Component class already has a "Model" field serving the same purpose as the recently introduced Schematic_ID. Consequently, Schematic_ID is dropped.

On the other hand, a new field "XML_Defined" is introduced in the Component class to indicate whether the component was loaded from the XML library or no
It is possible to have different components with the same name in different libraries. For example, "R" can be the ideal resistor from the Lumped Components library, but it can also be a custom resistor from a PDK. To avoid this kind of ambiguity, the netline of the component now includes the library according to the following format Library:ComponentName. Both "Library" and "ComponentName" must not contain spaces, so they are replaced by "_".

Backward compatibility with old Qucs-S schematics is ensured.
Devices from the IHP PDK are defined as subcircuits and calls to external libraries are required.

This commit adds the necessary subcircuit definitions and calls at the beginning of the netlist.

Qucs::readXML() is modified to load subcircuit definition and include instances from the XML file
The IHP library, "IHP-SG13G2.xml" was added to qucs.qrc. This is only for tracking the changes.

The proper path to this file is "<QUCS_USER_DIR>/PDKs/IHP-SG13G2/libs.tech/qucs-s"

where <QUCS_USER_DIR> is typically "/home/<user>/.qucs"
The PartCounter field was not being updated when loading components from a schematic file
Replace show=1 by show="true" as this was found easier for conversion into bool
Library call and subcircuit definition updated
Subcircuit definition and library includes were added to the XML file
It was found that when multiple subcircuits and libraries were to be included in the netlist the line break was missing.

This was fixed by turning the "SubcircuitDefinition" and "LibraryCalls" QStrings into QStringLists.
Both the PDKs folder and the OSDI files path should be customizable by the user
@andresmmera andresmmera self-assigned this Feb 19, 2025
@ra3xdh ra3xdh marked this pull request as draft February 19, 2025 06:05
@ra3xdh
Copy link
Owner

ra3xdh commented Feb 19, 2025

Thanks for sharing! I will evaluate this and post my feedback soon. This is task for the next relese cycle.

@ra3xdh ra3xdh linked an issue Feb 19, 2025 that may be closed by this pull request
@ra3xdh ra3xdh added this to the 25.2.0 milestone Feb 19, 2025
@ra3xdh
Copy link
Owner

ra3xdh commented Feb 19, 2025

The first point is to add muparser dependency in the deploy.yml CI scripts. Otherwise the CI fails.

@andresmmera
Copy link
Collaborator Author

andresmmera commented Feb 19, 2025

Vadim, I forgot to mention that I've made a change to the schematic file format. Since the component data is stored in a QMap by category and name, each instance in the schematic file is now written as "Category:Component_Name".

This is very efficient for retrieving component data. I have added some logic to ensure compatibility with older schematics, but older versions of Qucs-S will not be able to open schematics created with this version (unless a patch, such as a backwards export feature, is provided).

This notation is also very convenient, IMHO, because especially when introducing PDKs, components from different libraries may have the same name.

Do you think this is a problem?

As discussed in Slack, the subcircuit definition in the XML file is not needed
The location os the ODSI file should be the same as in xschem, i.e. {PDK_ROOT}/ihp-sg13g2/libs.tech/ngspice/openvaf/psp103_nqs.osdi

This makes possible to get rid off the OSDI path location setting
The XML file was simplified to use symbols from standard components.
Now it is possible to parse expressions from the XML component description.
The VRMS in the AC Power Source is now calculated using an expression defined in Sources.xml
As discussed on Slack, the `readXML()` function has been updated to support environment variables. This enhancement is particularly useful for handling custom symbols defined in a PDK. With this change, the PDK XML file can now specify the path to symbol files directly using environment variables (e.g., `{$PDK_ROOT}`), eliminating the need for relative paths.
The viewport is updated on changes made by clicking in the component property on the Schematic.
Otherwise, components with parameters dependent on expression won't show the updated value until the user clicks on the schematic
@andresmmera
Copy link
Collaborator Author

Closing temporarily

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Migrate C++ hardcoded devices to XML
2 participants