203 lines
9.3 KiB
Plaintext
203 lines
9.3 KiB
Plaintext
Second major code overhaul of 2026
|
|
-----------------------------------------
|
|
Implement the planned changes to "extresist":
|
|
|
|
(1) Remove the .sim format as a requirement. extresist will get its node
|
|
list from doing a standard extraction (extFindNodes() or
|
|
ExtFindRegions(), whichever is appropriate. This should be able to be
|
|
done as a relatively simple change, allowing "extresist" to be used
|
|
without doing "ext2sim" as part of the process.
|
|
|
|
(2) Move extresist into the "extract" code. "extresist" will become a
|
|
command "extract do extresist" and "ext2spice extresist on|off"
|
|
will determine if split nodes and terminals are kept apart in the
|
|
final netlist or aggregated---Exactly as capacitance is done now.
|
|
|
|
Need to figure out how "tile junk" client data and extract client
|
|
data can exist simultaneously.
|
|
|
|
"extresist" will run within "extBasic", being called on a node after
|
|
the devices and nodes are identified; nodes created by ExtFindRegions()
|
|
will get sub-divided into more nodes. The difficult case will be where
|
|
a single tile gets multiple nodes (such as where other wires branch off
|
|
the tile in the up or down direction). Maybe this can be done like
|
|
ClientData for split tiles, with an indicator bit in ti_body?
|
|
|
|
-----------------------------------------------------
|
|
For (1):
|
|
|
|
Reading the "nodes" file only creates "node" entries, one per net.
|
|
With an ExtFindRegions and ExtLabelRegions (or extFindNodes?) there
|
|
should be an equivalent list from which node names, locations, and
|
|
types can be taken. This information will be redundant, for now.
|
|
|
|
Note that ExtResisForDef() runs extResPrepSubstrate() which is like
|
|
extPrepSubstrate(), which is run from extCellFile().
|
|
|
|
So ExtResisForDef() could replace lines 150 to 174 with the ExtBasic
|
|
calls to ExtFindRegions(), extFindNodes(), and ExtLabelRegions().
|
|
This is followed by temporary code that creates the tables and lists
|
|
that the extresist code uses. Then, run the ResCheckSimNodes() code,
|
|
or at least the part for a single node (which is ResRex.c lines 1071
|
|
to 1240)
|
|
|
|
Add a ClientData record to a NodeRegion, and extresist can run
|
|
by adding "tileJunk" records to the NodeRegion client data, and
|
|
leave the region records in place. (done)
|
|
|
|
Then need to figure out how to output the data all at once.
|
|
|
|
Replace the "extresist" command with "extract do extresist".
|
|
EXT_DOEXTRESIST. Maybe later replace "resistance" and make it
|
|
equivalent to "extresist", or maybe make "resistance" *be*
|
|
DOEXTRESIST and use "lumped" instead of "resistance" (I like
|
|
this better). (done)
|
|
|
|
"ext2spice extresist on" will then output the netlist exactly as
|
|
it appears in the .ext file, while "ext2spice extresist off" will
|
|
conglomerate the .tX and .nX sub-nodes and produce what is
|
|
hopefully the equivalent of a netlist from a .ext file without
|
|
"extract do extresist".
|
|
|
|
We keep (maybe)
|
|
HashTable ResNodeTable
|
|
RDev *ResRDevList
|
|
|
|
At issue: Doing it this way might be more convenient, but by
|
|
keeping the NodeRegions in place and adding "tileJunk" records,
|
|
it's harder to find where the subnets are connected. If the
|
|
NodeRegions get replaced, then there are way more regions but,
|
|
for example, a transistor terminal node is easily found by
|
|
looking at the Region pointer connected to the terminal type.
|
|
However, nodes are output by working through the node list and
|
|
devices are output by working through the device list, so the
|
|
information is readily available.
|
|
|
|
Currently the "to-do" work starts at ExtBasic.c line 313.
|
|
|
|
Pulled out the central part of ResCheckSimNodes() into "ResProcessNode()".
|
|
This allows ExtBasic.c to loop over its own nodeList, prepare the
|
|
ResSimNode structure, and then call ResProcessNode() to process a
|
|
single network.
|
|
|
|
These are all then bypassed:
|
|
|
|
CmdExtResist()
|
|
ExtResisForDef()
|
|
extResPrepSubstrate()
|
|
ResReadSim()
|
|
ResCheckPorts()
|
|
ResCheckSimNodes()
|
|
(clean up ResNodeTable and ResRDevList)
|
|
|
|
The only one of the bypassed routines which may need to be handled
|
|
is "ResCheckPorts()". Possibly the ExtSubtree/ExtHier stuff can be
|
|
used in place? The main issue is figuring out where the ports are.
|
|
Unlike the original "extresist" method, it should be possible to do
|
|
this properly. Punt on it for the moment.
|
|
|
|
Try to compile with the separated-out ResProcessNode() routine.
|
|
Okay, got that working.
|
|
|
|
Now, the hard work: Prepare an extresist node record from ExtBasic.c.
|
|
Don't worry about how ClientData records are managed, for now.
|
|
|
|
Now, what does ResCleanUpEverything() do? We don't want to destroy
|
|
the records until the end. Maybe node regions should be replaced by
|
|
subnets here? And the resistors can be kept in a linked list or
|
|
hash table to be output along with the devices.
|
|
|
|
The issue here is that some tiles can contain multiple sub-nets,
|
|
if there are wires branching off. Note, however, that wires can
|
|
only branch off of a single rectangle in the north or south directions,
|
|
due to the "maximum horizontal stripes" rule. What if subnets within
|
|
a tile were handled by splitting the tile, which would only be done
|
|
horizontally, and keeping the tiles separate by setting a flag in
|
|
ti_body such that a long wire with many branches would be split into
|
|
multiple segments with the flag set to 1010101. . ., which allows the
|
|
normal tile handling to work. The flags can be cleaned up afterward
|
|
and the tiles merged (maybe just erase and repaint the tile)? Note
|
|
that this would never happen with split tiles. Probably okay with
|
|
contacts?
|
|
|
|
Due to the maximum horizontal stripes consideration, does
|
|
ResCalcNorthSouth() *ever* get called??
|
|
Okay, a long vertical contact with metal branches on either side
|
|
would invalidate my assumption, and yes, ResCalcNorthSouth() would
|
|
be called. Okay, so never mind that one.
|
|
|
|
Quandary: ResProcessNode() is pretty self-contained and cleans
|
|
up after itself. But extBasic() finds all nodes and keeps them
|
|
around for the duration of the extraction, and needs to have the
|
|
extresist splits on hand for coupling capacitance calculations
|
|
and all output. Maybe copy in a simplified form to yet another
|
|
ClientData field on a nodeRegion.
|
|
|
|
So there's another way to go about it:
|
|
(1) When running extract, create the device record for extresist
|
|
after running transList = ExtFindRegions(). This list does
|
|
not change between being created and the transistors being
|
|
output.
|
|
(2) Create the node record for extresist after running extFindNodes().
|
|
(3) With this information, it's possible to run extresist on the
|
|
node. Because nodes have all been marked with regions, use
|
|
a ClientData record in NodeRegion to store the extresist working
|
|
data. Clean up afterward; the NodeRegion records still remain
|
|
in place on the tiles.
|
|
|
|
The simplest approach is just to write the .res.ext annotation file
|
|
as before, although with the extresist code being run before the
|
|
.ext file is written, it is possible to combine the two. But the
|
|
use of .res.ext is a quicker intermediate step that allows the
|
|
extresist code to be checked for hierarchical operation, which it
|
|
will now be able to do relatively smoothly, as it is not necessary
|
|
to create multiple .sim and .node files for each subcircuit.
|
|
|
|
Trickier: Replace NodeRegions with the subnet regions. One
|
|
difficulty here is dealing with multiple subnets in a single tile.
|
|
|
|
Simplifying the extresist code by removing references to ARIEL
|
|
and LAPLACE (which are missing code and so cannot be reinstated
|
|
without a lot of guesswork), and removing some apparently nonfunctional
|
|
code having to do with events.
|
|
|
|
To do after finding transistors: What's done in ResReadSim():
|
|
Specifically, ResSimDevice() and ResSimSubckt().
|
|
|
|
ResReadNode() is the only thing needed to be done for nodes.
|
|
It calls ResInitializeNode() and sets location and (tile) type.
|
|
Everything else in the structure is TBD.
|
|
|
|
Another issue: The device type is determined by "extract" only
|
|
during extOutputDevices. The device type in "devrec" is not
|
|
computed until just before the device is output. But. . . is
|
|
this really needed by extresist? It was being used by extresist
|
|
because the device name is what's in the .sim file.
|
|
|
|
You know what probably works best?
|
|
(1) When nodes are written to the .ext file, save the information
|
|
for extresist.
|
|
(2) When devices are written to the .ext file, save the information
|
|
for extresist.
|
|
(3) Run extresist at the end of the cell def's extraction, and write
|
|
the .res.ext file as usual. (Later, maybe, get rid of the
|
|
.res.ext file and just re-write the annotated .ext file.)
|
|
(4) Create a new method for annotated coupling capacitances.
|
|
Recompute the coupling and output adjustments (positive for
|
|
the new node/terminal nodes, negative for the original node).
|
|
Coupling will be recomputed only for nets processed by
|
|
extresist. Node substrate capacitance changes will be
|
|
recorded in .res.ext (but---I think substrate capacitance is
|
|
now unused in the node record, because there is a substrate
|
|
node and substrate capacitance is now treated like coupling
|
|
to that node; isn't that right?) (and there will be multiple
|
|
substrate nodes, as well.)
|
|
|
|
This can also be done in two steps:
|
|
(1) Replace ResReadSim() with ResReadExt() and read back the .ext
|
|
file immediately after writing it.
|
|
(2) Remove the read-back and just generate the information on the
|
|
fly.
|
|
|
|
This also has the advantage that it can be tested in parts.
|