DIRECTORY Convert, Core, CoreFlat, CoreOps, CoreClasses, CoreProperties, ElectricalCoreClasses, IO, Real, RefTab, Rope, SpiceOps, SymTab, TerminalIO; SpiceInputGenImpl: CEDAR PROGRAM IMPORTS Convert, CoreFlat, CoreOps, CoreClasses, CoreProperties, ElectricalCoreClasses, IO, RefTab, Real, Rope, SpiceOps, SymTab, TerminalIO EXPORTS SpiceOps = BEGIN ConvData: TYPE = SpiceOps.ConvData; ROPE: TYPE = Rope.ROPE; CellType: TYPE = Core.CellType; FlatWire: TYPE = CoreFlat.FlatWire; 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: RefTab.Ref]; 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; defaultIndex: NAT _ LAST[NAT]; gndName: PUBLIC ROPE _ "public.Gnd"; vddName: PUBLIC ROPE _ "public.Vdd"; pModel: PUBLIC ROPE _ "VENPT"; nModel: PUBLIC ROPE _ "VENHT"; diodeModel: PUBLIC ROPE _ "D"; npnModel: PUBLIC ROPE _ "NPN"; pnpModel: PUBLIC ROPE _ "PNP"; modelTable: PUBLIC SymTab.Ref _ SymTab.Create[]; temp: PUBLIC REAL _ 27.0; fetDifLength: REAL _ 5.0; --microns spiceModel: PUBLIC ATOM _ CoreProperties.RegisterProperty[$SpiceOpsModel, CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]]; spiceOptions: PUBLIC ATOM _ CoreProperties.RegisterProperty[$SpiceOpsOptions, CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]]; analysisType: PUBLIC ATOM _ CoreProperties.RegisterProperty[$SpiceOpsAnalysis, CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]]; spiceExtraLine: PUBLIC ATOM _ CoreProperties.RegisterProperty[$SpiceOpsExtraLine, CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]]; WriteSpiceDeck: PUBLIC PROC [cellType: CellType, convData: ConvData] ~ { InitSpiceDeck[cellType, convData]; NetFromCore[convData]; CloseSpiceDeck[convData]; }; CreateConvData: PUBLIC PROC [inputStream, outputStream: IO.STREAM] RETURNS [convData: ConvData] ~ { convData _ NEW[SpiceOps.ConvDataRec]; convData.inS _ inputStream; convData.outS _ outputStream; convData.modelsUsed _ SymTab.Create[]; }; InitSpiceDeck: PUBLIC PROC [cellType: CellType, convData: ConvData] ~ { convData.rootCell _ cellType; convData.wTable _ RefTab.Create[equal: CoreFlat.FlatWireEqual, hash: CoreFlat.FlatWireHash]; convData.invTable _ SymTab.Create[]; PutHeader[convData]; }; WriteInstance: PROC [convData: ConvData, rope: ROPE] ~ { IF Rope.Length[rope]<=lineLength THEN IO.PutRope[convData.outS, Rope.Concat[rope, "\l"]] ELSE { index, index2: INT _ 0; UNTIL index2>=lineLength DO index _ index2; index2 _ Rope.Index[rope, index+1, sep]; ENDLOOP; IO.PutRope[convData.outS, Rope.Concat[Rope.Substr[rope, 0, index], "\l"]]; WriteInstance[convData, Rope.Concat["+", Rope.Substr[rope, index+1]]]; }; }; WireId: PROC [convData: ConvData, wire: FlatWire] RETURNS [id: ROPE] ~ { found: BOOL; val: RefTab.Val; [found, val] _ RefTab.Fetch[convData.wTable, wire]; IF found THEN RETURN [NARROW[val, ROPE]]; id _ NextInstanceId[convData]; [] _ RefTab.Insert[convData.wTable, wire, id]; [] _ SymTab.Insert[convData.invTable, id, wire]; 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: PUBLIC PROC [convData: ConvData, comment: ROPE] ~ { WriteInstance[convData, Rope.Concat["* ", Rope.Substr[comment, 0, 78]]]; }; Resistor: PUBLIC 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: PUBLIC 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: PUBLIC 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: PUBLIC 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: PUBLIC 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: PUBLIC 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: PUBLIC 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: PUBLIC 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: PUBLIC 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 : PUBLIC 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.Cat[diode, model, " "]; diode _ Rope.Concat[diode, RealToRope[area]]; WriteInstance[convData, diode] }; BJT: PUBLIC PROC [convData: ConvData, c, b, e: FlatWire, model: ROPE, area: REAL] ~ { bjt: ROPE _ Rope.Concat[base: "Q", rest: NextInstanceId[convData]]; bjt _ Rope.Cat[bjt, WireId[convData, c], WireId[convData, b], WireId[convData, e]]; bjt _ Rope.Cat[bjt, model, " "]; bjt _ Rope.Concat[bjt, RealToRope[area]]; WriteInstance[convData, bjt] }; MOSFet: PUBLIC PROC [convData: ConvData, gate, drain, source, bulk: FlatWire, model: ROPE, l, w: REAL] ~ { mos: ROPE _ Rope.Concat[base: "M", rest: NextInstanceId[convData]]; ad, as: REAL _ fetDifLength*w; pd, ps: REAL _ 2*fetDifLength+w; nrd, nrs: REAL _ fetDifLength/w; 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]]; mos _ Rope.Cat[mos, "AD=", RealToRope[ad, pico], " AS=", RealToRope[as, pico]]; mos _ Rope.Cat[mos, "PD=", RealToRope[pd, micro], " PS=", RealToRope[ps, micro]]; mos _ Rope.Cat[mos, " NRD=", RealToRope[nrd], " NRS=", RealToRope[nrs]]; WriteInstance[convData, mos] }; VSource: PUBLIC PROC [convData: ConvData, n1, n2: FlatWire, dc: REAL _ 0.0] ~ { vs: ROPE _ Rope.Concat[WireId[convData, n1], WireId[convData, n2]]; vs _ Rope.Cat["V", NextInstanceId[convData], vs]; IF dc#0.0 THEN vs _ Rope.Cat[vs, " DC ", RealToRope[dc]]; WriteInstance[convData, vs] }; ISource: PUBLIC 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: PUBLIC 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] }; SineGen: PUBLIC PROC [convData: ConvData, n1, n2: FlatWire, v0, vA, freq, td, theta: 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, "SIN(", RealToRope[v0], RealToRope[vA]]; vs _ Rope.Cat[vs, RealToRope[freq], RealToRope[td, nano]]; vs _ Rope.Cat[vs, RealToRope[theta], ")"]; WriteInstance[convData, vs] }; ACSource: PUBLIC PROC [convData: ConvData, n1, n2: FlatWire, mag, phase: REAL _ 0.0] ~ { vs: ROPE _ "VSource "; vs _ Rope.Cat[vs, WireId[convData, n1], WireId[convData, n2]]; vs _ Rope.Cat[vs, "DC AC", RealToRope[mag], RealToRope[phase], ")"]; WriteInstance[convData, vs] }; Model: PUBLIC PROC [convData: ConvData, mName: ROPE] ~ { found: BOOL; val: SymTab.Val; [found, val] _ SymTab.Fetch[modelTable, mName]; IF NOT found THEN Signal[Rope.Concat["Unknown model: ", mName]] ELSE WriteInstance[convData, NARROW[val]] }; PutHeader: PROC [convData: ConvData] ~ { vddWire, gndWire: FlatWire; node0: ROPE _ "0 "; warningMsg: ROPE _ NIL; Comment[convData, CoreOps.GetCellTypeName[convData.rootCell]]; gndWire _ NEW[CoreFlat.FlatWireRec _ CoreFlat.ParseWirePath[convData.rootCell, gndName]]; [] _ RefTab.Insert[convData.wTable, gndWire, node0]; vddWire _ NEW[CoreFlat.FlatWireRec _ CoreFlat.ParseWirePath[convData.rootCell, vddName ! CoreFlat.PathError => {warningMsg _ "warning: no Vdd wire"; CONTINUE}]]; IF warningMsg=NIL THEN VSource[convData, vddWire, gndWire, 5.0] ELSE TerminalIO.PutRope[warningMsg]; }; CloseSpiceDeck: PUBLIC PROC [convData: ConvData] ~ { WriteModels: SymTab.EachPairAction ~ {Model[convData, key]}; extraLine: ROPE _ NARROW[CoreProperties.GetCellTypeProp[convData.rootCell, spiceExtraLine]]; IF extraLine#NIL THEN WriteInstance[convData, extraLine]; [] _ SymTab.Pairs[x: convData.modelsUsed, action: WriteModels]; IF convData.initList#NIL THEN WriteInstance[convData, Rope.Concat[".IC ", convData.initList]]; WriteInstance[convData, Rope.Cat[".OPTIONS LIMPTS ", Convert.RopeFromInt[convData.limpts], " ", convData.optList]]; WriteInstance[convData, Rope.Concat[".TEMP ", RealToRope[convData.temp]]]; WriteInstance[convData, Rope.Cat[".PRINT ", convData.analysis, " ", convData.printList]]; IF Rope.Equal[convData.analysis, "TRAN"] THEN WriteInstance[convData, Rope.Cat[".", convData.analysis, " ", convData.tranList]] ELSE WriteInstance[convData, convData.analysis]; WriteInstance[convData, ".END"]; }; NextCellType: PROC [cell: Core.CellType, target: CoreFlat.FlatCellTypeRec, flatCell: CoreFlat.FlatCellTypeRec, instance: CoreClasses.CellInstance, parent: Core.CellType, flatParent: CoreFlat.FlatCellTypeRec, data: REF ANY, wireName: RefTab.Ref, proc: FlatCellProc] = { BindCellType: CoreFlat.UnboundFlatCellProc = { BindPublicToActual: CoreOps.EachWirePairProc = { IF publicWire.size=0 THEN { flatWire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[x: wireName, key: actualWire].val]; [] _ RefTab.Store[x: wireName, key: publicWire, val: 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, defaultIndex, parent, flatParent, data, BindCellType]; }; Flatten: FlatCellProc = { convData: ConvData _ NARROW[data]; SELECT cell.class FROM ElectricalCoreClasses.resistorCellClass => { n0Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0]].val]; n1Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[1]].val]; res: ElectricalCoreClasses.Resistor _ NARROW[cell.data]; Resistor[convData, n0Wire, n1Wire, res.value]; }; ElectricalCoreClasses.inductorCellClass => { n0Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0]].val]; n1Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[1]].val]; ind: ElectricalCoreClasses.Inductor _ NARROW[cell.data]; Inductor[convData, n0Wire, n1Wire, ind.value]; }; ElectricalCoreClasses.capacitorCellClass => { n0Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0]].val]; n1Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[1]].val]; capa: ElectricalCoreClasses.Capacitor _ NARROW[cell.data]; Capacitor[convData, n0Wire, n1Wire, capa.value]; }; ElectricalCoreClasses.diodeCellClass => { n0Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0]].val]; n1Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[1]].val]; diode: ElectricalCoreClasses.Diode _ NARROW[cell.data]; model: ROPE _ GetModelName[cell, instance]; IF diode.type#Junction AND model=NIL THEN TerminalIO.PutRope["***Diode model should be manually edited"]; IF model=NIL THEN model _ diodeModel; Diode[convData, n0Wire, n1Wire, model, diode.area]; }; ElectricalCoreClasses.bjtCellClass => { cWire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0]].val]; bWire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[1]].val]; eWire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[2]].val]; bjt: ElectricalCoreClasses.BJT _ NARROW[cell.data]; model: ROPE _ GetModelName[cell, instance]; IF model=NIL THEN model _ SELECT bjt.type FROM npn => npnModel, pnp => pnpModel, ENDCASE => ERROR; BJT[convData, cWire, bWire, eWire, model, bjt.area]; }; ElectricalCoreClasses.coupledIndCellClass => { n0Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0][0]].val]; n1Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0][1]].val]; n2Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[1][0]].val]; n3Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[1][1]].val]; coupledInd: ElectricalCoreClasses.CoupledInd _ NARROW[cell.data]; CoupledInductors[convData, n0Wire, n1Wire, n2Wire, n3Wire, coupledInd.l1, coupledInd.l2, coupledInd.k]; }; ElectricalCoreClasses.losslessLineCellClass => { n0Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0][0]].val]; n1Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0][1]].val]; n2Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[1][0]].val]; n3Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[1][1]].val]; losslessLine: ElectricalCoreClasses.LosslessLine _ NARROW[cell.data]; LosslessLine[convData, n0Wire, n1Wire, n2Wire, n3Wire, losslessLine.z0, losslessLine.td]; }; ElectricalCoreClasses.linearSourceCellClass => { n0Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0][0]].val]; n1Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0][1]].val]; n2Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[1][0]].val]; n3Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[1][1]].val]; 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[RefTab.Fetch[wireName, cell.public[0]].val]; 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.sineGeneratorCellClass => { nWire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0]].val]; gndWire: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec _ CoreFlat.ParseWirePath[convData.rootCell, gndName]]; sig: ElectricalCoreClasses.SineGenerator _ NARROW[cell.data]; SineGen[convData, nWire, gndWire, sig.v0, sig.vA, sig.freq, sig.td, sig.theta]; }; ElectricalCoreClasses.acSourceCellClass => { nWire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0]].val]; gndWire: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec _ CoreFlat.ParseWirePath[convData.rootCell, gndName]]; ac: ElectricalCoreClasses.ACSource _ NARROW[cell.data]; ACSource[convData, nWire, gndWire, ac.mag, ac.phase]; }; ElectricalCoreClasses.probeCellClass => { probe: ElectricalCoreClasses.Probe _ NARROW[cell.data]; SELECT probe.type FROM Voltage => { name: Rope.ROPE _ Rope.Cat[" V", probe.acKind, "("]; nWire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0]].val]; convData.printList _ Rope.Cat[convData.printList, name, WireId[convData, nWire], ")"]; }; Current => { name: Rope.ROPE _ Rope.Cat[" I", probe.acKind, "(V"]; n0Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0]].val]; n1Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[1]].val]; VSource[convData, n0Wire, n1Wire]; convData.printList _ Rope.Cat[convData.printList, name, 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[RefTab.Fetch[wireName, cell.public[0]].val]; convData.initList _ Rope.Cat[convData.initList, " V(", WireId[convData, nWire], ")=", RealToRope[init.value]]; }; Current => { }; ENDCASE => ERROR; }; ElectricalCoreClasses.panelCellClass => { propVal: REF; panel: ElectricalCoreClasses.Panel _ NARROW[cell.data]; convData.limpts _ Real.Fix[(panel.tMax - panel.tMin)/panel.tStep]+1; convData.tranList _ Rope.Cat[RealToRope[panel.tStep, nano], RealToRope[panel.tMax, nano], RealToRope[panel.tMin, nano]]; convData.optList _ Rope.Concat[convData.optList, NARROW[CoreProperties.GetCellInstanceProp[instance, spiceOptions]]]; propVal _ CoreProperties.GetCellInstanceProp[instance, SpiceOps.analysisType]; IF propVal=NIL THEN propVal _ CoreProperties.GetCellTypeProp[cell, SpiceOps.analysisType]; convData.analysis _ IF propVal=NIL THEN "TRAN" ELSE NARROW[propVal]; }; CoreClasses.transistorCellClass => { fourthWire: CoreFlat.FlatWire; gateWire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[x: wireName, key: cell.public[ORD[CoreClasses.TransistorPort.gate]]].val]; ch1Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[x: wireName, key: cell.public[ORD[CoreClasses.TransistorPort.ch1]]].val]; ch2Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[x: wireName, key: cell.public[ORD[CoreClasses.TransistorPort.ch2]]].val]; tran: CoreClasses.Transistor _ NARROW[cell.data]; model: ROPE _ GetModelName[cell, instance]; transistorLength: INT _ NARROW[CoreProperties.GetCellTypeProp[cell, CoreClasses.lengthProp], REF INT]^; transistorWidth: INT _ NARROW[CoreProperties.GetCellTypeProp[cell, CoreClasses.widthProp], REF INT]^; SELECT tran.type FROM pE => { fourthWire _ NEW[CoreFlat.FlatWireRec _ CoreFlat.ParseWirePath[convData.rootCell, vddName]]; IF model=NIL THEN model _ pModel; }; nE => { fourthWire _ NEW[CoreFlat.FlatWireRec _ CoreFlat.ParseWirePath[convData.rootCell, gndName]]; IF model=NIL THEN model _ nModel; }; ENDCASE => ERROR; [] _ SymTab.Insert[convData.modelsUsed, model, $TRUE]; MOSFet[convData, gateWire, ch1Wire, ch2Wire, fourthWire, model, transistorLength, transistorWidth]; }; CoreClasses.recordCellClass => { MarkAtomicPublic: PROC[wire: Core.Wire] = { [] _ RefTab.Store[x: publics, key: wire, val: $Public]; }; InsertInternal: PROC[wire: Core.Wire] = { IF NOT RefTab.Fetch[x: publics, key: wire].found THEN { InsertWire[wire, flatCell, wireName]; }; }; rct: CoreClasses.RecordCellType; publics: RefTab.Ref _ RefTab.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: RefTab.Ref, wireRoot: CoreFlat.WireRoot _ internal] = { flatWire: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec]; flatWire.flatCell _ flatCell; flatWire.wireRoot _ wireRoot; flatWire.wire _ wire; [] _ RefTab.Store[x: wireName, key: wire, val: flatWire]; }; NetFromCore: PUBLIC PROC[convData: ConvData] = { InsertPublic: PROC[wire: Core.Wire] = { InsertWire[wire, CoreFlat.rootCellType, wireName, public]; }; wireName: RefTab.Ref _ RefTab.Create[]; CoreOps.VisitRootAtomics[root: convData.rootCell.public, eachWire: InsertPublic]; Flatten[cell: convData.rootCell, data: convData, wireName: wireName]; }; GetModelName: PROC [cellType: Core.CellType, instance: CoreClasses.CellInstance] RETURNS [mName: ROPE] ~ { mName _ NARROW[CoreProperties.GetCellInstanceProp[instance, spiceModel]]; IF mName=NIL THEN mName _ NARROW[CoreProperties.GetCellTypeProp[cellType, spiceModel]]; }; ReadModels: PUBLIC PROC [file: IO.STREAM] ~ { modelRope: ROPE = ".MODEL"; line, thisModel, thisName: ROPE _ NIL; UNTIL IO.EndOf[file] DO line _ IO.GetLineRope[file ! IO.EndOfStream => CONTINUE]; IF line#NIL THEN SELECT Rope.Fetch[line, 0] FROM '. => { localStream: IO.STREAM _ IO.RIS[line]; IF NOT Rope.Equal[IO.GetTokenRope[localStream, IO.IDProc].token, modelRope] THEN Signal[Rope.Cat["Unknown Syntax: ", line]] ELSE { thisName _ IO.GetTokenRope[localStream, IO.IDProc].token; thisModel _ line; IF NOT SymTab.Store[modelTable, thisName, thisModel] THEN TerminalIO.PutRopes["SpiceOps: model ", thisName, " overwritten\n"]; } }; '+ => { thisModel _ Rope.Cat[thisModel, " ", Rope.Substr[line, 1]]; [] _ SymTab.Store[modelTable, thisName, thisModel]; }; '* => NULL; ' => NULL; ENDCASE => Signal[Rope.Cat["Unknown Syntax: ", line]]; ENDLOOP; }; Signal: SIGNAL[msg: Rope.ROPE _ NIL] = CODE; END. $SpiceInputGenImpl.mesa Copyright Σ 1987 by Xerox Corporation. All rights reserved. Christian Le Cocq September 27, 1988 5:09:10 pm PDT Last Edited by: Richley June 26, 1987 6:23:17 pm PDT constants Public Procs Print Procs Elements to Spice input line procs hack to keep the InstanceId of the VSource in convData.nextId, wether the wires n1 and n2 were already declared or not. Used in current probes. establish the power through the Circuit, and set Gnd to node # 0 IF Rope.Fetch[convData.analysis, 0]='. THEN { name: Rope.ROPE _ Rope.Substr[base: ROPE, start: INT _ 0, len: INT _ 2147483647] Input From Core PROC [actualWire, publicWire: Wire] it happens that we know the name of the fake voltage source from the last convData.nextId used due to the VSource implementation (berk !). NYI ΚΌ˜codešœ™K™˜>Kšœœ1˜?Kšœ˜K˜K˜—š œ œEœ ˜hK–([base: ROPE _ NIL, rest: ROPE _ NIL]šœœ:˜BKšœ>˜>Kšœ<˜˜>Kšœ:˜:Kšœ:˜:Kšœ*˜*Kšœ˜K˜K˜—š‘œœœ4œ ˜XK–([base: ROPE _ NIL, rest: ROPE _ NIL]šœœ˜Kšœ>˜>KšœD˜DKšœ˜K˜K˜—š œœœœ˜8Kšœœ˜ K˜Kšœ/˜/Kšœœœ.˜?Kšœœ˜)K˜K˜—š  œœ˜)Kšœ˜Kšœœ˜Kšœ œœ˜Kšœ>˜>K™@Kšœ œL˜YKšœ4˜4Kšœ œˆœ˜‘Kšœ œœ)˜?Kšœ ˜$Kšœ˜K˜—š œ œ˜5Kš  œ1˜˜uKšœN˜NKšœ œœG˜ZKš œœ œœœœ ˜DK˜—šœ$˜$Kšœ˜Kšœœ,œ)˜|Kšœœ,œ(˜zKšœœ,œ(˜zKšœœ ˜1Kšœœ ˜+Kš œœœ?œœ˜gKš œœœ>œœ˜ešœ ˜šœ˜Kšœ œL˜\Kšœœœ˜!Kšœ˜—šœ˜Kšœ œL˜\Kšœœœ˜!Kšœ˜—Kšœœ˜—Kšœ6˜6Kšœc˜cK˜—šœ!˜!K˜š œœ˜+Kšœ7˜7Kšœ˜K˜—š œœ˜)šœœ+œ˜7Kšœ%˜%K˜—Kšœ˜K˜—Kšœ ˜ Kšœ8˜8Kšœœ ˜KšœH˜HKšœG˜GKšœ[˜[K˜—šœ˜ Kšœœœ;˜XKšœ\˜`Kšœ˜——Kšœ˜K˜—š  œœx˜ˆKšœœ˜8Kšœ˜Kšœ˜Kšœ˜Kšœ9˜9Kšœ˜K˜—š  œœœ˜0K˜š  œœ˜'Kšœ:˜:Kšœ˜K˜—Kšœ'˜'KšœQ˜QKšœE˜EK˜K˜—š  œœ?œ œ˜jKšœœ;˜IKšœœœ œ7˜WK˜K˜—š   œœœœœ˜-Kšœ œ ˜Kšœœ˜&šœœ ˜Kšœœœœ˜9š œœœœ˜0˜K–)[rope: ROPE, oldStream: STREAM _ NIL]š œ œœœœ˜&Kš œœ œœœ+˜{šœ˜Kšœ œœ˜9Kšœ˜Kšœœ/œE˜~K˜—K˜—šœ˜Kšœ;˜;Kšœ3˜3K˜—Kšœœ˜ Kšœœ˜ Kšœ/˜6—Kšœ˜—K˜K˜—Kš  œœ œœœ˜,˜K˜—Kšœ˜—K˜—…—c~π