<> <> <<>> DIRECTORY Convert, Core, CoreFlat, CoreOps, CoreClasses, HashTable, ElectricalCoreClasses, Rope, SpiceOps, TerminalIO, TiogaFileOps; SpiceInputGenImpl: CEDAR PROGRAM IMPORTS Convert, CoreFlat, CoreOps, CoreClasses, HashTable, ElectricalCoreClasses, Rope, TerminalIO, TiogaFileOps EXPORTS SpiceOps = BEGIN s: TYPE = REAL; ROPE: TYPE = Rope.ROPE; TNode: TYPE = TiogaFileOps.Ref; CellType: TYPE = Core.CellType; FlatWire: TYPE = CoreFlat.FlatWire; ConvData: TYPE = REF ConvDataRec; ConvDataRec: TYPE = RECORD[ rootCell: Core.CellType, rootNode: TNode, wTable: HashTable.Table, nextId: CARD _ 0, initList: ROPE, tranList: ROPE, printList: ROPE ]; FlatCellProc: TYPE = PROC [cell: Core.CellType, target: CoreFlat.FlatCellTypeRec _ CoreFlat.allFlatCells, flatCell: CoreFlat.FlatCellTypeRec _ [], instance: CoreClasses.CellInstance _ NIL, parent: Core.CellType _ NIL, flatParent: CoreFlat.FlatCellTypeRec _ [], data: REF ANY _ NIL, wireName: HashTable.Table]; <> lineLength: NAT _ 80; sep: ROPE _ " "; infinity: NAT _ LAST[NAT]; femto: REAL _ 1e-15; pico: REAL _ 1e-12; nano: REAL _ 1e-9; micro: REAL _ 1e-6; mili: REAL _ 1e-3; kilo: REAL _ 1e3; mega: REAL _ 1e6; giga: REAL _ 1e9; tera: REAL _ 1e12; gndName: PUBLIC ROPE _ "public.Gnd"; vddName: PUBLIC ROPE _ "public.Vdd"; pModel: PUBLIC ROPE _ "PMOS"; nModel: PUBLIC ROPE _ "NMOS"; diodeModel: PUBLIC ROPE _ "D"; <> WriteSpiceDeck: PUBLIC PROC [cellType: CellType, outputFile: ROPE _ NIL] = BEGIN convData: ConvData _ NEW[ConvDataRec]; IF outputFile=NIL THEN IF CoreOps.GetCellTypeName[cellType]=NIL THEN outputFile _ "///Temp/Spice/Simulation.spice" ELSE outputFile _ Rope.Cat["///Temp/Spice/", CoreOps.GetCellTypeName[cellType], ".spice"]; convData.rootCell _ cellType; convData.wTable _ HashTable.Create[equal: CoreFlat.FlatWireEqual, hash: CoreFlat.FlatWireHash]; convData.rootNode _ TiogaFileOps.CreateRoot[]; PutHeader[convData, outputFile]; NetFromCore[convData]; PutEnd[convData, outputFile]; END; <> WriteInstance: PROC [convData: ConvData, rope: ROPE] ~ { tNode: TNode _ TiogaFileOps.InsertAsLastChild[convData.rootNode]; IF Rope.Length[rope]lineLength DO index _ index2; index2 _ Rope.Index[rope, index+1, sep]; ENDLOOP; TiogaFileOps.SetContents[tNode, Rope.Substr[rope, 0, index]]; WriteInstance[convData, Rope.Concat["+", Rope.Substr[rope, index+1]]]; }; }; WireId: PROC [convData: ConvData, wire: FlatWire] RETURNS [id: ROPE] ~ { found: BOOL; value: HashTable.Value; [found, value] _ HashTable.Fetch[convData.wTable, wire]; IF found THEN RETURN [NARROW[value, ROPE]]; id _ NextInstanceId[convData]; [] _ HashTable.Insert[convData.wTable, wire, id]; Comment[convData, Rope.Cat[id, ": ", CoreFlat.WirePathRope[convData.rootCell, wire^]]]; }; NextInstanceId: PROC [convData: ConvData] RETURNS [id: ROPE] ~ { convData.nextId _ convData.nextId+1; id _ Convert.RopeFromCard[from: convData.nextId, showRadix: FALSE]; id _ Rope.Concat[id, " "]; }; RealToRope: PROC [r: REAL, m: REAL _ 1.0] RETURNS [rope: ROPE] ~ { c: REAL _ 1.0; r _ r*m; IF r=0.0 THEN RETURN["0 "]; FOR x: REAL _ ABS[r], x*1000.0 UNTIL x>=1.0 DO c _ c/1000.0; ENDLOOP; FOR x: REAL _ ABS[r], x/1000.0 UNTIL x<1000.0 DO c _ c*1000.0; ENDLOOP; rope _ Rope.Concat[Convert.RopeFromReal[r/c], SELECT c FROM 1e12 => "T ", 1e09 => "G ", 1e06 => "MEG ", 1e03 => "K ", 1e00 => " ", 1e-3 => "M ", 1e-6 => "U ", 1e-9 => "N ", 1e-12 => "P ", 1e-15 => "F ", ENDCASE => ERROR]; -- Value outside of range... }; Comment: PROC [convData: ConvData, comment: ROPE] ~ { tNode: TNode _ TiogaFileOps.InsertAsLastChild[convData.rootNode]; TiogaFileOps.SetContents[tNode, Rope.Concat["* ", comment]]; }; Resistor: PROC [convData: ConvData, n1, n2: FlatWire, value: REAL, tc1, tc2: REAL _ 0.0] ~ { res: ROPE _ Rope.Concat[base: "R", rest: NextInstanceId[convData]]; res _ Rope.Cat[res, WireId[convData, n1], WireId[convData, n2]]; res _ Rope.Concat[res, RealToRope[value, kilo]]; IF tc1#0.0 OR tc2#0.0 THEN res _ Rope.Cat[res, " TC=", RealToRope[tc1], ",", RealToRope[tc2]]; WriteInstance[convData, res]; }; Capacitor: PROC [convData: ConvData, n1, n2: FlatWire, value: REAL, incond: REAL _ 0.0] ~ { cap: ROPE _ Rope.Concat[base: "C", rest: NextInstanceId[convData]]; cap _ Rope.Cat[cap, WireId[convData, n1], WireId[convData, n2]]; cap _ Rope.Concat[cap, RealToRope[value, pico]]; IF incond#0.0 THEN cap _ Rope.Cat[cap, " IC=", RealToRope[incond]]; WriteInstance[convData, cap] }; Inductor: PROC [convData: ConvData, n1, n2: FlatWire, value: REAL, incond: REAL _ 0.0] ~ { ind: ROPE _ Rope.Concat[base: "L", rest: NextInstanceId[convData]]; ind _ Rope.Cat[ind, WireId[convData, n1], WireId[convData, n2]]; ind _ Rope.Concat[ind, RealToRope[value, micro]]; IF incond#0.0 THEN ind _ Rope.Cat[ind, " IC=", RealToRope[incond]]; WriteInstance[convData, ind] }; CoupledInductors: PROC [convData: ConvData, n0, n1, n2, n3: FlatWire, l1, l2: REAL, k: REAL] ~ { cind: ROPE _ Rope.Concat[base: "K", rest: NextInstanceId[convData]]; Inductor[convData, n0, n1, l1]; cind _ Rope.Cat[cind, "L", Convert.RopeFromCard[from: convData.nextId, showRadix: FALSE], " "]; Inductor[convData, n2, n3, l2]; cind _ Rope.Cat[cind, "L", Convert.RopeFromCard[from: convData.nextId, showRadix: FALSE], " "]; cind _ Rope.Concat[cind, RealToRope[k]]; WriteInstance[convData, cind] }; LosslessLine: PROC [convData: ConvData, n0, n1, n2, n3: FlatWire, z0: REAL, td: REAL] ~ { lline: ROPE _ Rope.Concat[base: "T", rest: NextInstanceId[convData]]; lline _ Rope.Cat[lline, WireId[convData, n0], WireId[convData, n1]]; lline _ Rope.Cat[lline, WireId[convData, n2], WireId[convData, n3]]; lline _ Rope.Cat[lline, "Z0=", RealToRope[z0, kilo], "TD=", RealToRope[td, nano]]; WriteInstance[convData, lline] }; Vccs: PROC [convData: ConvData, n0, n1, n2, n3: FlatWire, value: REAL] ~ { lsource: ROPE _ Rope.Concat[base: "G", rest: NextInstanceId[convData]]; lsource _ Rope.Cat[lsource, WireId[convData, n0], WireId[convData, n1]]; lsource _ Rope.Cat[lsource, WireId[convData, n2], WireId[convData, n3]]; lsource _ Rope.Concat[lsource, RealToRope[value]]; WriteInstance[convData, lsource] }; Vcvs: PROC [convData: ConvData, n0, n1, n2, n3: FlatWire, value: REAL] ~ { lsource: ROPE _ Rope.Concat[base: "E", rest: NextInstanceId[convData]]; lsource _ Rope.Cat[lsource, WireId[convData, n0], WireId[convData, n1]]; lsource _ Rope.Cat[lsource, WireId[convData, n2], WireId[convData, n3]]; lsource _ Rope.Concat[lsource, RealToRope[value]]; WriteInstance[convData, lsource] }; Cccs: PROC [convData: ConvData, n0, n1, n2, n3: FlatWire, value: REAL] ~ { lsource: ROPE _ Rope.Concat[base: "F", rest: NextInstanceId[convData]]; lsource _ Rope.Cat[lsource, WireId[convData, n0], WireId[convData, n1]]; VSource[convData, n2, n3]; lsource _ Rope.Cat[lsource, "V", Convert.RopeFromCard[from: convData.nextId, showRadix: FALSE], " "]; lsource _ Rope.Concat[lsource, RealToRope[value]]; WriteInstance[convData, lsource] }; Ccvs: PROC [convData: ConvData, n0, n1, n2, n3: FlatWire, value: REAL] ~ { lsource: ROPE _ Rope.Concat[base: "H", rest: NextInstanceId[convData]]; lsource _ Rope.Cat[lsource, WireId[convData, n0], WireId[convData, n1]]; VSource[convData, n2, n3]; lsource _ Rope.Cat[lsource, "V", Convert.RopeFromCard[from: convData.nextId, showRadix: FALSE], " "]; lsource _ Rope.Concat[lsource, RealToRope[value]]; WriteInstance[convData, lsource] }; Diode: PROC [convData: ConvData, n1, n2: FlatWire, model: ROPE, area: REAL] ~ { diode: ROPE _ Rope.Concat[base: "D", rest: NextInstanceId[convData]]; diode _ Rope.Cat[diode, WireId[convData, n1], WireId[convData, n2]]; diode _ Rope.Concat[diode, model]; diode _ Rope.Concat[diode, RealToRope[area, pico]]; WriteInstance[convData, diode] }; VSource: PROC [convData: ConvData, n1, n2: FlatWire, dc: REAL _ 0.0] ~ { vs: ROPE _ Rope.Concat[base: "V", rest: NextInstanceId[convData]]; vs _ Rope.Cat[vs, WireId[convData, n1], WireId[convData, n2]]; IF dc#0.0 THEN vs _ Rope.Cat[vs, " DC ", RealToRope[dc]]; WriteInstance[convData, vs] }; ISource: PROC [convData: ConvData, n1, n2: FlatWire, ma: REAL _ 0.0] ~ { is: ROPE _ Rope.Concat[base: "I", rest: NextInstanceId[convData]]; is _ Rope.Cat[is, WireId[convData, n1], WireId[convData, n2]]; IF ma#0.0 THEN is _ Rope.Cat[is, " DC ", RealToRope[ma, mili]]; WriteInstance[convData, is] }; PulseVS: PROC [convData: ConvData, n1, n2: FlatWire, v1, v2, td, tr, tf, pw, per: REAL _ 0.0] ~ { vs: ROPE _ Rope.Concat[base: "V", rest: NextInstanceId[convData]]; vs _ Rope.Cat[vs, WireId[convData, n1], WireId[convData, n2]]; vs _ Rope.Cat[vs, "PULSE(", RealToRope[v1], RealToRope[v2]]; vs _ Rope.Cat[vs, RealToRope[td, nano], RealToRope[tr, nano], RealToRope[tf, nano]]; vs _ Rope.Cat[vs, RealToRope[pw, nano], RealToRope[per, nano], ")"]; WriteInstance[convData, vs] }; MOSFet: PROC [convData: ConvData, gate, drain, source, bulk: FlatWire, model: ROPE, l, w, ad, as: REAL] ~ { mos: ROPE _ Rope.Concat[base: "M", rest: NextInstanceId[convData]]; mos _ Rope.Cat[mos, WireId[convData, drain], WireId[convData, gate], WireId[convData, source], WireId[convData, bulk]]; mos _ Rope.Concat[mos, model]; mos _ Rope.Cat[mos, " L=", RealToRope[l, micro], " W=", RealToRope[w, micro]]; IF ad#0.0 OR as#0.0 THEN mos _ Rope.Cat[mos, "AD=", RealToRope[ad, pico], " AS=", RealToRope[as, pico]]; WriteInstance[convData, mos] }; PutHeader: PROC [convData: ConvData, outputFile: ROPE] ~ { node: TNode; vddWire, gndWire: FlatWire; node0: ROPE _ "0 "; TiogaFileOps.SetStyle[convData.rootNode, "Cedar"]; node _ TiogaFileOps.InsertAsLastChild[convData.rootNode]; Comment[convData, CoreOps.GetCellTypeName[convData.rootCell]]; <> vddWire _ NEW[CoreFlat.FlatWireRec _ CoreFlat.ParseWirePath[convData.rootCell, vddName]]; gndWire _ NEW[CoreFlat.FlatWireRec _ CoreFlat.ParseWirePath[convData.rootCell, gndName]]; [] _ HashTable.Insert[convData.wTable, gndWire, node0]; VSource[convData, vddWire, gndWire, 5.0]; }; PutEnd: PROC [convData: ConvData, outputFile: ROPE] ~ { node: TNode; IF convData.initList#NIL THEN { node _ TiogaFileOps.InsertAsLastChild[convData.rootNode]; TiogaFileOps.SetContents[node, Rope.Concat[".IC ", convData.initList]]; }; node _ TiogaFileOps.InsertAsLastChild[convData.rootNode]; TiogaFileOps.SetContents[node, Rope.Concat[".PRINT TRAN ", convData.printList]]; node _ TiogaFileOps.InsertAsLastChild[convData.rootNode]; TiogaFileOps.SetContents[node, Rope.Concat[".TRAN ", convData.tranList]]; node _ TiogaFileOps.InsertAsLastChild[convData.rootNode]; TiogaFileOps.SetContents[node, ".END"]; TiogaFileOps.Store[convData.rootNode, outputFile] }; <> NextCellType: PROC [cell: Core.CellType, target: CoreFlat.FlatCellTypeRec, flatCell: CoreFlat.FlatCellTypeRec, instance: CoreClasses.CellInstance, parent: Core.CellType, flatParent: CoreFlat.FlatCellTypeRec, data: REF ANY, wireName: HashTable.Table, proc: FlatCellProc] = { BindCellType: CoreFlat.UnboundFlatCellProc = { BindPublicToActual: CoreOps.EachWirePairProc = { <> IF publicWire.size=0 THEN { flatWire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[table: wireName, key: actualWire].value]; [] _ HashTable.Store[table: wireName, key: publicWire, value: flatWire]; }; }; IF CoreOps.VisitBinding[actual: IF instance=NIL OR instance.type#cell THEN previous.public ELSE instance.actual, public: cell.public, eachWirePair: BindPublicToActual] THEN ERROR; proc[cell, target, flatCell, instance, parent, flatParent, data, wireName]; }; previous: Core.CellType _ cell; CoreFlat.NextUnboundCellType[cell, target, flatCell, instance, parent, flatParent, data, BindCellType]; }; Flatten: FlatCellProc = { convData: ConvData _ NARROW[data]; SELECT cell.class FROM ElectricalCoreClasses.resistorCellClass => { n0Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[0]].value]; n1Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[1]].value]; res: ElectricalCoreClasses.Resistor _ NARROW[cell.data]; Resistor[convData, n0Wire, n1Wire, res.value]; }; ElectricalCoreClasses.inductorCellClass => { n0Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[0]].value]; n1Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[1]].value]; ind: ElectricalCoreClasses.Inductor _ NARROW[cell.data]; Inductor[convData, n0Wire, n1Wire, ind.value]; }; ElectricalCoreClasses.capacitorCellClass => { n0Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[0]].value]; n1Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[1]].value]; capa: ElectricalCoreClasses.Capacitor _ NARROW[cell.data]; Capacitor[convData, n0Wire, n1Wire, capa.value]; }; ElectricalCoreClasses.diodeCellClass => { n0Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[0]].value]; n1Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[1]].value]; diode: ElectricalCoreClasses.Diode _ NARROW[cell.data]; IF diode.type#Junction THEN TerminalIO.PutRope["***Diode model should be manually edited"]; Diode[convData, n0Wire, n1Wire, diodeModel, diode.area]; }; ElectricalCoreClasses.coupledIndCellClass => { n0Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[0][0]].value]; n1Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[0][1]].value]; n2Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[1][0]].value]; n3Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[1][1]].value]; coupledInd: ElectricalCoreClasses.CoupledInd _ NARROW[cell.data]; CoupledInductors[convData, n0Wire, n1Wire, n2Wire, n3Wire, coupledInd.l1, coupledInd.l2, coupledInd.k]; }; ElectricalCoreClasses.losslessLineCellClass => { n0Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[0][0]].value]; n1Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[0][1]].value]; n2Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[1][0]].value]; n3Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[1][1]].value]; losslessLine: ElectricalCoreClasses.LosslessLine _ NARROW[cell.data]; LosslessLine[convData, n0Wire, n1Wire, n2Wire, n3Wire, losslessLine.z0, losslessLine.td]; }; ElectricalCoreClasses.linearSourceCellClass => { n0Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[0][0]].value]; n1Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[0][1]].value]; n2Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[1][0]].value]; n3Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[1][1]].value]; linearSource: ElectricalCoreClasses.LinearSource _ NARROW[cell.data]; SELECT linearSource.type FROM VCCS => Vccs[convData, n0Wire, n1Wire, n2Wire, n3Wire, linearSource.value]; VCVS => Vcvs[convData, n0Wire, n1Wire, n2Wire, n3Wire, linearSource.value]; CCCS => Cccs[convData, n0Wire, n1Wire, n2Wire, n3Wire, linearSource.value]; ccvs => Ccvs[convData, n0Wire, n1Wire, n2Wire, n3Wire, linearSource.value]; ENDCASE => ERROR; -- a change in ElectricalCoreClasses ??? }; ElectricalCoreClasses.signalGeneratorCellClass => { nWire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[0]].value]; gndWire: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec _ CoreFlat.ParseWirePath[convData.rootCell, gndName]]; sig: ElectricalCoreClasses.SignalGenerator _ NARROW[cell.data]; SELECT sig.type FROM DC => VSource[convData, nWire, gndWire, sig.onLevel]; RectWave => PulseVS[convData, nWire, gndWire, sig.offLevel, sig.onLevel, sig.tDelay, sig.tRise, sig.tFall, sig.width-sig.tRise-sig.tFall, sig.period]; OneShot => PulseVS[convData, nWire, gndWire, sig.offLevel, sig.onLevel, sig.tDelay, sig.tRise, sig.tFall, sig.width-sig.tRise-sig.tFall, infinity]; Step => PulseVS[convData, nWire, gndWire, sig.offLevel, sig.onLevel, sig.tDelay, sig.tRise, sig.tFall, infinity, infinity]; ENDCASE => ERROR; }; ElectricalCoreClasses.probeCellClass => { SELECT NARROW[cell.data, ElectricalCoreClasses.Probe].type FROM Voltage => { nWire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[0]].value]; convData.printList _ Rope.Cat[convData.printList, " V(", WireId[convData, nWire], ")"]; }; Current => { n0Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[0]].value]; n1Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[1]].value]; VSource[convData, n0Wire, n1Wire]; convData.printList _ Rope.Cat[convData.printList, "I(V", Convert.RopeFromCard[from: convData.nextId, showRadix: FALSE], ")"]; }; ENDCASE => ERROR; }; ElectricalCoreClasses.initCellClass => { init: ElectricalCoreClasses.Init _ NARROW[cell.data]; SELECT init.type FROM Voltage => { nWire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[wireName, cell.public[0]].value]; convData.initList _ Rope.Cat[convData.initList, " V(", WireId[convData, nWire], ")=", RealToRope[init.value]]; }; Current => { <> }; ENDCASE => ERROR; }; ElectricalCoreClasses.panelCellClass => { panel: ElectricalCoreClasses.Panel _ NARROW[cell.data]; convData.tranList _ Rope.Cat[RealToRope[panel.tStep, nano], RealToRope[panel.tMax, nano], RealToRope[panel.tMin, nano]]; }; CoreClasses.transistorCellClass => { gateWire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[table: wireName, key: cell.public[ORD[CoreClasses.TransistorPort.gate]]].value]; ch1Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[table: wireName, key: cell.public[ORD[CoreClasses.TransistorPort.ch1]]].value]; ch2Wire: CoreFlat.FlatWire _ NARROW[HashTable.Fetch[table: wireName, key: cell.public[ORD[CoreClasses.TransistorPort.ch2]]].value]; tran: CoreClasses.Transistor _ NARROW[cell.data]; SELECT tran.type FROM pE => { vddWire: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec _ CoreFlat.ParseWirePath[convData.rootCell, vddName]]; MOSFet[convData, gateWire, ch1Wire, ch2Wire, vddWire, pModel, tran.length, tran.width, 0.0, 0.0] }; nE => { gndWire: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec _ CoreFlat.ParseWirePath[convData.rootCell, gndName]]; MOSFet[convData, gateWire, ch1Wire, ch2Wire, gndWire, nModel, tran.length, tran.width, 0.0, 0.0]; }; ENDCASE => ERROR; }; CoreClasses.recordCellClass => { MarkAtomicPublic: PROC[wire: Core.Wire] = { [] _ HashTable.Store[table: publics, key: wire, value: $Public]; }; InsertInternal: PROC[wire: Core.Wire] = { IF NOT HashTable.Fetch[table: publics, key: wire].found THEN { InsertWire[wire, flatCell, wireName]; }; }; rct: CoreClasses.RecordCellType; publics: HashTable.Table _ HashTable.Create[cell.public.size+1]; rct _ NARROW[cell.data]; CoreOps.VisitRootAtomics[root: cell.public, eachWire: MarkAtomicPublic]; CoreOps.VisitRootAtomics[root: rct.internal, eachWire: InsertInternal]; NextCellType[cell, target, flatCell, instance, parent, flatParent, data, wireName, Flatten] }; ENDCASE => { IF cell.class.recast=NIL THEN TerminalIO.PutRopes[" What is a ", cell.class.name, "?\n"] ELSE NextCellType[cell, target, flatCell, instance, parent, flatParent, data, wireName, Flatten] }; }; InsertWire: PROC [wire: Core.Wire, flatCell: CoreFlat.FlatCellTypeRec, wireName: HashTable.Table, wireRoot: CoreFlat.WireRoot _ internal] = { flatWire: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec]; flatWire.flatCell _ flatCell; flatWire.wireRoot _ wireRoot; flatWire.wire _ wire; [] _ HashTable.Store[table: wireName, key: wire, value: flatWire]; }; NetFromCore: PUBLIC PROC[convData: ConvData] = { InsertPublic: PROC[wire: Core.Wire] = { InsertWire[wire, CoreFlat.rootCellType, wireName, public]; }; wireName: HashTable.Table _ HashTable.Create[]; TerminalIO.PutRopes["\nConverting cell ", CoreOps.GetCellTypeName[convData.rootCell], "... "]; CoreOps.VisitRootAtomics[root: convData.rootCell.public, eachWire: InsertPublic]; Flatten[cell: convData.rootCell, data: convData, wireName: wireName]; TerminalIO.PutRope[" Finished\n"]; }; END.