-
Notifications
You must be signed in to change notification settings - Fork 119
/
package-decorator-2020-05-27.html
206 lines (169 loc) · 17.3 KB
/
package-decorator-2020-05-27.html
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
<!DOCTYPE html>
<html lang="en">
<head>
<title>SKiDL — Good Things Come In Packages!</title>
<meta charset="utf-8" />
<link rel="profile" href="http://gmpg.org/xfn/11" />
<link rel="stylesheet" type="text/css" href="/skidl/theme/css/style.css" />
<link rel='stylesheet' id='oswald-css' href='http://fonts.googleapis.com/css?family=Oswald&ver=3.3.2' type='text/css' media='all' />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Oswald&family=Roboto+Condensed&display=swap" rel="stylesheet">
<!-- <style type="text/css">
body.custom-background { background-color: #f5f5f5; }
</style> -->
<link rel="alternate" type="application/atom+xml"
title="SKiDL — Flux Atom"
href="/skidl/" />
<!--[if lte IE 8]><script src="/skidl/theme/js/html5shiv.js"></script><![endif]-->
</head>
<body class="home blog custom-background " >
<div id="container">
<div id="header">
<h1 id="site-title"><a href="/skidl"><img src="/skidl/images/banner.png" width="100%"></a></h1>
<!-- <h1 id="site-title"><a href="/skidl">SKiDL</a></h1> -->
</div><!-- /#banner -->
<div id="menu">
<div class="menu-navigation-container">
<ul id="menu-navigation" class="menu">
<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="https://github.com/devbisme/skidl">Github</a></li>
<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="https://github.com/devbisme/skidl/discussions">Forum</a></li>
<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="/skidl/category/posts.html">Blog</a></li>
<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="/skidl/api/html/index.html">API</a></li>
<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="/skidl/">Home</a></li>
</ul>
</div> <!--/#menu-navigation-container-->
</div><!-- /#menu -->
<div class="page-title">
</div>
<div id="contents">
<div class="post type-post status-publish format-standard hentry category-general" id="post">
<div class="entry-meta">
<span class="date"><a href="/skidl/package-decorator-2020-05-27.html">Wed 27 May 2020</a></span>
/
<span class="byline"><a href="/skidl/author/dave-vandenbout.html">Dave Vandenbout</a></span>
</div> <!-- /#entry-meta -->
<div class="main">
<h2 class="entry-title">
<a href="/skidl/package-decorator-2020-05-27.html" title="Permalink to Good Things Come In Packages!" rel="bookmark">Good Things Come In Packages!</a>
</h2>
<div class="entry-content">
<p>Up to now, SKiDL supported hierarchy by applying the <code>@subcircuit</code> decorator to a Python function:</p>
<div class="highlight"><pre><span></span><code><span class="nd">@subcircuit</span>
<span class="k">def</span> <span class="nf">analog_average</span><span class="p">(</span><span class="n">in1</span><span class="p">,</span> <span class="n">in2</span><span class="p">,</span> <span class="n">avg</span><span class="p">):</span>
<span class="w"> </span><span class="sd">"""Output the average of the two inputs."""</span>
<span class="c1"># Create two 1K resistors.</span>
<span class="n">r1</span><span class="p">,</span> <span class="n">r2</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">Part</span><span class="p">(</span><span class="s1">'Device'</span><span class="p">,</span> <span class="s1">'R'</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">'1K'</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>
<span class="c1"># Each input connects thru a resistor to the avg output.</span>
<span class="n">r1</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in1</span><span class="p">,</span> <span class="n">avg</span>
<span class="n">r2</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in2</span><span class="p">,</span> <span class="n">avg</span>
</code></pre></div>
<p>Then this subcircuit is instantiated by calling the function with nets
passed as arguments:</p>
<div class="highlight"><pre><span></span><code><span class="n">in1</span><span class="p">,</span> <span class="n">in2</span><span class="p">,</span> <span class="n">in3</span><span class="p">,</span> <span class="n">in4</span><span class="p">,</span> <span class="n">out1</span><span class="p">,</span> <span class="n">out2</span> <span class="o">=</span> <span class="n">Net</span><span class="p">()</span><span class="o">*</span><span class="mi">6</span> <span class="c1"># Make some I/O nets.</span>
<span class="n">analog_average</span><span class="p">(</span><span class="n">in1</span><span class="p">,</span> <span class="n">in2</span><span class="p">,</span> <span class="n">out1</span><span class="p">)</span> <span class="c1"># One instantiation of the averager.</span>
<span class="o">...</span> <span class="n">Some</span> <span class="n">more</span> <span class="n">code</span> <span class="o">...</span>
<span class="n">analog_average</span><span class="p">(</span><span class="n">in3</span><span class="p">,</span> <span class="n">in4</span><span class="p">,</span> <span class="n">out2</span><span class="p">)</span> <span class="c1"># A second instantiation.</span>
</code></pre></div>
<p>It was <a href="https://github.com/devbisme/skidl/issues/48">pointed out</a> that this method
of instantiating subcircuits is quite different from what is used for parts.
Unlike the connections to a subcircuit that are all made at a single place when the
function is called, the connections to a part can be placed
at various, non-contiguous locations in the code:</p>
<div class="highlight"><pre><span></span><code><span class="n">q_npn</span> <span class="o">=</span> <span class="n">Part</span><span class="p">(</span><span class="s2">"Device"</span><span class="p">,</span> <span class="s2">"Q_NPN_BCE"</span><span class="p">)</span> <span class="c1"># Instantiate a transistor.</span>
<span class="o">...</span>
<span class="n">q_npn</span><span class="p">[</span><span class="s1">'E'</span><span class="p">]</span> <span class="o">+=</span> <span class="n">Net</span><span class="p">(</span><span class="s1">'GND'</span><span class="p">)</span> <span class="c1"># Connect the emitter to ground.</span>
<span class="o">...</span>
<span class="n">q_npn</span><span class="p">[</span><span class="s1">'B'</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in1</span> <span class="c1"># Connect an input to the base.</span>
<span class="o">...</span>
<span class="n">q_npn</span><span class="p">[</span><span class="s1">'C'</span><span class="p">]</span> <span class="o">+=</span> <span class="n">out1</span> <span class="c1"># Connect the output to the collector.</span>
</code></pre></div>
<p>Another issue is that you can pass a part instance as an argument to a subcircuit that
connects it to the internal circuitry.
But you can't do the same thing with a subcircuit function without making changes to the
code because of the syntactic differences in how connections are made:</p>
<div class="highlight"><pre><span></span><code><span class="nd">@subcircuit</span>
<span class="k">def</span> <span class="nf">analog_average</span><span class="p">(</span><span class="n">in1</span><span class="p">,</span> <span class="n">in2</span><span class="p">,</span> <span class="n">avg</span><span class="p">,</span> <span class="n">r</span><span class="p">):</span>
<span class="w"> </span><span class="sd">"""Output the average of the two inputs."""</span>
<span class="n">r1</span><span class="p">,</span> <span class="n">r2</span> <span class="o">=</span> <span class="n">r</span><span class="p">(</span><span class="n">num_copies</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span> <span class="c1"># Create two copies of the resistor part.</span>
<span class="n">r1</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in1</span><span class="p">,</span> <span class="n">avg</span>
<span class="n">r2</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in2</span><span class="p">,</span> <span class="n">avg</span>
<span class="c1"># If r was a subcircuit function, this would have to be written as:</span>
<span class="c1"># r(in1, avg)</span>
<span class="c1"># r(in2, avg)</span>
</code></pre></div>
<p>To make subcircuits act more like parts, the <code>@package</code> decorator has been introduced.
Just replace the <code>@subcircuit</code> decorator while keeping everything else the same:</p>
<div class="highlight"><pre><span></span><code><span class="nd">@package</span>
<span class="k">def</span> <span class="nf">analog_average</span><span class="p">(</span><span class="n">in1</span><span class="p">,</span> <span class="n">in2</span><span class="p">,</span> <span class="n">avg</span><span class="p">):</span>
<span class="n">r1</span><span class="p">,</span> <span class="n">r2</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">Part</span><span class="p">(</span><span class="s1">'Device'</span><span class="p">,</span> <span class="s1">'R'</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">'1K'</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>
<span class="n">r1</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in1</span><span class="p">,</span> <span class="n">avg</span>
<span class="n">r2</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in2</span><span class="p">,</span> <span class="n">avg</span>
</code></pre></div>
<p>Instantiating the subcircuit now occurs in two phases.
First, create instances of the subcircuit wherever they are needed:</p>
<div class="highlight"><pre><span></span><code><span class="n">avg1</span> <span class="o">=</span> <span class="n">analog_average</span><span class="p">()</span>
<span class="o">...</span>
<span class="n">avg2</span> <span class="o">=</span> <span class="n">analog_average</span><span class="p">()</span>
</code></pre></div>
<p>In the second phase, make connections to these subcircuits as if they were parts
with the names of the function parameters serving as pin names:</p>
<div class="highlight"><pre><span></span><code><span class="n">in1</span><span class="p">,</span> <span class="n">in2</span><span class="p">,</span> <span class="n">in3</span><span class="p">,</span> <span class="n">in4</span><span class="p">,</span> <span class="n">out1</span><span class="p">,</span> <span class="n">out2</span> <span class="o">=</span> <span class="n">Net</span><span class="p">()</span><span class="o">*</span><span class="mi">6</span>
<span class="c1"># Make connections. You can use either [] or . to reference the I/O.</span>
<span class="n">avg1</span><span class="p">[</span><span class="s1">'in1'</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in1</span>
<span class="n">avg1</span><span class="o">.</span><span class="n">in2</span> <span class="o">+=</span> <span class="n">in2</span>
<span class="n">avg1</span><span class="p">[</span><span class="s1">'avg'</span><span class="p">]</span> <span class="o">+=</span> <span class="n">out1</span>
<span class="o">...</span>
<span class="n">avg2</span><span class="p">[</span><span class="s1">'in1'</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in3</span>
<span class="n">avg2</span><span class="p">[</span><span class="s1">'in2'</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in4</span>
<span class="n">avg2</span><span class="o">.</span><span class="n">avg</span> <span class="o">+=</span> <span class="n">out2</span>
</code></pre></div>
<p>In addition to nets, pins, and buses, you can pass any other type of
parameter to subcircuits.
For example, <code>analog_average</code> could take a float as a <code>ratio</code> parameter to
set the amount each input contributes to the output:</p>
<div class="highlight"><pre><span></span><code><span class="nd">@package</span>
<span class="k">def</span> <span class="nf">analog_average</span><span class="p">(</span><span class="n">in1</span><span class="p">,</span> <span class="n">in2</span><span class="p">,</span> <span class="n">avg</span><span class="p">,</span> <span class="n">ratio</span><span class="p">):</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">Part</span><span class="p">(</span><span class="s1">'Device'</span><span class="p">,</span> <span class="s1">'R'</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>
<span class="n">r1</span> <span class="o">=</span> <span class="n">r</span><span class="p">(</span><span class="n">value</span><span class="o">=</span><span class="mi">2000</span> <span class="o">*</span> <span class="n">ratio</span><span class="p">)</span>
<span class="n">r2</span> <span class="o">=</span> <span class="n">r</span><span class="p">(</span><span class="n">value</span><span class="o">=</span><span class="mi">2000</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="n">ratio</span><span class="p">))</span>
<span class="n">r1</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in1</span><span class="p">,</span> <span class="n">avg</span>
<span class="n">r2</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">in2</span><span class="p">,</span> <span class="n">avg</span>
</code></pre></div>
<p>Then the subcircuit can either be instantiated with a given ratio:</p>
<div class="highlight"><pre><span></span><code><span class="n">avg1</span> <span class="o">=</span> <span class="n">analog_average</span><span class="p">(</span><span class="n">ratio</span><span class="o">=</span><span class="mf">0.25</span><span class="p">)</span>
<span class="n">avg1</span><span class="o">.</span><span class="n">in1</span> <span class="o">+=</span> <span class="n">in1</span>
<span class="n">avg1</span><span class="o">.</span><span class="n">in2</span> <span class="o">+=</span> <span class="n">in2</span>
<span class="n">avg1</span><span class="o">.</span><span class="n">avg</span> <span class="o">+=</span> <span class="n">out1</span>
</code></pre></div>
<p>or you can set the ratio outside the function call:</p>
<div class="highlight"><pre><span></span><code><span class="n">avg2</span> <span class="o">=</span> <span class="n">analog_average</span><span class="p">()</span>
<span class="n">avg2</span><span class="o">.</span><span class="n">ratio</span> <span class="o">=</span> <span class="mf">0.25</span> <span class="c1"># Use a normal assignment (=) since this is not a circuit connection.</span>
<span class="n">avg2</span><span class="o">.</span><span class="n">in1</span> <span class="o">+=</span> <span class="n">in3</span>
<span class="n">avg2</span><span class="o">.</span><span class="n">in2</span> <span class="o">+=</span> <span class="n">in4</span>
<span class="n">avg2</span><span class="o">.</span><span class="n">avg</span> <span class="o">+=</span> <span class="n">out2</span>
</code></pre></div>
<p>A subcircuit function instantiates its circuitry when it is called.
But this doesn't happen when using a package.
Instead, the subcircuit is placed in a list and executed after the
complete circuit is finalized
(i.e., whenever <code>ERC()</code> or <code>generate_netlist()</code> is called).
The arguments passed to the function consist of the connections
and other values that were assigned to the package parameters in the preceding code.</p>
<p>That's about it for the <code>@package</code> decorator.
Since it's new, it hasn't seen a lot of use and there could be unknown bugs
lying in wait.
If you have questions or problems, please ask on the
<a href="https://skidl.discourse.group/">SKiDL forum</a> or
raise an <a href="https://github.com/devbisme/skidl/issues">issue</a>. </p>
</div> <!--/#entry-content-->
</div> <!--/#main-->
</div> <!--/#post-->
</div>
<div id="footer">
<p> </p>
</div><!-- /#footer -->
</div><!-- /#container -->
<div style="display:none"></div>
</body>
</html>