├── cds
├── __init__.py
├── test
│ └── test_adexl.py
└── adexl.py
├── setup.sh
├── README.md
└── notebooks
└── adexl class demo.ipynb
/cds/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/setup.sh:
--------------------------------------------------------------------------------
1 | export PYTHONPATH=$PYTHONPATH:`pwd`
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | pycds
2 | =====
3 |
4 | Python interface to Cadence Virtuoso data
5 |
--------------------------------------------------------------------------------
/cds/test/test_adexl.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from cds.adexl import ADE_XL_Result
4 |
5 | def test_adexl():
6 | r = ADE_XL_Result(os.path.join(os.path.dirname(__file__), 'data', 'adexl'))
7 | print r
8 |
9 |
10 |
--------------------------------------------------------------------------------
/cds/adexl.py:
--------------------------------------------------------------------------------
1 | from lxml import etree
2 | import os
3 | import sqlite3
4 | import pandas.io.sql
5 |
6 | import util
7 |
8 | class ADE_XL_Result(object):
9 | def __init__(self, directory):
10 | self.directory = directory
11 |
12 | self.setupdb = self.xmldata()
13 |
14 | self._load_tests()
15 | self._load_history()
16 |
17 | def check(self):
18 | ## FIXME, check consistency
19 | return True
20 |
21 | def xmldata(self):
22 | """Return ADE-XL XML data etree"""
23 | datafile = os.path.join(self.directory, "data.sdb")
24 | return etree.parse(datafile)
25 |
26 | def expand_path(self, path):
27 | """Expand paths relative to result directory"""
28 | return path.replace('$AXL_SETUPDB_DIR', self.directory)
29 |
30 | def get_history_entry_names(self):
31 | return [he.name for he in self.history]
32 |
33 | def get_history_entry(self, name):
34 | for h_entry in self.history:
35 | if h_entry.name == name:
36 | return h_entry
37 |
38 | def _load_tests(self):
39 | self.tests = [ADE_XL_Test(elem)
40 | for elem in self.setupdb.findall('active/tests/test')]
41 |
42 | def _load_history(self):
43 | self.history = [ADE_XL_HistoryEntry(elem)
44 | for elem in self.setupdb.findall('history/historyentry')]
45 |
46 | class ADE_XL_Test(object):
47 | def __init__(self, elem):
48 | self.elem = elem
49 |
50 | self.name = elem.text.strip()
51 |
52 | self._load_tooloptions()
53 | self._load_outputs()
54 |
55 | def _load_outputs(self):
56 | self.outputs = [ADE_XL_TestOutput(elem.text.strip())
57 | for elem in self.elem.findall('outputs/output')]
58 |
59 | def _load_tooloptions(self):
60 | ## Load tool options
61 | tooloptions = {}
62 | for tooloption in self.elem.findall('tooloptions/option'):
63 | value = tooloption.find('./value')
64 | tooloptions[tooloption.text.strip()] = value.text.strip()
65 |
66 | self.tooloptions = tooloptions
67 |
68 | def get_state_dir(self, result):
69 | return os.path.join(*([result.expand_path(self.tooloptions['path']),
70 | self.cellview[0],
71 | self.cellview[1],
72 | self.simulator,
73 | self.tooloptions['state']
74 | ]))
75 |
76 | def get_state_file(self, filename, result):
77 | with open(os.path.join(self.get_state_dir(result), filename)) as f:
78 | return f.read()
79 |
80 | @property
81 | def cellview(self):
82 | return [self.tooloptions['lib'],
83 | self.tooloptions['cell'],
84 | self.tooloptions['view']]
85 |
86 | @property
87 | def simulator(self):
88 | return self.tooloptions['sim']
89 |
90 | class ADE_XL_TestOutput(object):
91 | def __init__(self, name):
92 | self.name = name
93 |
94 | class ADE_XL_HistoryEntry(object):
95 | def __init__(self, elem):
96 | self.elem = elem
97 |
98 | self._load_history_entry()
99 |
100 | def _load_history_entry(self):
101 | self.name = self.elem.text.strip()
102 | self.simresults = self.elem.find('./simresults').text.strip()
103 |
104 | def get_result_db(self, result):
105 | if self.simresults:
106 | sqlitedbfile = result.expand_path(self.simresults)
107 | return ADE_XL_ResultDatabase(sqlitedbfile)
108 |
109 | class ADE_XL_ResultDatabase(object):
110 | def __init__(self, dbfile):
111 | self.conn = sqlite3.connect(dbfile)
112 |
113 | def get_results(self, **results):
114 | """Get selected results as pandas dataframe"""
115 |
116 | query = """SELECT
117 | test.name as testname, resultValue.pointID,
118 | result.name as resultname, resultValue.value
119 | FROM
120 | resultValue
121 | INNER JOIN
122 | result ON result.resultID = resultValue.resultID
123 | INNER JOIN
124 | point ON point.pointID = resultValue.pointID
125 | INNER JOIN
126 | corner ON corner.cornerID = point.cornerID
127 | INNER JOIN
128 | test ON test.testID = result.testID
129 | """
130 | return pandas.io.sql.read_frame(query, self.conn).applymap(util.adexl_to_python)
131 |
132 | def get_point_corner_parameters(self, ):
133 | """Get all results as pandas dataframe"""
134 |
135 | query = """SELECT
136 | test.name as testname, resultValue.pointID,
137 | corner.name as cornername,
138 | result.name as resultname, resultValue.value
139 | FROM
140 | resultValue
141 | INNER JOIN
142 | result ON result.resultID = resultValue.resultID
143 | INNER JOIN
144 | point ON point.pointID = resultValue.pointID
145 | INNER JOIN
146 | corner ON corner.cornerID = point.cornerID
147 | INNER JOIN
148 | test ON test.testID = result.testID
149 | """
150 | return pandas.io.sql.read_frame(query, self.conn).applymap(util.adexl_to_python)
151 |
152 | def get_result_names(self):
153 | query = """SELECT result.name
154 | FROM result"""
155 | return [row[0] for row in self.conn.execute(query).fetchall()]
156 |
157 | def get_parameter_names(self):
158 | query = """SELECT name
159 | FROM parameter"""
160 | return [row[0] for row in self.conn.execute(query).fetchall()]
161 |
162 | def get_results(self, *resultnames):
163 | ## If no parameters, select all columns
164 | if len(resultnames) == 0:
165 | resultnames = self.get_result_names()
166 |
167 | subqueries = ["""(SELECT value
168 | FROM resultValue
169 | INNER JOIN
170 | result ON result.resultID = resultValue.resultID
171 | INNER JOIN
172 | test ON test.testID = result.testID
173 | WHERE resultValue.pointID == point.pointID
174 | AND result.name = '%(resultname)s')
175 | AS '%(resultname)s'""" % {'resultname': resultname}
176 | for resultname in resultnames]
177 | select_columns = ", ".join(subqueries)
178 |
179 | quoted_result_names = ', '.join(["'%s'" % rn for rn in resultnames])
180 |
181 | query = """SELECT
182 | point.pointID as pointID,
183 | %s
184 | FROM
185 | point
186 | """ % select_columns
187 |
188 | return pandas.io.sql.read_frame(query, self.conn).applymap(util.adexl_to_python)
189 |
190 | def get_parameter_values(self, *parameternames):
191 | ## If no parameters, select all columns
192 | if len(parameternames) == 0:
193 | parameternames = self.get_parameter_names()
194 |
195 | subqueries = ["""(SELECT value
196 | FROM parameterValue
197 | INNER JOIN
198 | parameter ON parameter.parameterID = parameterValue.parameterID
199 | WHERE parameterValue.pointID == point.pointID
200 | AND parameter.name = '%(parametername)s')
201 | AS '%(parametername)s'""" % {'parametername': parametername}
202 | for parametername in parameternames]
203 | select_columns = ", ".join(subqueries)
204 |
205 | query = """SELECT
206 | point.pointID as pointID,
207 | %s
208 | FROM
209 | point
210 | """ % select_columns
211 |
212 | return pandas.io.sql.read_frame(query, self.conn).applymap(util.adexl_to_python)
213 |
214 |
215 | def get_parameters(self, pointid):
216 | query = """SELECT
217 | parameter.name, parameterValue.value
218 | FROM
219 | parameterValue
220 | INNER JOIN
221 | parameter ON parameter.parameterID = parameterValue.parameterID
222 | WHERE
223 | parameterValue.pointID = %d""" % pointid
224 | return pandas.io.sql.read_frame(query, self.conn).applymap(util.adexl_to_python)
225 |
226 |
227 | if __name__ == '__main__':
228 | r = ADE_XL_Result(os.path.join(os.path.dirname(__file__), 'test', 'data', 'adexl'))
229 |
230 | test = r.tests[0]
231 |
232 | statedir = test.get_state_dir(r)
233 |
234 | history = r.history
235 |
236 | print "Tests:", [test.name for test in r.tests]
237 | print "History:", [he.name for he in r.history]
238 |
239 | resultdb = history[0].get_result_db(r)
240 |
241 | tables = resultdb.execute("SELECT name FROM sqlite_master WHERE type='table'").fetchall()
242 |
243 | print "Tables: %s" % tables
244 |
245 | query = """SELECT
246 | test.name, resultValue.pointID, result.name, resultValue.value
247 | FROM
248 | resultValue
249 | INNER JOIN
250 | result ON result.resultID = resultValue.resultID
251 | INNER JOIN
252 | test ON test.testID = result.testID
253 | """
254 |
255 | for historyentry in r.history:
256 | print historyentry.get_parameters(1, r)
257 | print historyentry.get_all_results(r)
258 |
259 |
--------------------------------------------------------------------------------
/notebooks/adexl class demo.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "name": ""
4 | },
5 | "nbformat": 3,
6 | "nbformat_minor": 0,
7 | "worksheets": [
8 | {
9 | "cells": [
10 | {
11 | "cell_type": "code",
12 | "collapsed": false,
13 | "input": [
14 | "import cds.adexl as adexl\n",
15 | "\n",
16 | "datadir = \"/home/hjohansson/pycds/cds/test/data/adexl\""
17 | ],
18 | "language": "python",
19 | "metadata": {},
20 | "outputs": [],
21 | "prompt_number": 19
22 | },
23 | {
24 | "cell_type": "code",
25 | "collapsed": false,
26 | "input": [
27 | "adexl_result = adexl.ADE_XL_Result(datadir)"
28 | ],
29 | "language": "python",
30 | "metadata": {},
31 | "outputs": [],
32 | "prompt_number": 20
33 | },
34 | {
35 | "cell_type": "code",
36 | "collapsed": false,
37 | "input": [
38 | "adexl_result.get_history_entry_names()"
39 | ],
40 | "language": "python",
41 | "metadata": {},
42 | "outputs": [
43 | {
44 | "metadata": {},
45 | "output_type": "pyout",
46 | "prompt_number": 21,
47 | "text": [
48 | "['Interactive.205',\n",
49 | " 'Interactive.206',\n",
50 | " 'Interactive.207',\n",
51 | " 'Interactive.208',\n",
52 | " 'Interactive.209',\n",
53 | " 'Interactive.210',\n",
54 | " 'Interactive.211',\n",
55 | " 'Interactive.212',\n",
56 | " 'Interactive.213',\n",
57 | " 'Interactive.214',\n",
58 | " 'Interactive.215',\n",
59 | " 'Interactive.216',\n",
60 | " 'Interactive.217',\n",
61 | " 'Interactive.218',\n",
62 | " 'Interactive.219']"
63 | ]
64 | }
65 | ],
66 | "prompt_number": 21
67 | },
68 | {
69 | "cell_type": "code",
70 | "collapsed": false,
71 | "input": [
72 | "h_entry = adexl_result.get_history_entry('Interactive.210')"
73 | ],
74 | "language": "python",
75 | "metadata": {},
76 | "outputs": [],
77 | "prompt_number": 32
78 | },
79 | {
80 | "cell_type": "code",
81 | "collapsed": false,
82 | "input": [
83 | "h_entry.get_all_results(adexl_result)"
84 | ],
85 | "language": "python",
86 | "metadata": {},
87 | "outputs": [
88 | {
89 | "html": [
90 | "
\n",
91 | "
\n",
92 | " \n",
93 | " \n",
94 | " | \n",
95 | " name | \n",
96 | " pointID | \n",
97 | " name | \n",
98 | " value | \n",
99 | "
\n",
100 | " \n",
101 | " \n",
102 | " \n",
103 | " | 0 | \n",
104 | " psrr | \n",
105 | " 1 | \n",
106 | " PStoCM 20MHz | \n",
107 | " -15.293499 | \n",
108 | "
\n",
109 | " \n",
110 | " | 1 | \n",
111 | " psrr | \n",
112 | " 1 | \n",
113 | " PStoDM 20MHz | \n",
114 | " -165.119020 | \n",
115 | "
\n",
116 | " \n",
117 | " | 2 | \n",
118 | " psrr | \n",
119 | " 1 | \n",
120 | " PStoDM 40MHz | \n",
121 | " -159.372130 | \n",
122 | "
\n",
123 | " \n",
124 | " | 3 | \n",
125 | " psrr | \n",
126 | " 1 | \n",
127 | " PStoDM 10MHz | \n",
128 | " -170.331518 | \n",
129 | "
\n",
130 | " \n",
131 | " | 4 | \n",
132 | " psrr | \n",
133 | " 1 | \n",
134 | " PStoCM 40MHz | \n",
135 | " -15.293499 | \n",
136 | "
\n",
137 | " \n",
138 | " | 5 | \n",
139 | " psrr | \n",
140 | " 1 | \n",
141 | " PStoCM 10MHz | \n",
142 | " -15.293499 | \n",
143 | "
\n",
144 | " \n",
145 | "
\n",
146 | "
"
147 | ],
148 | "metadata": {},
149 | "output_type": "pyout",
150 | "prompt_number": 33,
151 | "text": [
152 | " name pointID name value\n",
153 | "0 psrr 1 PStoCM 20MHz -15.293499\n",
154 | "1 psrr 1 PStoDM 20MHz -165.119020\n",
155 | "2 psrr 1 PStoDM 40MHz -159.372130\n",
156 | "3 psrr 1 PStoDM 10MHz -170.331518\n",
157 | "4 psrr 1 PStoCM 40MHz -15.293499\n",
158 | "5 psrr 1 PStoCM 10MHz -15.293499"
159 | ]
160 | }
161 | ],
162 | "prompt_number": 33
163 | },
164 | {
165 | "cell_type": "code",
166 | "collapsed": false,
167 | "input": [
168 | "h_entry.get_parameters(1, adexl_result)"
169 | ],
170 | "language": "python",
171 | "metadata": {},
172 | "outputs": [
173 | {
174 | "html": [
175 | "\n",
176 | "
\n",
177 | " \n",
178 | " \n",
179 | " | \n",
180 | " name | \n",
181 | " value | \n",
182 | "
\n",
183 | " \n",
184 | " \n",
185 | " \n",
186 | " | 0 | \n",
187 | " C | \n",
188 | " 1p | \n",
189 | "
\n",
190 | " \n",
191 | " | 1 | \n",
192 | " Cload | \n",
193 | " 100f | \n",
194 | "
\n",
195 | " \n",
196 | " | 2 | \n",
197 | " Ibias | \n",
198 | " 25u | \n",
199 | "
\n",
200 | " \n",
201 | " | 3 | \n",
202 | " Rload | \n",
203 | " 400k | \n",
204 | "
\n",
205 | " \n",
206 | " | 4 | \n",
207 | " Vcm | \n",
208 | " 650m | \n",
209 | "
\n",
210 | " \n",
211 | " | 5 | \n",
212 | " Vcmdac | \n",
213 | " 0.6 | \n",
214 | "
\n",
215 | " \n",
216 | " | 6 | \n",
217 | " Vcmin | \n",
218 | " 0.65 | \n",
219 | "
\n",
220 | " \n",
221 | " | 7 | \n",
222 | " Vcmout | \n",
223 | " 0.65 | \n",
224 | "
\n",
225 | " \n",
226 | " | 8 | \n",
227 | " Vdd | \n",
228 | " 1.35 | \n",
229 | "
\n",
230 | " \n",
231 | " | 9 | \n",
232 | " amp | \n",
233 | " 10m | \n",
234 | "
\n",
235 | " \n",
236 | " | 10 | \n",
237 | " amp1 | \n",
238 | " 10m | \n",
239 | "
\n",
240 | " \n",
241 | " | 11 | \n",
242 | " amp2 | \n",
243 | " 10m | \n",
244 | "
\n",
245 | " \n",
246 | " | 12 | \n",
247 | " bw | \n",
248 | " 37 | \n",
249 | "
\n",
250 | " \n",
251 | " | 13 | \n",
252 | " dac | \n",
253 | " 0 | \n",
254 | "
\n",
255 | " \n",
256 | " | 14 | \n",
257 | " fin | \n",
258 | " 1M | \n",
259 | "
\n",
260 | " \n",
261 | " | 15 | \n",
262 | " fund | \n",
263 | " 10M | \n",
264 | "
\n",
265 | " \n",
266 | " | 16 | \n",
267 | " fund1 | \n",
268 | " 32M | \n",
269 | "
\n",
270 | " \n",
271 | " | 17 | \n",
272 | " fund2 | \n",
273 | " 36M | \n",
274 | "
\n",
275 | " \n",
276 | " | 18 | \n",
277 | " gain | \n",
278 | " 7 | \n",
279 | "
\n",
280 | " \n",
281 | " | 19 | \n",
282 | " gain1 | \n",
283 | " 1 | \n",
284 | "
\n",
285 | " \n",
286 | " | 20 | \n",
287 | " gain2 | \n",
288 | " 1 | \n",
289 | "
\n",
290 | " \n",
291 | " | 21 | \n",
292 | " iac | \n",
293 | " 0.005 | \n",
294 | "
\n",
295 | " \n",
296 | " | 22 | \n",
297 | " idac | \n",
298 | " 1u | \n",
299 | "
\n",
300 | " \n",
301 | " | 23 | \n",
302 | " idc | \n",
303 | " 2.5m | \n",
304 | "
\n",
305 | " \n",
306 | " | 24 | \n",
307 | " iin | \n",
308 | " 1u | \n",
309 | "
\n",
310 | " \n",
311 | " | 25 | \n",
312 | " iin_ac | \n",
313 | " 0 | \n",
314 | "
\n",
315 | " \n",
316 | " | 26 | \n",
317 | " iin_amp | \n",
318 | " 0 | \n",
319 | "
\n",
320 | " \n",
321 | " | 27 | \n",
322 | " iin_dc | \n",
323 | " 0 | \n",
324 | "
\n",
325 | " \n",
326 | " | 28 | \n",
327 | " rc_proc | \n",
328 | " 1 | \n",
329 | "
\n",
330 | " \n",
331 | "
\n",
332 | "
"
333 | ],
334 | "metadata": {},
335 | "output_type": "pyout",
336 | "prompt_number": 35,
337 | "text": [
338 | " name value\n",
339 | "0 C 1p\n",
340 | "1 Cload 100f\n",
341 | "2 Ibias 25u\n",
342 | "3 Rload 400k\n",
343 | "4 Vcm 650m\n",
344 | "5 Vcmdac 0.6\n",
345 | "6 Vcmin 0.65\n",
346 | "7 Vcmout 0.65\n",
347 | "8 Vdd 1.35\n",
348 | "9 amp 10m\n",
349 | "10 amp1 10m\n",
350 | "11 amp2 10m\n",
351 | "12 bw 37\n",
352 | "13 dac 0\n",
353 | "14 fin 1M\n",
354 | "15 fund 10M\n",
355 | "16 fund1 32M\n",
356 | "17 fund2 36M\n",
357 | "18 gain 7\n",
358 | "19 gain1 1\n",
359 | "20 gain2 1\n",
360 | "21 iac 0.005\n",
361 | "22 idac 1u\n",
362 | "23 idc 2.5m\n",
363 | "24 iin 1u\n",
364 | "25 iin_ac 0\n",
365 | "26 iin_amp 0\n",
366 | "27 iin_dc 0\n",
367 | "28 rc_proc 1"
368 | ]
369 | }
370 | ],
371 | "prompt_number": 35
372 | },
373 | {
374 | "cell_type": "code",
375 | "collapsed": false,
376 | "input": [],
377 | "language": "python",
378 | "metadata": {},
379 | "outputs": []
380 | }
381 | ],
382 | "metadata": {}
383 | }
384 | ]
385 | }
--------------------------------------------------------------------------------