CoreNameImpl: 
CEDAR 
PROGRAM
IMPORTS Convert, CoreClasses, CoreOps, HashTable, IO, Rope
EXPORTS CoreName
~ BEGIN
ROPE:  TYPE = Core.ROPE;
Wire:  TYPE = Core.Wire;
CellType: TYPE = Core.CellType;
Context: TYPE = CoreName.Context;
Ph:  TYPE = CoreName.Ph;
Polarity: TYPE = CoreName.Polarity;
SigRec: TYPE = CoreName.SigRec;
table: HashTable.Table ←
HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
NILRope:    ROPE = "NIL";
nilRope:     ROPE = "nil";
NILRopeRegistered: BOOL ← HashTable.Store[table, NILRope, nilRope];
nilRopeRegistered: BOOL ← HashTable.Store[table, nilRope,  nilRope];
Signal: SIGNAL = CODE;
RopeNm: 
PUBLIC 
PROC[rope: 
ROPE] 
RETURNS[registered: 
ROPE] = {
IF rope=NIL THEN RETURN[NIL];
registered ← NARROW[HashTable.Fetch[table, rope].value];
SELECT registered 
FROM
nilRope => RETURN[NIL];
NIL  => {[] ← HashTable.Store[table, rope, rope]; RETURN[rope]};
ENDCASE => RETURN[registered]};
 
 
WireNm: 
PUBLIC 
PROC[wire: Core.Wire, rope: 
ROPE←
NIL]
RETURNS[w: Core.Wire, n: ROPE] = {
IF wire=NIL THEN RETURN[NIL, NIL];
IF rope=NIL THEN rope ← CoreOps.GetShortWireName[wire];
n ← RopeNm[rope];
w ← CoreOps.SetShortWireName[wire, n]};
 
CellNm: 
PUBLIC 
PROC[cell: Core.CellType, rope: 
ROPE←
NIL]
RETURNS[c: Core.CellType, n: ROPE] = {
IF rope=NIL THEN rope ← CoreOps.GetCellTypeName[cell];
n ← RopeNm[rope];
c ← CoreOps.SetCellTypeName[cell, n]};
 
NextIDIndex: INT ← 0;
ID: 
PUBLIC 
PROC[rope: 
ROPE] 
RETURNS[unique: 
ROPE] = {
unique ← RopeNm[IO.PutFR["%g%g", IO.rope[rope], IO.int[NextIDIndex]]];
NextIDIndex ← NextIDIndex+1};
 
NewContext: 
PUBLIC 
PROC 
RETURNS[ctx: Context] =
{RETURN[HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]]};
 
CtxCopyWire: 
PUBLIC 
PROC[ctx: Context, wire: Core.Wire] 
-- only name prop is copied
RETURNS[new: Core.Wire] = {
Copy: 
PROC [wire: Core.Wire] 
RETURNS [new: Core.Wire] = {
IF (new ← 
NARROW[HashTable.Fetch[table: visitTab, key: wire].value])=
NIL 
THEN {
name: ROPE ← WireNm[wire].n;
new ← CtxNameToWire[ctx, name];
IF new#
NIL 
THEN
{[]←HashTable.Insert[table: visitTab, key: wire, value: new]; RETURN[new]};
 
new ← CoreOps.CreateWires[size: wire.size];
IF name#NIL THEN IF NOT CtxRegisterWire[ctx, new, name].ok THEN ERROR;
IF NOT HashTable.Insert[table: visitTab, key: wire, value: new] THEN ERROR;
[]←WireNm[new, name];
FOR i: NAT IN [0 .. wire.size) DO new[i] ← Copy[wire[i]] ENDLOOP } };
 
 
visitTab: HashTable.Table ← HashTable.Create[];  -- Wire to Wire
IF ctx=NIL THEN RETURN[NIL];
new ← IF wire=NIL THEN NIL ELSE Copy[wire] };
 
