-
Notifications
You must be signed in to change notification settings - Fork 120
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
xesscorp
committed
May 9, 2021
1 parent
7c7e07e
commit db1bdd8
Showing
12 changed files
with
24,541 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
--- | ||
layout: post | ||
title: Automatic Schematic! | ||
date: 2020-09-24T10:01:10-05:00 | ||
author: | ||
name: Dave Vandenbout | ||
photo: devb-pic.jpg | ||
email: [email protected] | ||
description: Relax, I do this stuff for a living. | ||
category: blog | ||
permalink: blog/automatic-schematic | ||
--- | ||
|
||
Everybody wants ERC. Everybody hates ERC. | ||
|
||
Electrical rules checking (ERC) looks for errors in how your circuit is constructed. | ||
It's like running [`lint`](https://en.wikipedia.org/wiki/Lint_(software)), but for hardware. | ||
And as with `lint`, you get a whole bunch of warnings that don't matter but which | ||
*obscure the ones that do*. | ||
|
||
SKiDL tries to help by allowing you to | ||
[selectively turn off ERC](https://xesscorp.github.io/skidl/docs/_site/index.html#selectively-supressing-erc-messages) | ||
for nets, pins, and parts. | ||
That fixes part of the problem. | ||
|
||
The other part is the inflexibility of ERC: it has fixed rules for common errors | ||
(like two outputs driving against each other), but adding rules for special cases | ||
isn't easy. | ||
|
||
The `erc_assert()` function was added to SKiDL to make customizing ERC easier. | ||
With `erc_assert()`, you can add specialized rules that are checked only | ||
in particular instances. | ||
In the example below, `erc_assert()` is used to | ||
flag nets that have too much fanout: | ||
|
||
```py | ||
from skidl import * | ||
|
||
# Function to get the number of inputs on a net. | ||
def get_fanout(net): | ||
fanout = 0 | ||
for pin in net.get_pins(): | ||
if pin.func in (Pin.INPUT, Pin.BIDIR): | ||
fanout += 1 | ||
return fanout | ||
|
||
net1, net2 = Net('IN1'), Net('IN2') | ||
|
||
# Place some assertions on the fanout of each net. | ||
# Note that the assertions are passed as strings. | ||
erc_assert('get_fanout(net1) < 5', 'failed on net1') | ||
erc_assert('get_fanout(net2) < 5', 'failed on net2') | ||
|
||
# Attach some pins to the nets. | ||
net1 += Pin(func=Pin.OUTPUT) | ||
net2 += Pin(func=Pin.OUTPUT) | ||
net1 += Pin(func=Pin.INPUT) * 4 # This net passes the assertion. | ||
net2 += Pin(func=Pin.INPUT) * 5 # This net fails because of too much fanout. | ||
|
||
# When the ERC runs, it will also evaluate any erc_assert statements. | ||
ERC() | ||
``` | ||
```terminal | ||
ERC ERROR: get_fanout(net2) < 5 failed on net2 in <ipython-input-20-766848d35dca>:16:<module>. | ||
0 warnings found during ERC. | ||
1 errors found during ERC. | ||
``` | ||
|
||
You might ask: “Why not just use the standard Python `assert` statement?” | ||
The reason is that a standard assertion is evaluated as soon as the `assert` statement | ||
is encountered so the result might be incorrect if the nets | ||
are not yet completely defined. | ||
But the statement passed to the `erc_assert()` function is a **string** that | ||
isn’t evaluated until all the circuitry has been connected and ERC() is called. | ||
Note in the code above that when the `erc_assert()` function is called, | ||
no pins are even attached to the `net1` or `net2` nets. | ||
The `erc_assert()` function just places the statement to be checked into | ||
a queue that gets evaluated when `ERC()` is run. | ||
By then, the nets will have pins attached by then. | ||
|
||
You can perform more complicated checks by creating a function and then placing a call | ||
to it in the assertion string: | ||
|
||
```py | ||
from skidl import * | ||
|
||
def get_fanout(net): | ||
fanout = 0 | ||
for pin in net.get_pins(): | ||
if pin.func in (Pin.INPUT, Pin.BIDIR): | ||
fanout += 1 | ||
return fanout | ||
|
||
# Function to check a fanout constraint on a net and drop into | ||
# the debugger if the constraint is violated. | ||
def check_fanout(net, threshold): | ||
fanout = get_fanout(net) | ||
if fanout >= threshold: | ||
# Report the net which violated the constraint." | ||
print(f'{net.name} fanout of {fanout} >= {threshold}.') | ||
|
||
# Drop into the debugger so you can query the circuit | ||
# and then continue. | ||
breakpoint() | ||
|
||
return False # Return False to trigger the erc_assert(). | ||
|
||
return True # Return True if the constraint is not violated. | ||
|
||
net1, net2 = Net('IN1'), Net('IN2') | ||
|
||
# Place calls to the check_fanout() function into the assertions. | ||
erc_assert('check_fanout(net1, 5)') | ||
erc_assert('check_fanout(net2, 5)') | ||
|
||
net1 += Pin(func=Pin.OUTPUT) | ||
net2 += Pin(func=Pin.OUTPUT) | ||
net1 += Pin(func=Pin.INPUT) * 4 | ||
net2 += Pin(func=Pin.INPUT) * 5 | ||
|
||
ERC() | ||
``` | ||
```terminal | ||
IN2 fanout of 5 >= 5. | ||
> <ipython-input-18-800a83e11624>(22)check_fanout() | ||
-> return False # Return False to trigger the erc_assert(). | ||
(Pdb) c | ||
ERC ERROR: check_fanout(net2, 5) FAILED in <ipython-input-18-800a83e11624>:30:<module>. | ||
0 warnings found during ERC. | ||
1 errors found during ERC. | ||
``` | ||
|
||
You can detect if a subcircuit is being used correctly by embedding calls to | ||
`erc_assert()` to check inputs, outputs, and internal circuitry: | ||
|
||
```py | ||
from skidl import * | ||
|
||
# Return True if the net has a pullup on it, False if not. | ||
def has_pullup(net): | ||
for pin in net.get_pins(): | ||
if pin.func == Pin.PULLUP: | ||
return True | ||
|
||
print(f'No pullup on net {net.name}') | ||
return False | ||
|
||
@subcircuit | ||
def some_circuit(in1, in2): | ||
# Check the subcircuit inputs to see if they have pullups. | ||
erc_assert('has_pullup(in1)') | ||
erc_assert('has_pullup(in2)') | ||
|
||
# OK, this subcircuit doesn't really do anything, so you'll | ||
# just have to imagine that it did. | ||
pass | ||
|
||
net1, net2 = Net('IN1'), Net('IN2') | ||
|
||
# Instantiating the subcircuit automatically checks the input nets. | ||
some_circuit(net1, net2) | ||
|
||
net1 += Pin(func=Pin.OUTPUT) | ||
net1 += Pin(func=Pin.INPUT) # No pullup -> this net fails. | ||
net2 += Pin(func=Pin.OUTPUT) | ||
net2 += Pin(func=Pin.PULLUP) | ||
|
||
ERC() | ||
``` | ||
```terminal | ||
No pullup on net IN1 | ||
ERC ERROR: has_pullup(in1) FAILED in <ipython-input-16-6e72ef7d46c8>:15:some_circuit. | ||
0 warnings found during ERC. | ||
1 errors found during ERC. | ||
``` | ||
|
||
You can even use the `erc_assert()` function to add global checks | ||
that scan the entire circuit for violations of custom rules: | ||
|
||
```py | ||
from skidl import * | ||
|
||
# Global function that checks all the nets in the circuit and | ||
# flags nets which have pullups when they shouldn't. | ||
def my_erc(): | ||
erc_result = True | ||
for net in default_circuit.get_nets(): | ||
if getattr(net, 'disallow_pullups', False) == True: | ||
pin_types = [pin.func for pin in net.get_pins()] | ||
if Pin.PULLUP in pin_types: | ||
print(f'Pull-up not allowed on {net.name}.') | ||
erc_result = False | ||
return erc_result | ||
|
||
net1, net2 = Net('IN1'), Net('IN2') | ||
|
||
net1.disallow_pullups = True # Don't allow pullups on this net. | ||
net1 += Pin(func=Pin.INPUT) | ||
net1 += Pin(func=Pin.PULLUP) # This net will fail ERC. | ||
net2 += Pin(func=Pin.INPUT) | ||
net2 += Pin(func=Pin.PULLUP) | ||
|
||
# Call your own customized global ERC. | ||
erc_assert('my_erc()') | ||
|
||
ERC() | ||
``` | ||
```terminal | ||
Pull-up not allowed on IN1. | ||
ERC ERROR: my_erc() FAILED in <ipython-input-12-888102e7799c>:24:<module>. | ||
0 warnings found during ERC. | ||
1 errors found during ERC. | ||
``` | ||
|
||
That's about it for the `erc_assert()` function. | ||
Since it's new, it hasn't seen a lot of use so there could be | ||
modifications that are needed to make it more useful. | ||
If you have questions or problems, please ask on the | ||
[SKiDL forum](https://skidl.discourse.group/) or | ||
raise an [issue](https://github.com/xesscorp/skidl/issues). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
--- | ||
layout: post | ||
title: 1.0 | ||
date: 2021-05-09T10:01:10-05:00 | ||
author: | ||
name: Dave Vandenbout | ||
photo: devb-pic.jpg | ||
email: [email protected] | ||
description: Relax, I do this stuff for a living. | ||
category: blog | ||
permalink: blog/one-dot-oh | ||
--- | ||
|
||
Nearly a year after 0.0.30, today marks the release of SKiDL version **1.0.0**. | ||
But why assign such an exalted milestone to *this* release given the relative | ||
paucity of [new features](https://github.com/xesscorp/skidl/blob/master/HISTORY.rst#100-2021-05-09), | ||
most of them mundane (with the possible exception of | ||
[automatic generation of schematics](https://xess.com/skidl/docs/_site/index.html#svg-schematics))? | ||
|
||
Because I said so. | ||
|
||
It's time I cut the cord and ramped down the language-evolution phase of SKiDL. | ||
The syntax is pretty complete and has the necessary features for compactly | ||
describing circuits. | ||
Now it's time to concentrate on building things around and on top of SKiDL. | ||
([zyc](https://xess.com/zyc/docs/_build/singlehtml/index.html) | ||
was an early example of doing that.) | ||
The added infrastructure will help new users get productive with SKiDL faster. | ||
And as the surrounding environment is developed, the tempo of new SKiDL releases | ||
may increase since using a language always exposes | ||
weaknesses that need to be fixed. | ||
So SKiDL probably won't stay at 1.0.0 for long. | ||
And hopefully these changes will be corrective, not disruptive. | ||
|
||
Now, on to Phase 2! |
Oops, something went wrong.