LogicVSimpleImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Created by: Louis Monier October 14, 1988 2:53:02 pm PDT
Last Edited by: Louis Monier October 17, 1988 11:09:33 am PDT
A simplified version of Logic that relies on Verilog for simulation, and maps to LSILogic library
DIRECTORY CoreClasses, CoreCreate, CoreOps, CoreProperties, IO, Logic, LogicUtils, Real;
LogicVSimpleImpl: CEDAR PROGRAM
IMPORTS CoreClasses, CoreCreate, CoreOps, CoreProperties, IO, LogicUtils, Real
EXPORTS Logic
= BEGIN OPEN LogicUtils, CoreCreate;
Verilog leaves
vTypeProp: ATOM = $VerilogType;
vName: ATOM = $VerilogName;
dirProp: ATOM = $VerilogDirection;
nbGatesProp: ATOM = $LSIGates;
-- the order of ports is very important
-- the outputs must be atomic wires!!!
-- name must match a verilog primitive (i.e. defined by a table, and running like Hell)
Primitive: PROC [cacheName, name: ROPE, nbGates: INT, public: WireSeq, outputs: LIST OF ROPE] RETURNS [ct: CellType] ~ {
ct ← MakePrimitive[cacheName, name, nbGates, public, outputs, $Leaf];
};
-- must correspond to a predefined module (in primitives.v)
Module: PROC [cacheName, name: ROPE, nbGates: INT, public: WireSeq, outputs: LIST OF ROPE] RETURNS [ct: CellType] ~ {
ct ← MakePrimitive[cacheName, name, nbGates, public, outputs, $Module];
};
MakePrimitive: PROC [cacheName, name: ROPE, nbGates: INT, public: WireSeq, outputs: LIST OF ROPE, vType: ATOM] RETURNS [ct: CellType] ~ {
SetDirection: PROC [wire: Wire] ~ {CoreProperties.PutWireProp[wire, dirProp, $input]};
ct ← CacheFetch[cacheName];
IF ct#NIL THEN RETURN[ct];
ct ← CoreClasses.CreateUnspecified[public: public, name: cacheName];
[] ← CoreOps.VisitRootAtomics[ct.public, SetDirection];
FOR l: LIST OF ROPE ← outputs, l.rest WHILE l#NIL DO
wire: Wire ← CoreOps.FindWire[ct.public, l.first];
IF wire=NIL THEN ERROR; -- where is this output?
CoreProperties.PutWireProp[wire, dirProp, $output];
ENDLOOP;
CoreProperties.PutCellTypeProp[ct, vTypeProp, vType];
CoreProperties.PutCellTypeProp[ct, vName, name];
CoreProperties.PutCellTypeProp[ct, nbGatesProp, NEW[INT ← nbGates]];
CacheStore[cacheName, ct];
};
Simple gates: they match a Verilog primitive
-- The vanilla inverter (optionally with double power output) with explicit layout
Inv: PUBLIC PROC [buffered: BOOLFALSE] RETURNS [ct: CellType] = {
logicName: ROPE = IF buffered THEN "InvB" ELSE "Inv";
ct ← Primitive[logicName, "not", 1, Wires["X", "I", "Vdd", "Gnd"], LIST["X"]];
};
And: PUBLIC PROC[n: NAT] RETURNS [ct: CellType] = {ct ← B4Large["and", n]};
Nand: PUBLIC PROC[n: NAT] RETURNS [ct: CellType] = {ct ← B4Large["nand", n]};
Or: PUBLIC PROC[n: NAT] RETURNS [ct: CellType] = {ct ← B4Large["or", n]};
Nor: PUBLIC PROC[n: NAT] RETURNS [ct: CellType] = {ct ← B4Large["nor", n]};
Xor2: PUBLIC PROC RETURNS [ct: CellType] = {
ct ← Primitive["xor2", "xor", 3, Wires["X", "I-A", "I-B", "Vdd", "Gnd"], LIST["X"]];};
Xnor2: PUBLIC PROC RETURNS [ct: CellType] = {
ct ← Primitive["xnor2", "xnor", 3, Wires["X", "I-A", "I-B", "Vdd", "Gnd"], LIST["X"]];};
FlatB4Large: PROC [opName: ROPE, n: NAT] RETURNS [ct: CellType] ~ {
logicName: ROPEIO.PutFR["%g%g", IO.rope[opName], IO.int[n]];
public: WireSeq ← CoreOps.CreateWires[n+3];
public[0] ← CoreOps.CreateWire[name: "X"];
public[n+1] ← CoreOps.CreateWire[name: "Vdd"];
public[n+2] ← CoreOps.CreateWire[name: "Gnd"];
FOR i: NAT IN [0..n) DO
public[i+1] ← CoreOps.CreateWire[name: IO.PutFR["I%g", IO.int[i]]];
ENDLOOP;
ct ← Primitive[logicName, opName, n/2, public, LIST["X"]];
};
B4Large: PROC [opName: ROPE, n: NAT] RETURNS [ct: CellType] ~ {
pas: LIST OF PANIL;
instances: CellInstances ← NIL;
cacheName: ROPEIO.PutFR["Str%g%g", IO.rope[opName], IO.int[n]];
ct ← CacheFetch[cacheName];
IF ct#NIL THEN RETURN[ct];
pas ← LIST[["X", "X"]];
FOR i: NAT IN [0..n) DO
pas ← CONS[ [IO.PutFR["I%g", IO.int[i]], IO.PutFR["I[%g]", IO.int[i]]], pas];
ENDLOOP;
ct ← Cell[public: Wires["X", Seq["I", n], "Vdd", "Gnd"],
name: cacheName,
instances: LIST[InstanceList[type: FlatB4Large[opName, n], pas: pas]]];
CacheStore[cacheName, ct];
};
Complex gates: a primitive is defined for each cell in primitive.v
A22o2i: PUBLIC PROC[] RETURNS [ct: CellType] = {
ct ← Primitive["A22o2i", "a22o2i", 2, Wires["X", "A", "B", "C", "D", "Vdd", "Gnd"], LIST["X"]];};
O22a2i: PUBLIC PROC[] RETURNS [ct: CellType] = {
ct ← Primitive["O22a2i", "o22a2i", 2, Wires["X", "A", "B", "C", "D", "Vdd", "Gnd"], LIST["X"]];};
A21o2i: PUBLIC PROC[] RETURNS [ct: CellType] = {
ct ← Primitive["A21o2i", "a21o2i", 2, Wires["X", "A", "B", "C", "Vdd", "Gnd"], LIST["X"]];};
O21a2i: PUBLIC PROC[] RETURNS [ct: CellType] = {
ct ← Primitive["O21a2i", "o21a2i", 2, Wires["X", "A", "B", "C", "Vdd", "Gnd"], LIST["X"]];};
Predefined modules, not primitives (complex cell, or more than one output)
-- the flop from LSILogic IS metastable-resistant
FlipFlop: PUBLIC PROC [metaStableResistant: BOOLFALSE] RETURNS [ct: CellType] = {
ct ← Module["FF", "ff", 7, Wires["Q", "NQ", "CK", "D", "Vdd", "Gnd"], LIST["Q", "NQ"]];
};
FlipFlopEnable: PUBLIC PROC RETURNS [ct: CellType] = {
ct ← Module["FFen", "ffen", 9, Wires["Q", "NQ", "CK", "D", "nEn", "en", "Vdd", "Gnd"], LIST["Q", "NQ"]];
};
DLatch: PUBLIC PROC RETURNS [ct: CellType] = {
ct ← Module["DLatch", "dLatch", 5, Wires["Q", "D", "S", "Vdd", "Gnd"], LIST["Q"]];
};
TstDriver: PUBLIC PROC RETURNS [ct: CellType] = {
ct ← Module["Tristate", "tristate", 2, Wires["X", "I", "EN", "NEN", "Vdd", "Gnd"], LIST["X"]];
};
Temporary hacks until people clean up their old designs
Rec2V: PUBLIC PROC RETURNS [ct: CellType] ~ {
instances: CellInstances ← NIL;
cacheName: ROPE ← "rec2V";
ct ← CacheFetch[cacheName];
IF ct#NIL THEN RETURN[ct];
ct ← Cell[public: Wires["X", "I", "Vth", "Vdd", "Gnd"],
name: cacheName,
instances: LIST[Instance[Inv[], ["X", "X"], ["I", "I"]]]];
CacheStore[cacheName, ct];
};
Unchanged
Buffer: PUBLIC PROC[d: NAT] RETURNS [ct: CellType] = {
fullName: ROPE = IO.PutFR["Buffer d=%g", IO.int[d]];
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
IF d=0 THEN Error["Please specify size of buffer"];
ct ← SequenceCell[name: "Buffer", baseCell: Inv[TRUE], count: MAX[(d+1)/2, 1]];
CacheStore[fullName, ct];
};
CKBuffer: PUBLIC PROC[d, numRows: NAT] RETURNS [ct: CellType] = {
ct ← Buffer[d];
};
Driver: PUBLIC PROC [d: NAT] RETURNS [ct: CellType] ~ {
fullName: ROPE = IO.PutFR["Driver d=%g", IO.int[d]];
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
SELECT d FROM
<=0 => Error["Please specify strength of driver"];
<=4 => ct ← SCBlock[Extract["driver4.sch"]];
<=8 => ct ← SCBlock[Extract["driver8.sch"]];
ENDCASE => { -- use constant amplification in 2 stages, correct up to 64
n2: NAT = (d+3)/4; -- second stage: 1 inverter may drive 4, round up
n1: NAT = Real.Round[Real.SqRt[n2]]; -- first stage, sqrt of second stage
ct ← Extract["driver.sch", LIST[["n1", n1], ["n2", n2]]];
};
CacheStore[fullName, ct];
};
InvDriver: PUBLIC PROC [d: NAT] RETURNS [ct: CellType] ~ {
fullName: ROPE = IO.PutFR["InvDriver d=%g", IO.int[d]];
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
SELECT d FROM
<=0 => Error["Please specify strength of inverting driver"];
<=4 => ct ← SCBlock[Extract["invDriver4.sch"]];
<=8 => ct ← SCBlock[Extract["invDriver8.sch"]];
ENDCASE => ct ← Extract["invDriver.sch", LIST[["drv", d]]]; -- use direct driver
CacheStore[fullName, ct];
};
SymDriver: PUBLIC PROC [d: NAT] RETURNS [ct: CellType] ~ {
fullName: ROPE = IO.PutFR["SymDriver d=%g", IO.int[d]];
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
SELECT d FROM
<=0 => Error["Please specify strength of symmetrical driver"];
<=3 => ct ← SCBlock[Extract["symDriver3.sch"]];
<=6 => ct ← SCBlock[Extract["symDriver6.sch"]];
ENDCASE => { -- use constant amplification in 3 stages, correct up to 64
n2: NAT = (d+3)/4; -- last inverting stage: 1 inverter may drive 4, round up
d1: NAT = d+n2; -- logic drive of initial non-inverting driver
ct ← Extract["symDriver.sch", LIST[["n2", n2], ["d1", d1]]];
};
CacheStore[fullName, ct];
};
TristateI: PUBLIC PROC RETURNS [ct: CellType] ~ {
fullName: ROPE = "TristateI";
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
ct ← SCBlock[Extract["3BufferI.icon"]];
CacheStore[fullName, ct];
};
TristateNI: PUBLIC PROC RETURNS [ct: CellType] ~ {
fullName: ROPE = "TristateNI";
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
ct ← SCBlock[Extract["3BufferNI.icon"]];
CacheStore[fullName, ct];
};
FlipFlopAsyncReset: PUBLIC PROC RETURNS [ct: CellType] = {
name: ROPE = "FlipFlopAsyncReset";
ct ← CacheFetch[name];
IF ct#NIL THEN RETURN[ct];
ct ← SCBlock[Extract["ffAR.sch"]];
CacheStore[name, ct];
};
Not mapped in Verilog/LSILogic
RecTTL: PUBLIC PROC RETURNS [ct: CellType] = {ERROR};
Tr2: PUBLIC PROC [type: ATOM] RETURNS [ct: CellType] = {ERROR};
PullUp: PUBLIC PROC [n: NAT] RETURNS [ct: CellType] = {ERROR};
Storage: PUBLIC PROC RETURNS [ct: CellType] = {ERROR};
RS: PUBLIC PROC RETURNS [ct: CellType] = {ERROR};
END.