CtxWire: 
PUBLIC 
PROC[ctx: Context, name: 
ROPE, size: 
INT ← -1]
RETURNS[wire: Core.Wire] = {
IF ctx=NIL THEN RETURN[NIL];
IF name=NIL OR name.Length[]=0 THEN RETURN[NIL];
wire ← CtxNameToWire[ctx, name];
IF wire=
NIL
THEN {wire ← NEW[Core.WireRec[MAX[size, 0]]]; [ ] ← CtxRegisterWire[ctx, wire, name]}
ELSE {IF size#-1 AND wire.size#size THEN wire ← NIL}};
 
 
CtxRegisterWire: 
PUBLIC 
PROC[ctx: Context, wire: Core.Wire, name: 
ROPE ← 
NIL]
RETURNS[ok: BOOL] ={
oldWire: Core.Wire;
IF ctx=NIL THEN RETURN[FALSE];
IF name=NIL OR name.Length[]=0 THEN name ← CoreOps.GetShortWireName[wire];
IF name=NIL OR name.Length[]=0 THEN RETURN[FALSE];
oldWire ← NARROW[HashTable.Fetch[ctx, name].value];
IF oldWire#NIL AND oldWire#wire THEN RETURN[FALSE];
wire ← CoreOps.SetShortWireName[wire, RopeNm[name]];
IF oldWire=wire THEN RETURN[TRUE];
[ ] ← HashTable.Store[ctx, name, wire]};
 
CtxNameToWire: 
PUBLIC 
PROC[ctx: Context, name: 
ROPE] 
RETURNS[wire: Core.Wire] = {
IF ctx=NIL THEN RETURN[NIL];
IF name=NIL OR name.Length[]=0 THEN RETURN[NIL];
wire ← NARROW[HashTable.Fetch[ctx, name].value]};
 
CtxWireToName: 
PUBLIC 
PROC[ctx: Context, wire: Core.Wire] 
RETURNS[name: 
ROPE] = {
oldWire: Core.Wire;
IF ctx=NIL THEN RETURN[NIL];
IF wire=NIL THEN RETURN[NIL];
name  ← CoreOps.GetShortWireName[wire];
oldWire ← NARROW[HashTable.Fetch[ctx, name].value];
RETURN[ IF wire=NIL OR oldWire=NIL OR wire#oldWire THEN NIL ELSE name]};
 
WiresFromCtx: 
PUBLIC 
PROC[ctx: Context] 
RETURNS[wires: Core.Wires] = {
TwoWires: TYPE = RECORD[w0, w1: Wire];
action: HashTable.EachPairAction = {wires ← CONS[NARROW[value], wires]};
ordered: BOOL;
[ ] ← HashTable.Pairs[ctx, action];
ordered ← wires=NIL OR wires.rest=NIL;
WHILE 
NOT ordered 
DO
ordered ← TRUE;
FOR ws: Core.Wires ← wires, ws.rest 
WHILE ws.rest # 
NIL 
DO
IF Rope.Compare[WireNm[ws.first].n, WireNm[ws.rest.first].n] = greater 
THEN
{[ws.first, ws.rest.first] ← TwoWires[ws.rest.first, ws.first]; ordered ← FALSE};
 
ENDLOOP;
 
ENDLOOP};
 
 
WireFromCtx: 
PUBLIC 
PROC[ctx: Context] 
RETURNS[wire: Core.Wire] =
{wire ← CoreOps.CreateWire[ WiresFromCtx[ctx] ]};
 
killing: BOOL ← TRUE; 
KillContext: 
PUBLIC PROC[ctx: Context] 
RETURNS[Context] = 
{
IF killing
THEN {HashTable.Erase[ctx]; RETURN[NIL]}
ELSE {RETURN[ctx]}};
 
BindModules: 
PUBLIC PROC[public: Wire, modules: 
LIST 
OF CellType, name: 
ROPE ← 
NIL]
RETURNS [cell: CellType] = {
RegPubs: CoreOps.EachWireProc = {[]𡤌txRegisterWire[ctx, wire]};
ctx:   Context ← NewContext[];
rec:    CoreClasses.RecordCellType;
cnt:   NAT ← 0;
[] ← CoreOps.VisitWire[public, RegPubs];
FOR m: LIST OF CellType ← modules, m.rest WHILE m#NIL DO cnt ← cnt + 1 ENDLOOP;
rec ← NEW [CoreClasses.RecordCellTypeRec[cnt]];
cnt ← 0;
FOR m: 
LIST 
OF CellType ← modules, m.rest 
WHILE m#
NIL 
DO
rec[cnt] ← 
NEW[ CoreClasses.CellInstanceRec ←
[actual: CtxCopyWire[ctx, m.first.public], type: m.first]];
cnt ← cnt+1 ENDLOOP;
 
rec.internal ← WireFromCtx[ctx];
cell   ← 
NEW [Core.CellTypeRec ← [
class:  CoreClasses.recordCellClass,
public: public,
data:  rec ]];
[ ] ← CellNm[cell, name];
ctx ← KillContext[ctx]};
 
PrintWire: 
PUBLIC PROC[wire: Core.Wire] = {
};
 
PhRope: 
PUBLIC 
ARRAY Ph 
OF 
ROPE ←
["A", "AB", "ABB", "ABBB", "Ac", "B", "BA", "BAA", "BAAA", "Bc", ""];
PolarityRope: PUBLIC ARRAY Polarity OF ROPE ← ["", "n", "?n"];
SigName: 
PUBLIC 
PROC [sigRec: SigRec] 
RETURNS [name: 
ROPE ← NIL ] ~ {
name ← sigRec.root;
IF name = NIL THEN RETURN[NIL];
IF sigRec.not   THEN name ← Rope.Cat["Not", name];
IF sigRec.cy#-1  THEN name ← name.Cat[ Convert.RopeFromInt[sigRec.cy]];
IF sigRec.ph#unk THEN name ← name.Cat[ PhRope[sigRec.ph]];
IF sigRec.idx#-1 THEN name ← name.Cat[ ".", Convert.RopeFromInt[sigRec.idx]];
name ← RopeNm[name]};
 
NameSig: 
PUBLIC 
PROC [name: 
ROPE] 
RETURNS [sigRec: SigRec ← [ ] ] ~ {
phasesize: ARRAY Ph OF INT ← [1,2,3,4,2,1,2,3,4,2,0];
char: CHARACTER;
end: INT;
not4: BOOL ← Rope.Equal[name.Substr[0, 4], "Not.", FALSE];
not3: BOOL ← Rope.Equal[name.Substr[0, 3], "Not", FALSE];
IF name=NIL THEN RETURN[[]];
name ← name.Substr[start: (IF not4 THEN 4 ELSE IF not3 THEN 3 ELSE 0)];
sigRec.not ← not3 OR not4;
end ← name.Index[0, "."];
sigRec.root ← name.Substr[0, end];
sigRec.idx ← 
IF (end+1)< name.Length
THEN Convert.IntFromRope[name.Substr[end+1]] ELSE -1;
sigRec.ph ← 
SELECT name.Fetch[sigRec.root.Length[]-1] 
FROM
'A => 
SELECT sigRec.root.Fetch[sigRec.root.Length[]-2] 
FROM
'B   => BA,
'A   => 
SELECT sigRec.root.Fetch[sigRec.root.Length[]-3] 
FROM
'B   => BAA,
'A   => 
SELECT sigRec.root.Fetch[sigRec.root.Length[]-4] 
FROM
'B   => BAAA,
ENDCASE => unk,
ENDCASE => unk,
ENDCASE => A,
'B => 
SELECT sigRec.root.Fetch[sigRec.root.Length[]-2]
 FROM
'A   => AB,
'B   => 
SELECT sigRec.root.Fetch[sigRec.root.Length[]-3] 
FROM
'A   => ABB,
'B   => 
SELECT sigRec.root.Fetch[sigRec.root.Length[]-4] 
FROM
'A   => ABBB,
ENDCASE => unk,
ENDCASE => unk,
ENDCASE => B,
'c => 
SELECT sigRec.root.Fetch[sigRec.root.Length[]-2] 
FROM
'A   => Ac,
'B   => Bc,
ENDCASE => unk,
ENDCASE => unk;
sigRec.root ← sigRec.root.Substr[0, sigRec.root.Length[]-phasesize[sigRec.ph]];
char ← sigRec.root.Fetch[sigRec.root.Length[]-1];
IF char 
IN ['0..'9] 
THEN {
sigRec.cy  ← char.ORD - '0.ORD;
sigRec.root ← sigRec.root.Substr[0, sigRec.root.Substr.Length[]-1]};
 
sigRec.root ← RopeNm[sigRec.root] };
 
SelectName: 
PUBLIC 
PROC[inv: 
BOOL, posNm, negNm: 
ROPE]
RETURNS [inverted: BOOL, name: ROPE] = {
sig, sigI: SigRec;
IF posNm=NIL THEN {inv ← ~inv; posNm ← negNm; negNm ← NIL};
sig ← NameSig[posNm];
sigI ← NameSig[negNm];
IF inv#sig.not AND negNm#NIL AND inv#sigI.not THEN {sig ← sigI; inv ← ~inv};
inverted ← inv#sig.not; sig.not ← FALSE;  name ← SigName[sig]};
 
NormalFormatNames: 
PUBLIC PROC [format: REFBit.FormatRec]
RETURNS[name, nameInv: 
ROPE, dual, inverted: 
BOOL, cy, idx: 
INT] = {
name  ← BitRopeToSigRope[format.name];
nameInv ← BitRopeToSigRope[format.nameInv];
IF name#
NIL 
AND nameInv#
NIL
THEN {
sig: SigRec ← NameSig[name];
sigI: SigRec ← NameSig[nameInv];
IF sig.not#sigI.not THEN Signal[];
IF sig.cy#sigI.cy THEN Signal[];
IF sig.idx#sigI.idx THEN Signal[];
IF sig.not
THEN {name  ← sigI.root; nameInv ← sig.root}
ELSE {name  ← sig.root; nameInv ← sigI.root};
 
cy   ← sig.cy;
idx  ← sig.idx;
inverted ← FALSE;
dual  ← TRUE }
 
ELSE {
sig: SigRec;
IF name#
NIL
THEN {sig ← NameSig[name];  inverted ←  sig.not}
ELSE {sig ← NameSig[nameInv]; inverted ← NOT sig.not};
 
name  ← sig.root;
nameInv ← NIL;
dual  ← FALSE ;
cy   ← sig.cy;
idx  ← sig.idx }};
 
 
 
 
BitRopeToSigRope: 
PUBLIC 
PROC [name: 
ROPE] 
RETURNS [
ROPE] ~ {
Cap: 
PROC[rope: 
ROPE, idx: 
INT] 
RETURNS[
ROPE] = {
char: CHAR ← rope.Fetch[idx+1];
IF char IN ['a..'z] THEN char ← char + LOOPHOLE['A - 'a];
RETURN[IO.PutFR["%g", IO.char[char]]]};
 
IF name = NIL THEN RETURN[NIL];
name ← Rope.Cat[Cap[name, -1], name.Substr[1]];
DO 
-- remove peiods and Capitalize next letters until end or next char is number
index: INT ← name.Index[0, "."];
IF index+1 >= name.Length[] OR name.Fetch[index+1] IN ['0..'9] THEN RETURN[name];
name ← Rope.Cat[name.Substr[0,index], Cap[name, index], name.Substr[index+2]];
ENDLOOP };
 
 
RootExt: 
PUBLIC 
PROC [name: 
ROPE] 
RETURNS [root, ext: 
ROPE] ~ {
end: INT;
end ← name.Index[0, "."];
root ← name.Substr[0, end];
ext ← IF end+1< name.Length THEN name.Substr[end] ELSE NIL};
 
END.