-- JaMMOSSIMFnsImplA.mesa
-- created by Haeberli from JamMOSSIM.mesa:  7-Jan-82 13:17:11

DIRECTORY
  IODefs,
  JaMFnsDefs,
  JaMMasterDefs USING [Object],
  JaMMOSSIMFns,
  Mopcodes,
  MOSSIMFns,
  StreamDefs,
  StringDefs,
  SystemDefs,
  WF;

JaMMOSSIMFnsImplA: PROGRAM
  IMPORTS IODefs, JaMFnsDefs, MOSSIMFns, SystemDefs, WF
  EXPORTS JaMMOSSIMFns =
  {
  OPEN JaMFnsDefs, MOSSIMFns, StreamDefs;


  -- a buffer for receiving arguments
  line: STRING ← SystemDefs.AllocateHeapString[256];


  Init: PUBLIC PROC = {
    steps: CARDINAL;
    targc ← 1;
    steps ← initializationResult[];
    PushInteger[LOOPHOLE[steps, INTEGER]]};

  SimRead: PUBLIC PROC = {
    targv[1].length ← 0; PopString[targv[1]]; targc ← 2; readFileString[]};

  SetInputHigh: PUBLIC PROC = {
    targv[1].length ← 0; PopString[targv[1]]; targc ← 2; setInputH[]};

  SetInputLow: PUBLIC PROC = {
    targv[1].length ← 0; PopString[targv[1]]; targc ← 2; setInputL[]};

  SetInputX: PUBLIC PROC = {
    targv[1].length ← 0; PopString[targv[1]]; targc ← 2; setInputX[]};

  Question: PUBLIC PROC = {
    targv[1].length ← 0; PopString[targv[1]]; targc ← 2; question[]};

  Exclamation: PUBLIC PROC = {
    targv[1].length ← 0; PopString[targv[1]]; targc ← 2; exclamation[]};

  GetNodeValue: PUBLIC PROC = {
    targc ← 2;
    targv[1].length ← 0;
    PopString[targv[1]];
    PushInteger[getNodeValue[]]};

  PrintNodeValue: PUBLIC PROC = {
    targc ← 2;
    targv[1].length ← 0;
    PopString[targv[1]];
    IODefs.WriteChar[LOOPHOLE[getNodeValue[] + '0, CHARACTER]]};


  Step: PUBLIC PROC = {value: INTEGER; targc ← 1; value ← step[]; PushInteger[value]};

  -- BitString receives a string of tokens that are separated by spaces. 
  --The first token is the name of the vector and the rest are the 
  --rest are the names of the transistors that constitute the vector.
  BitString: PUBLIC PROC = {
    line.length ← 0; PopString[line]; BreakIntoTokens[line]; setBitsString[]};

  -- GetVectorValue returns a string of values ('0,'1,'X) of the vector 
  --defined by BitString
  GetVectorValue: PUBLIC PROC = {
    targc ← 2;
    targv[1].length ← 0;
    PopString[targv[1]];
    PushString[vectorValue[]]};

  GetVectorWord: PUBLIC PROC = {
    i, inc: CARDINAL;
    result: STRING;
    word: INTEGER;
    targc ← 2;
    targv[1].length ← 0;
    PopString[targv[1]];
    result ← vectorValue[];
    IF result.length > 16 THEN WF.WF1["Vector too long: %s*n", result];
    word ← 0;
    FOR i IN [0..result.length) DO
      IF result[i] = '0 THEN inc ← 0
      ELSE
        IF result[i] = '1 THEN inc ← 1
        ELSE {WF.WF1["Vector undefined: %s*n", result]; EXIT};
      word ← word*2 + inc
      ENDLOOP;
    PushInteger[word]};

  PutVectorValue: PUBLIC PROC = {
    arg1: LONG INTEGER;
    ob: JaMMasterDefs.Object;
    targc ← 2;
    targv[1].length ← 0;
    PopString[targv[1]];
    ob ← PopObject[];
    WITH dob: ob SELECT FROM
      IntegerType => arg1 ← LONG[dob.IntegerVal];
      ENDCASE => BEGIN PushObject[ob]; arg1 ← JaMFnsDefs.PopLongInteger[]; END;
    putVectorValue[arg1]};

  -- PrintVectorValue is similar to GetVectorValue, except the output is printed.
  PrintVectorValue: PUBLIC PROC = {
    targc ← 2;
    targv[1].length ← 0;
    PopString[targv[1]];
    IODefs.WriteString[vectorValue[]]};

  -- ResetChangeCount sets all the changecount fields of nodes to 0
  ResetChangeCount: PUBLIC PROC = {resetChangeCount[]};

  -- DisplayChangedNodes displays in the file "mossim.log" the 
  --number of times nodes have changed their potentials
  DisplayChangedNodes: PUBLIC PROC = {displayChangedNodes[]};

  -- TraceNode will set the trace flag of a node
  TraceNodes: PUBLIC PROC = {
    line.length ← 0; PopString[line]; BreakIntoTokens[line]; traceNodes[]};

  UnTraceNodes: PUBLIC PROC = {
    line.length ← 0; PopString[line]; BreakIntoTokens[line]; unTraceNodes[]};

  Warning: PUBLIC PROC = {ToggleWarning[]};

  Enter: PUBLIC PROC = {MOSSIMEnter[]};

  -- Private procedure
  BreakIntoTokens: PROC [line: STRING] = {
    pos: CARDINAL ← 0;

    Get: PROC [s: STRING] RETURNS [STRING] = {
      char: CHARACTER;
      end, length: CARDINAL;
      s.length ← length ← 0;
      IF (end ← pos) >= line.length THEN RETURN[NIL];
      DO
        SELECT (char ← line[end]) FROM
          ' , IODefs.TAB, ', => EXIT;
          IODefs.CR => IF end = 0 THEN RETURN[NIL] ELSE EXIT;
          ENDCASE => {
            s[length] ← char;
            end ← end + 1;
            length ← length + 1;
            IF end >= line.length THEN EXIT}
        ENDLOOP;
      s.length ← length;
      pos ← end + 1;
      RETURN[s]};

    targc ← 1;
    UNTIL Get[targv[targc]] = NIL DO targc ← targc + 1 ENDLOOP;
    };

  }.