-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathimportXML.py
More file actions
153 lines (133 loc) · 7.32 KB
/
Copy pathimportXML.py
File metadata and controls
153 lines (133 loc) · 7.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# To run use `python3 scripts/importXML.py insert/your/file/path/here`
import argparse
import xml.etree.ElementTree as ET
def parseXml(path):
tree = ET.parse(path)
root = tree.getroot()
return root
def generateCPPCode(root):
circuitName = root.find('Name').text
category = root.find('Category').text
numNodes = root.find('./Settings/numNodes').text
hasDCBlockerElem = root.find('./Settings/hasDCBlocker')
hasDCBlocker = hasDCBlockerElem.text if hasDCBlockerElem is not None else 'false'
outputElem = root.find('./Settings/Output')
output = outputElem.text if outputElem is not None else None
cpp_code = []
cpp_code.append(f"class {circuitName} : public Circuit")
cpp_code.append("{\n")
cpp_code.append("public:")
cpp_code.append(f" {circuitName}"+"(){")
cpp_code.append(f" layout.numNodes = {numNodes};\n")
elements = root.find('Elements')
for element in elements:
elementName = element.tag
if elementName == "VoltageInput":
node1 = element.find('node1').text
node2 = element.find('node2').text
cpp_code.append(" layout.Vin = CircuitElement::VoltageInput {"+f"{node1}, {node2}"+"};")
elif elementName == "VoltageOutput":
node1 = element.find('node1').text
node2 = element.find('node2').text
cpp_code.append(" layout.Vout = CircuitElement::VoltageOutput {"+f"{node1}, {node2}"+"};\n")
elif elementName == "Vs":
voltageSources = []
for i, subelement in enumerate(element):
voltage = subelement.find('voltage').text
node = subelement.find('node').text
voltageSources.append(f" CircuitElement::VoltageSource Vs{i+1} "+"{"+f"{voltage}, {node}"+"};")
cpp_code.extend(voltageSources)
cpp_code.append(f" layout.Vs = std::vector<CircuitElement::VoltageSource> {{{', '.join([f'Vs{i+1}' for i in range(len(voltageSources))])}}};\n")
elif elementName == "Rs":
resistors = []
for i, subelement in enumerate(element):
value = subelement.find('value').text
node1 = subelement.find('node1').text
node2 = subelement.find('node2').text
resistors.append(f" CircuitElement::Resistor R{i+1} "+"{"+f"{value}, {node1}, {node2}"+"};")
cpp_code.extend(resistors)
cpp_code.append(f" layout.Rs = std::vector<CircuitElement::Resistor> {{{', '.join([f'R{i+1}' for i in range(len(resistors))])}}};\n")
elif elementName == "Cs":
capacitors = []
for i, subelement in enumerate(element):
value = subelement.find('value').text
node1 = subelement.find('node1').text
node2 = subelement.find('node2').text
capacitors.append(f" CircuitElement::Capacitor C{i+1} "+"{"+f"{value}, {node1}, {node2}"+"};")
cpp_code.extend(capacitors)
cpp_code.append(f" layout.Cs = std::vector<CircuitElement::Capacitor> {{{', '.join([f'C{i+1}' for i in range(len(capacitors))])}}};\n")
elif elementName == "VarRs":
varResistors = []
for i, subelement in enumerate(element):
maxValue = subelement.find('maxValue').text
parameterNumber = subelement.find('parameterNumber').text
direction = subelement.find('Direction').text
node1 = subelement.find('node1').text
node2 = subelement.find('node2').text
skew = subelement.find('Skew').text
varResistors.append(
f" CircuitElement::VariableResistor VarR{i+1} "+"{"+f"{maxValue},\n"
f" {parameterNumber},\n"
f" CircuitElement::VariableResistor::ParamDirection::{direction},\n"
f" CircuitElement::VariableResistor::Skew::{skew},\n"
f" {node1}, {node2}"+"};")
cpp_code.extend(varResistors)
cpp_code.append(f" layout.VarRs = std::vector<CircuitElement::VariableResistor> {{{', '.join([f'VarR{i+1}' for i in range(len(varResistors))])}}};\n")
elif elementName == "OPAmps":
opamps = []
for i, subelement in enumerate(element):
nonInvertingNode = subelement.find('nonInvertingNode').text
invertingNode = subelement.find('invertingNode').text
outputNode = subelement.find('outputNode').text
opamps.append(f" CircuitElement::OPAmp OPA{i+1} "+"{"+f"{nonInvertingNode}, {invertingNode}, {outputNode}"+"};")
cpp_code.extend(opamps)
cpp_code.append(f" layout.OPAmps = std::vector<CircuitElement::OPAmp> {{{', '.join([f'OPA{i+1}' for i in range(len(opamps))])}}};\n")
elif elementName == "BJTs":
bjts = []
for i, subelement in enumerate(element):
doping = subelement.find('Doping').text
semiconductor = subelement.find('Semiconductor').text
nodeBase = subelement.find('nodeBase').text
nodeCollector = subelement.find('nodeCollector').text
nodeEmitter = subelement.find('nodeEmitter').text
bjts.append(
f" CircuitElement::BJT BJT{i+1} "+"{"+f"CircuitElement::BJT::Doping::{doping},\n"
f" CircuitElement::BJT::Semiconductor::{semiconductor},\n"
f" {nodeBase}, {nodeCollector}, {nodeEmitter}"+"};")
cpp_code.extend(bjts)
cpp_code.append(f" layout.BJTs = std::vector<CircuitElement::BJT> {{{', '.join([f'BJT{i+1}' for i in range(len(bjts))])}}};\n")
# Add hasDCBlocker if true
if hasDCBlocker.lower() == 'true':
cpp_code.append(f" layout.hasDCBlocker = true;\n")
# Add Output if specified
if output is not None:
cpp_code.append(f" layout.Output = {output};\n")
cpp_code.append(f" circuit = CircuitModel(layout);")
cpp_code.append(" }")
cpp_code.append("};")
return "\n".join(cpp_code)
def insertCodeToHeader(cppCode, headerFilePath):
with open(headerFilePath, 'r') as headerFile:
lines = headerFile.readlines()
insertPos = 0
for i, line in enumerate(reversed(lines)):
if line.strip() == "}":
insertPos = len(lines) - i - 1
break
updatedLines = lines[:insertPos] + ["\n" +cppCode+ "\n"] + lines[insertPos:]
with open(headerFilePath, 'w') as headerFile:
headerFile.writelines(updatedLines)
print(f"XML has been appended to {headerFilePath}")
def main():
parser = argparse.ArgumentParser(
description="Generate a pybind11 binding .cpp for a given header file."
)
parser.add_argument("filePath", help="File path to XML file containing custom circuit.")
args = parser.parse_args()
xmlFilePath = args.filePath
headerFilePath = "include/circuits/UserCircuits.h"
xmlRoot = parseXml(xmlFilePath)
cppCode = generateCPPCode(xmlRoot)
insertCodeToHeader(cppCode, headerFilePath)
if __name__ == "__main__":
main()