[Export program between lines of "#########" into a text file and compile with QuickBASIC 4.5]
###################################################################
DECLARE SUB RefreshInputText (s$)
DECLARE SUB GetALine (a$)
DECLARE SUB StoreALine (a$)
'--------------------------------------------------------------------------
' NET2PRM.BAS .. a netlist compiler for use with SYNETSIM compartmental
' modeling software.
'
' Version 1.8 October 4, 1990
' Most recent update:
' Version 1.8 has been modified to allow lines longer than
' 80 characters in the netlist. Whereas this was previously
' allowed only within the .DEFINE, .BATCH, etc. structures, it
' can now be used within the entire netlist. The '+' symbol
' is used to identify any line as a continuation of the line
' previous. v1.8X has MAXBR%=50
'
' Version 1.7 has been corrected using 2GC as opposed to GC/2
'
' Compatibility with SYNETSIM.33B, using GAMMA or GBAR (conductance
' density or actual conductance) capability.
'
' Greg Wolodkin
' Bekesy Laboratory of Neurobiology
' University of Hawaii at Manoa
' Honolulu, Hawaii 96822
'
' email greg@uhunix.uhcc.Hawaii.Edu
'--------------------------------------------------------------------------
DECLARE SUB AddQuotes (G$)
DECLARE SUB CheckConnect (CON$, SW$, DP%)
DECLARE SUB CheckForTyp (code%, DP%)
DECLARE SUB CodeCount (code$, n%)
DECLARE SUB CodePointer (f$, DP%)
DECLARE SUB CountSlash (f$, n%, s%)
DECLARE SUB DEFPointer (D$, DP%)
DECLARE SUB ErrorCheck (EMSG%, FLAG%, m$)
DECLARE SUB FixText (T$)
DECLARE SUB FormatNumbers (f$)
DECLARE SUB FormFullName (CON$, SW$, cname$)
DECLARE SUB GetBatchInfo (BFID$, B%)
DECLARE SUB GetBatchSize (B%, MAXP%)
DECLARE SUB GetCaps (T$)
DECLARE SUB GetData (a$, B$, n%, D$)
DECLARE SUB GetFileNames (NETFILE$, PRMFILE$, MSTFILE$, BATFILE$, SW$)
DECLARE SUB GetFormatSize (PFID$, SHC%, HC%, HP%, MTYP%, PHD%)
DECLARE SUB GetMasterInfo (MIDD$, MPS%)
DECLARE SUB GetMasterSize (MPS%)
DECLARE SUB GetNextParm (f$, s$)
DECLARE SUB GetParentheses (f$, s$)
DECLARE SUB GetParmNames (HC%, HP%, MTYP%, PHID%)
DECLARE SUB GetTyp (MOD$, code%, TYP%)
DECLARE SUB MakeConnect (CON$, cname$, count%, DP%, CCD%, KC%)
DECLARE SUB MakeFileName (f$, L$, R$)
DECLARE SUB PRMPointer (f$, code%, DP%)
DECLARE SUB ProcessBatch (BATFILE$)
DECLARE SUB PushSwitch (f$, s$)
DECLARE SUB ReadBatch (s$)
DECLARE SUB ReadBlock (s$)
DECLARE SUB ReadDefinition (srch$)
DECLARE SUB ReadMaster (s$)
DECLARE SUB Sort (a$(), B$(), n%)
DECLARE SUB StripQuotes (G$)
DECLARE SUB StuffDefinition (DEFT$, code%)
DECLARE SUB StuffMods (MOD$, code%, ECHK%)
DECLARE SUB TotalConnect (CHAV$, CEXP$, CRET$, cname$, TARG$, SW$, n%)
DECLARE SUB Trim (G$)
DECLARE SUB WriteMaster (MPS%, TITLE$, MIDD$, PRMFILE$, MSTFILE$, MSWITCH%)
DECLARE SUB WriteToPRMfile (code%)
'--------------------------------------------------------------------------
CONST PROGID$ = "NET2PRM.BAS v1.8X 10/19/90"
CONST PRMDATA$ = "NET2PRM.CNF" 'SYNETSIM parameter configuration
CONST MSTDATA$ = "NET2MST.CNF" ' and master file configuration.
CONST BATDATA$ = "NET2SBT.CNF" ' and batch file information
CONST MAXBR% = 50 'from SYNETSIM dimensions
CONST DFCOUNT% = 30 'allow 30 .DEFINE commands
CONST NTCOUNT% = 200 'allow 200 components in net
CONST BatchSize% = 100 'lines of batch text allowed
CONST SPKFLG$ = "TRIGR SPIKE STIM" 'synaptic connection aliases
CONST CPALIAS$ = "CMPT SPHERE CYL" 'cmpt aliases
CONST Cmnt$ = "'" 'choose your comment indicator
CONST ENDBATCH$ = "7" 'marks end of .SBT file for
CONST pi = 3.1415926# ' synetsim.
CONST cunit = 1 'uF per square cm
CONST LEGALBR% = 2 'allow Y and Delta nets at most.
'--------------------------------------------------------------------------
PRINT PROGID$ 'Print header
PRINT
CALL GetFileNames(NETFILE$, PRMFILE$, MSTFILE$, BATFILE$, SW$)
'-----------------------
'--->Parameter File Info
PRINT "Searching the current directory for "; PRMDATA$; "...";
CALL GetFormatSize(PFID$, SHIC%, HIC%, HIP%, MTYP%, PHID%)
LOCATE CSRLIN, 1
'Arrays containing reference data
'--------------------------------
DIM SHARED PRM$(HIC%, HIP%) 'names of legal parameters
DIM SHARED PPRM$(MTYP%, PHID%, HIP%) 'extra data for 'TYPE=' codes
DIM SHARED COD$(HIC%) 'names of available codes
DIM SHARED CODN%(HIC%) 'code counter
DIM SHARED CNECT$(HIC%) 'connection types
DIM SHARED PCNECT$(MTYP%, PHID%) 'pool connection types
DIM SHARED PTYP$(MTYP%) 'relating codenames using
'------------------------------------------
CALL GetParmNames(HIC%, HIP%, MTYP%, PHID%)
'Arrays containing netlist info
'------------------------------
DIM SHARED cname$(MAXBR%) 'cell/cmpt names
DIM SHARED STIM$(MAXBR%) 'STIM names
DIM SHARED CYLBR$(MAXBR%) 'Names of connecting cylinders
DIM SHARED CYLGC(MAXBR%, MAXBR%) 'Conductance values for same
DIM SHARED CYLBC%(MAXBR%, LEGALBR%) 'Number of connections to a cylinder
DIM SHARED DFPRM(DFCOUNT%, HIP%) 'DEFINE'd parameters
DIM SHARED DFNAME$(DFCOUNT%) 'definition names
DIM SHARED ntname$(NTCOUNT%) 'network names and info
DIM SHARED TMPRM$(HIP%) 'temp. storage before disk
DIM SHARED NSORT$(NTCOUNT%) 'used to keep netlist order
DIM SHARED PPOS%(MAXBR%) 'used to assign pools to POOLX
DIM SHARED BATCH$(BatchSize%) 'storage of .BATCH info
DIM SHARED TXFLG$(HIC%) 'toxin flags for master file
'--->Master File Info
PRINT "Searching the current directory for "; MSTDATA$; "... ";
CALL GetMasterSize(MPS%)
LOCATE CSRLIN, 1
'-------------------------------
DIM SHARED MNAME$(MPS%) 'master file parm names
DIM SHARED MVAL$(MPS%) 'master file parm values
'-------------------------------
CALL GetMasterInfo(MIDD$, MPS%)
'--->SBT or .BATCH File Info
PRINT "Searching the current directory for "; BATDATA$; "... ";
CALL GetBatchSize(HIBL%, HIBP%) 'Batch listings and batch parms
LOCATE CSRLIN, 1 'remove .CNF filenames from
PRINT SPACE$(79); 'screen once you know they
LOCATE CSRLIN, 1 'exist.
'-------------------------------
DIM SHARED BNAME$(HIBL%) 'names of batch items (i.e. FREE_RUN)
DIM SHARED BPARM$(HIBL%, HIBP%) 'valid parm names and numbers
DIM SHARED BTEMP$(HIBP%) 'temp array prior to disk write
'-------------------------------
CALL GetBatchInfo(BFID$, HIBL%)
'-------------------------------
'Done with parameter info file, get netlist info.
'-->Process command line switch
IF SW$ = "" THEN
GOTO Default
ELSE
SW% = ASC(SW$) - 64
ON SW% GOTO a, invalid, invalid, D
END IF
invalid:
PRINT
PRINT "Invalid switch /"; SW$; " in command line ignored."; CHR$(7)
PRINT
GOTO Default
a:
REM Author mode.. primarily for debugging.
DBUG% = -1
PRINT "Debug mode is ON."
GOTO Default
D:
REM Change the way geometrical calculations proceed.
REM All calculated conductances will be in mhos, not mhos/cm2.
PRINT
PRINT "Using SYNETSIM 3.2D format for calculated conductances."
PRINT
OLDVERSW% = -1
Default:
REM Default setting is OLDVERSW%=0... Compatible with SYNETSIM 3.3.1
REM Calculated conductances will be conductance densities, in mhos/cm2
'------------------------
REM Start of Main Program
'------------------------
PRINT "Opening netlist "; TAB(25); NETFILE$
OPEN "I", 1, NETFILE$
LINE INPUT #1, TITLE$
CALL StripQuotes(TITLE$)
'First Pass reads all data from file
cell% = 0: count% = 0
WHILE NOT EOF(1) AND find$ <> ".END"
DO 'Get a line from netlist
CALL GetALine(a$) 'ignoring comment lines
CALL FixText(a$) 'and blank lines
CALL Trim(a$)
LOOP WHILE LEFT$(a$, 1) = Cmnt$ OR a$ = ""
srch$ = a$
CALL GetNextParm(find$, srch$) 'get first word of line
'use it to make a decision.
IF find$ = ".DEFINE" THEN
CALL ReadDefinition(srch$)
ELSEIF find$ = ".MASTER" THEN
MSWITCH% = -1 'set master flag.
IF LEFT$(srch$, 1) = "(" THEN
CALL ReadMaster(srch$) 'and read information
ELSE
CALL ErrorCheck(1, -1, srch$) 'else fatal error.
END IF
ELSEIF find$ = ".BLOCK" THEN
IF LEFT$(srch$, 1) = "(" THEN
CALL ReadBlock(srch$) 'read .block information
ELSE
CALL ErrorCheck(1, -1, srch$) 'else fatal error.
END IF
ELSEIF find$ = ".BATCH" THEN
BSWITCH% = -1 'set batch flag.
CALL ReadBatch(srch$) 'and read .batch information
ELSEIF find$ = ".END" THEN
EMSG% = -1 'set 'proper' ending flag.
ELSEIF find$ = "CELL" THEN 'treat special case CELL
CALL GetNextParm(find$, srch$)
cell% = cell% + 1
cell$(cell%) = find$
cell$ = cell$(cell%)
ELSE code% = 1 'treat Codes
CALL PushSwitch(find$, srch$)
WHILE find$ <> COD$(code%)
code% = code% + 1
IF code% > HIC% THEN CALL ErrorCheck(2, -1, find$)
WEND
count% = count% + 1
acode% = code% 'save original code
'in case of alias.
CODN%(code%) = CODN%(code%) + 1 'increment branch count
IF INSTR(CPALIAS$, find$) <> 0 THEN 'compartment special case
code% = 1 'certain aliases appear as cmpts
CODN%(code%) = CODN%(code%) + 1 'increment cmpt count
CODN%(acode%) = CODN%(acode%) - 1 'and decrement alias count.
CALL CodeCount("CMPT", cmpt%) 'get compartment count
CALL GetNextParm(find$, srch$) 'get CMPT name
cname$(cmpt%) = cell$(cell%) + "/" + find$
cname$ = cname$(cmpt%) 'store in cell/CMPT format
ntname$(count%) = cname$(cmpt%)
IF acode% <> code% THEN 'if it's an alias (CYL,SPHERE)
acode$ = STR$(acode%) 'then add !ALIAS to net info.
CALL Trim(acode$)
ntname$(count%) = ntname$(count%) + "!" + acode$
END IF
ELSE
ntname$(count%) = cname$(cmpt%)
IF COD$(acode%) = "INFCYL" THEN
ALIAS$ = STR$(acode%)
CALL Trim(ALIAS$)
ntname$(count%) = ntname$(count%) + "!" + ALIAS$
END IF
ntname$(count%) = ntname$(count%) + "/" + find$ 'include code
IF LEFT$(srch$, 1) = "/" THEN 'and switch, if one
CALL GetNextParm(find$, srch$) 'was pushed earlier
ntname$(count%) = ntname$(count%) + find$'cell/cmpt/code/switch
END IF
END IF
IF COD$(code%) = "POOL" THEN
CALL CodeCount("POOL", POOL%) 'Keep track of
PPOS%(POOL%) = count% 'pool locations in net
END IF
CALL RefreshInputText(srch$)
IF LEFT$(srch$, 1) = "(" THEN 'no .DEFINed parms
find$ = ""
ELSE
CALL GetNextParm(find$, srch$) 'DEFINition name
END IF
ntname$(count%) = ntname$(count%) + "|" + find$ 'add DEFINition, if any
CALL GetParentheses(find$, srch$) 'parm (modifications)
CALL ErrorCheck(1, VAL(find$), B$)
ntname$(count%) = ntname$(count%) + "|" + find$
CALL GetNextParm(find$, srch$) 'first connection
CALL Trim(find$)
IF CNECT$(acode%) = "CMPT" AND find$ <> "" THEN
CALL CountSlash(find$, NSL%, SP%)
IF NSL% = 0 THEN
find$ = cell$(cell%) + "/" + find$ 'add cell name
END IF
IF COD$(acode%) = "CYL" THEN 'resistive network info
CYLBR$(cmpt%) = find$ 'stored in CYLBR$
find$ = "" 'rather than with CYL.
END IF
END IF
find$ = find$ + "|" + srch$ 'second connection, if any
CALL Trim(find$)
ntname$(count%) = ntname$(count%) + "|" + find$ 'add connections
NSORT$(count%) = STR$(100000 + code% * 1000 + count%) 'and index
IF COD$(acode%) = "INFCYL" THEN 'special case alias
a$ = ntname$(count%)
NSORT$(count%) = STR$(102000 + count%) 'sort just after CMPTs
ALIAS$ = NSORT$(count%)
CALL Trim(ALIAS$) 'add COND branch
count% = count% + 1
ntname$(count%) = cname$(cmpt%) + "/COND/!" + ALIAS$ + "||( )|"
CALL CodePointer("COND", DP%)
CODN%(DP%) = CODN%(DP%) + 1 'increment COND count
NSORT$(count%) = STR$(100000 + DP% * 1000 + count%)'add sorting index
END IF
END IF
WEND
IF EMSG% <> -1 THEN 'warn of missing .END statement
PRINT
PRINT "Missing .END statement in netlist."; CHR$(7)
PRINT
END IF
CLOSE #1 'Done with netlist
'------------------------------------------------------------------------
' End of first pass through netlist. Each item in netlist is stored as |
' cell/cmpt[!alias][/code/[switch]]|[defin]|[(mods)]|[cnect1]|[cnect2] |
'------------------------------------------------------------------------
' Examine CYLBR$() to begin resolving Y networks into delta networks...
'
FOR I% = 1 TO MAXBR% 'step through compartments
IF cname$(I%) <> "" THEN
FOR J% = 1 TO MAXBR% 'step through connections
IF CYLBR$(J%) = cname$(I%) THEN
CYLBC%(I%, 0) = CYLBC%(I%, 0) + 1
IF CYLBC%(I%, 0) > LEGALBR% THEN
PRINT "Too many branches at compartment "; cname$(I%); CHR$(7)
STOP
END IF
CYLBC%(I%, CYLBC%(I%, 0)) = J%
END IF
NEXT J%
END IF
NEXT I%
' Create enough ELECTN connections for network transform
' The non-boolean negative value of GC will cause GC to be
' looked up in the array CYLGC().
FOR I% = 1 TO MAXBR%
B% = CYLBC%(I%, 0) 'number of connections to cmpt I%
IF B% > 0 THEN
FOR J% = 0 TO B%
IF J% = 0 THEN
cal% = I%
ELSE
cal% = CYLBC%(I%, J%)
END IF
NUMEL% = B% - J%
FOR K% = 1 TO NUMEL%
count% = count% + 1
CNECT$ = cname$(CYLBC%(I%, J% + K%))
n$ = cname$(cal%) + "/ELECTN/!CYL||(GC=cylgc)|" + CNECT$
ntname$(count%) = n$
CALL CodePointer("ELECTN", DP%)
CODN%(DP%) = CODN%(DP%) + 1
NSORT$(count%) = STR$(100000 + DP% * 1000 + count%) 'add sorting index
NEXT K%
NEXT J%
END IF
NEXT I%
FOR I% = 2 TO SHIC% 'analyze Toxin Flags.
IF (CODN%(I%) > 0 AND TXFLG$(I%) <> "BLOCK") THEN
TXFLG$(I%) = "0" 'unblocking net codes
END IF 'unless specifically BLOCKed.
NEXT I% 'Write Master File -->
CALL WriteMaster(MPS%, TITLE$, MIDD$, PRMFILE$, MSTFILE$, MSWITCH%)
CALL Sort(NSORT$(), ntname$(), count%) 'sort net by code and net order
'-----------------------------------------------------------------------
' Second pass makes netlist connections and writes PRM file.
'-----------------------------------------------------------------------
PRINT "Writing parameter file "; TAB(25); PRMFILE$
PRINT
OPEN "O", 1, PRMFILE$ '.PRM file
WRITE #1, TITLE$ 'As found in netlist
WRITE #1, PFID$ 'As found in PRMDATA.DAT'
code% = 0: POOL% = 0: K% = 0: GCFLAG% = -1
'Netlist info is now sorted by code number.
'Cmpt aliases fall under the heading of compartments.
'INFCYL alias is at the top of the list, with CODE=0.
'(aliases need to be evaluated first, removing !ALIAS notation
'prior to making connections to !ALIAS compartments.)
CALL CodePointer("CYL", DP%) 'remove connection field
CNECT$(DP%) = "" 'from CYL alias for 2nd pass.
FOR I% = 1 TO count%
IF VAL(MID$(NSORT$(I%), 3, 2)) <> code% THEN
code% = VAL(MID$(NSORT$(I%), 3, 2))
K% = 0
END IF
K% = K% + 1
CALL CheckForTyp(code%, TYPFLG%) 'location in PTYP$, if any.
a$ = ntname$(I%) 'current line of netlist
IF DBUG% THEN
PRINT a$; 'to examine net as it is
LINE INPUT "", FOO$ 'compiled.. use /A switch.
END IF
CALL GetData(a$, C2$, 1, "/") 'cell name
CALL GetData(a$, C3$, 2, "/") 'cmpt name|defin|(parms)...
CALL GetData(C3$, C4$, 1, "|") 'cmpt name
SP% = INSTR(C4$, "!")
IF SP% = 0 THEN
acode% = code%
ELSE 'if this is an alias
acode% = VAL(RIGHT$(C4$, LEN(C4$) - SP%))'then remove !ALIAS from cmpt
IF COD$(acode%) = "INFCYL" THEN
code% = acode%
ELSE
code% = 1 'name, and act accordingly.
END IF
C4$ = LEFT$(C4$, SP% - 1)
X$ = ntname$(I%)
SP% = INSTR(X$, "!") - 1
EP% = INSTR(X$, "|") - 1
ntname$(I%) = LEFT$(X$, SP%) + RIGHT$(X$, LEN(X$) - EP%)
END IF
cname$ = C2$ + "/" + C4$ 'name of current cell/cmpt.
cmpt% = 1
WHILE cname$ <> cname$(cmpt%)
cmpt% = cmpt% + 1 'number of current cmpt.
WEND
cell% = 1
WHILE C2$ <> cell$(cell%)
cell% = cell% + 1 'number of current cell.
WEND
'________________ Alias Patch for ELECTN connections _______________
IF code% > 1 AND GCFLAG% THEN 'Resolve Y-networks now
FOR m% = 1 TO MAXBR%
'For now, special cases...
IF CYLBC%(m%, 0) = 0 THEN
REM no connections
ELSEIF CYLBC%(m%, 0) = 1 THEN 'Two nodes... sum resistances or
n% = CYLBC%(m%, 1) 'take series combo of conductances.
Gm = CYLGC(m%, m%): Gn = CYLGC(n%, n%)
IF Gm = 0 THEN
GCeff = Gn
ELSEIF Gn = 0 THEN
GCeff = Gm
ELSE
GCeff = Gm * Gn / (Gm + Gn)
END IF
CYLGC(n%, m%) = GCeff
CYLGC(m%, n%) = GCeff
ELSEIF CYLBC%(m%, 0) = 2 THEN
REM DELTA Transform
nodeA% = m%
nodeB% = CYLBC%(m%, 1)
nodeC% = CYLBC%(m%, 2)
g1 = CYLGC(nodeA%, nodeA%)
IF g1 = 0 THEN
r1 = 0
ELSE
r1 = 1 / g1
END IF
g2 = CYLGC(nodeB%, nodeB%)
IF g2 = 0 THEN
r2 = 0
ELSE
r2 = 1 / g2
END IF
g3 = CYLGC(nodeC%, nodeC%)
IF g3 = 0 THEN
r3 = 0
ELSE
r3 = 1 / g3
END IF
Rdenom = r1 * r2 + r2 * r3 + r3 * r1
gA = r1 / Rdenom
gB = r2 / Rdenom
gC = r3 / Rdenom
CYLGC(nodeB%, nodeC%) = gA: CYLGC(nodeC%, nodeB%) = gA
CYLGC(nodeA%, nodeC%) = gB: CYLGC(nodeC%, nodeA%) = gB
CYLGC(nodeA%, nodeB%) = gC: CYLGC(nodeB%, nodeA%) = gC
END IF
NEXT m%
GCFLAG% = 0
END IF
'__________________ End Alias Patch for ELECTN _______________________
CALL GetData(a$, DEFT$, 2, "|") 'get defin name
CALL StuffDefinition(DEFT$, acode%) 'and load defin'd parms.
CALL GetData(a$, MOD$, 3, "|") 'get (mod) string
IF TYPFLG% > 0 THEN
CALL GetTyp(MOD$, acode%, TYP%)
IF DBUG% THEN
PRINT "TYPFLG%="; TYPFLG%
PRINT "TYP%="; TYP%
PRINT "MOD$="; MOD$
END IF
END IF
CALL StuffMods(MOD$, acode%, -1) 'and modify parm set.
CALL GetData(a$, CHAV1$, 4, "|") 'get connection field
CALL GetData(CNECT$(acode%), CEXP1$, 1, "|")
IF DBUG% AND CHAV1$ <> "" THEN
PRINT "Calling TotalConnect with CHAV$="; CHAV1$
PRINT " CEXP$="; CEXP1$
PRINT " CNECT$="; CNECT$(acode%)
END IF 'and make connection.
CALL TotalConnect(CHAV1$, CEXP1$, CRET1$, cname$, TARG$, SW$, 1)
CALL GetData(a$, CHAV2$, 5, "|") 'get second connection field
CALL GetData(CNECT$(acode%), CEXP2$, 2, "|")
IF CEXP2$ <> "-1" THEN
CALL TotalConnect(CHAV2$, CEXP2$, CRET2$, cname$, TARG$, SW$, 2)
ELSE
CRET2$ = "" 'and make connection, if any.
END IF
'________________ Beginning of ALIAS section ______________________
'
' These codes are not recognized by synetsim, but rather they are
' interpreted by the compiler and transformed into synetsim codes.
' SPHERE and CYL are straightforward geometrical compartments, while
' INFCYL is a means of inserting a conductance into another compartment.
' The value of the conductance is equal to the input impedance of an
' infinite cylinder as specified in a given netlist.
IF COD$(acode%) = "SPHERE" THEN
diam = VAL(TMPRM$(1)) 'in um
rhom = VAL(TMPRM$(2)) 'in ohms-cm2
fold = VAL(TMPRM$(3)) 'dimensionless
rp = VAL(TMPRM$(4)) 'in millivolts
diam = diam * .0001 'converts um to cm
sa = pi * diam * diam * fold 'in cm2
C = sa * cunit 'in uF
GL = sa / (rhom * .000001) 'in umho
GAMMA = 1 / (rhom * .001) 'in mmho / cm2
MOD$ = "(C=" + STR$(C) + " RP=" + STR$(rp)
MOD$ = MOD$ + " GL=" + STR$(GL) + " GAMMA=" + STR$(GAMMA) + ")"
CALL FormatNumbers(MOD$)
CALL StuffDefinition("", code%) 'to set up tmprm array
CALL StuffMods(MOD$, code%, 0) 'to insert calculated parms
END IF
IF COD$(acode%) = "CYL" THEN
length = VAL(TMPRM$(2)) 'in cm
diam = VAL(TMPRM$(3)) 'in cm
rhom = VAL(TMPRM$(4)) 'in ohms-cm2
rhoi = VAL(TMPRM$(5)) 'in ohms/cm
fold = VAL(TMPRM$(6)) 'dimensionless
rp = VAL(TMPRM$(7)) 'in mV
length = length * .0001 'um to cm
diam = diam * .0001 'um to cm
sa = pi * diam * fold * length 'in cm2
C = sa * cunit 'in uF
gC = (pi * diam * diam) / (4! * rhoi * .000001 * length)'in umho
GL = sa / (rhom * .000001) 'in umho
GAMMA = 1 / (rhom * .001) 'in mmho / cm2
'The array CYLGC() will be full before any ELECTN connections
'are met by the second-pass compilation.
CYLGC(cmpt%, cmpt%) = gC * 2 'store 1/2 resistance
MOD$ = "(C=" + STR$(C) + " RP=" + STR$(rp)
MOD$ = MOD$ + " GL=" + STR$(GL) + " GAMMA=" + STR$(GAMMA) + ")"
CALL FormatNumbers(MOD$) 'Compartment parameters...
CALL StuffDefinition("", code%) 'set up tmprm$ array
CALL StuffMods(MOD$, code%, 0) 'and insert calculated parms.
END IF
IF COD$(acode%) = "INFCYL" THEN
diam = VAL(TMPRM$(1)) 'in cm
rhom = VAL(TMPRM$(2)) 'in ohms-cm2
rhoi = VAL(TMPRM$(3)) 'in ohms-cm
fold = VAL(TMPRM$(4)) 'dimensionless
rp = VAL(TMPRM$(5)) 'in mV
diam = diam * .0001 'um to cm
GINF = SQR((pi * pi * diam * diam * diam * fold) / (4 * rhom * rhoi))
GINF = GINF * 1000000! 'in umho
ALIAS$ = NSORT$(I%) 'Find COND and insert conductance value GINF
CALL Trim(ALIAS$) 'using !ALIAS notation as a guide.
ALIAS$ = "!" + ALIAS$
DP% = 1
WHILE INSTR(ntname$(DP%), ALIAS$) = 0
DP% = DP% + 1
WEND
SP% = INSTR(ntname$(DP%), " ")
lh$ = LEFT$(ntname$(DP%), SP% - 1)
rh$ = RIGHT$(ntname$(DP%), LEN(ntname$(DP%)) - SP%)
MOD$ = "GCOND=" + STR$(GINF) + " VCOND=" + STR$(rp)
CALL FormatNumbers(MOD$)
ntname$(DP%) = lh$ + MOD$ + rh$
GOTO SkipWrite 'This alias doesn't directly
END IF 'write to .PRM file.
IF COD$(acode%) = "COND" THEN 'final INFCYL patch
SP% = INSTR(ntname$(I%), "!")
IF SP% <> 0 THEN
CALL PRMPointer("GCOND=?", acode%, PP%)
GINF = VAL(TMPRM$(PP%))
gC = CYLGC(cmpt%, cmpt%)
IF gC = 0 THEN 'not a cylinder-type cmpt.
Geff = GINF
ELSE 'else take series combo of G's
Geff = GINF * gC / (GINF + gC)
END IF
TMPRM$(PP%) = STR$(Geff)
END IF
END IF
'___________ end of ALIAS section ________________________________
' Insertion of synetsim branch numbers, compartment numbers, cell
' numbers, cell names, etc. These are all functions of netlist
' structure, rather than functions of the individual netlist items.
K$ = "K%=" + STR$(K%)
CP$ = " CP%=" + STR$(cmpt%)
CL$ = " CELL%=" + STR$(cell%)
CLL$ = " CELL$=" + cname$
IF COD$(code%) = "POOL" THEN
CALL GetData(a$, PN$, 1, "|")
IF INSTR(PN$, "POOL/") = 0 THEN
PN$ = "" 'if the pool has a switch,
ELSE
PN$ = RIGHT$(PN$, LEN(PN$) - INSTR(PN$, "POOL/") - 3)
END IF 'make that the pool name, and
DFT$ = RIGHT$(DEFT$, LEN(DEFT$) - INSTR(DEFT$, "POOL/") - 4)
PN$ = " XNAME$=" + DFT$ + PN$ 'attach name to POOL in PRM file.
END IF
POOL% = 0
OC% = VAL(MID$(NSORT$(I%), 5, 3))
WHILE PPOS%(POOL% + 1) < OC% AND PPOS%(POOL% + 1) <> 0
POOL% = POOL% + 1
WEND 'attach pool number.
PLP$ = " POOL%=" + STR$(POOL%)
MOD$ = K$ + CP$ + CL$ + CLL$ + PN$ + PLP$ + " " + CRET1$ + " " + CRET2$
CALL FormatNumbers(MOD$)
CALL Trim(MOD$)
MOD$ = "(" + MOD$ + ")"
' At this point, MOD$ contains many things. Some are needed, and
' some are not. Obviously, an ELECTN connection doesn't need or
' use a POOL number. Information which is not needed is simply
' ignored.
CALL StuffMods(MOD$, code%, 0)
IF COD$(code%) = "ELECTN" THEN
CALL PRMPointer("GC=?", code%, PP%)
IF TMPRM$(PP%) = "cylgc" THEN 'GC needs to be looked up.
CALL PRMPointer(" CHR$(34) THEN G$ = CHR$(34) + G$
IF RIGHT$(G$, 1) <> CHR$(34) THEN G$ = G$ + CHR$(34)
END SUB
'======================================================================
' Subroutines used by NET2PRM.BAS
'======================================================================
'==========================================
SUB CheckConnect (CON$, SW$, DP%) STATIC
'Examines a connection name, isolating a
'switch if necessary, returning the code
'number of connection in CODE%. Switch is
'returned in SW$, if it exists.
'-----------------------------------------
SHARED DBUG%
IF DBUG% THEN PRINT "Connection given to CheckConnect as "; CON$
SW$ = ""
CALL CountSlash(CON$, NSL%, SP%)
CALL GetData(CON$, code$, NSL% + 1, "/")
CALL CodePointer(code$, DP%)
IF DP% = -1 THEN
CALL PushSwitch(CON$, SW$)
CALL CountSlash(CON$, NSL%, SP%)
CALL GetData(CON$, code$, NSL% + 1, "/")
CALL CodePointer(code$, DP%)
IF DP% = -1 THEN
m$ = "Connection error... connection reads: " + CON$ + CHR$(13)
m$ = m$ + "No such code " + code$
CALL ErrorCheck(10, -1, m$)
END IF
ELSE
SW$ = ""
END IF
IF DBUG% THEN
PRINT "Successful connection made..."
PRINT "CODE = "; COD$(DP%)
PRINT "Switch = "; SW$
END IF
END SUB
'===================================
SUB CheckForTyp (code%, DP%) STATIC
'Returns DP%=-1 if no type is
'required. Returns DP%=PTYP%
'(position in PTYP$) if a type
'designator is required.
'(i.e. PTYP$(1)="POOL" as it
'is the first CODE requiring a type
'designator as of 08/06/90)
'----------------------------------
SHARED MTYP%
DP% = 1: I% = 1
WHILE (COD$(code%) <> PTYP$(I%) AND DP% > 0)
I% = I% + 1
IF I% > MTYP% THEN
DP% = -1
I% = 1
ELSE
DP% = I%
END IF
WEND
END SUB
'==========================================
SUB CodeCount (code$, n%) STATIC
'Returns N%, the number of branches
'of code CODE$ currently processed.
'When called from second pass, returns
'the number of branches in the net.
'-----------------------------------------
CALL CodePointer(code$, DP%)
IF DP% > 0 THEN
n% = CODN%(DP%)
ELSE
n% = -1
END IF
END SUB
'==========================================
SUB CodePointer (f$, DP%) STATIC
'F$ is a (supposed) code name.
'This routine checks for F$ in COD$(),
'returning DP% as a pointer into COD$().
'A negative value of DP% indicates no find.
'------------------------------------------
SHARED HIC%
I% = 1: DP% = 1
WHILE f$ <> COD$(I%) AND DP% > 0
I% = I% + 1
IF I% > HIC% THEN
DP% = -1: I% = 1
ELSE
DP% = I%
END IF
WEND
END SUB
'======================================================
SUB CountSlash (f$, n%, s%) STATIC
'Count /'s in F$ and return position of last one as S%
'-----------------------------------------------------
n% = 0
FOR I% = 1 TO LEN(f$)
IF MID$(f$, I%, 1) = "/" THEN n% = n% + 1: s% = I%
NEXT I%
END SUB
'==============================================
SUB DEFPointer (D$, DP%) STATIC
'Looks for D$ in DFNAME()$, returns DP% as a
'pointer into DFNAME$() and DFPRM().
'Failure is indicated by DP%=-1.
'---------------------------------------------
I% = 1: DP% = 1
WHILE D$ <> DFNAME$(I%) AND DP% > 0
I% = I% + 1
IF I% > VAL(DFNAME$(0)) THEN
DP% = -1
ELSE
DP% = I%
END IF
WEND
IF DP% = -1 THEN
PRINT "Unknown Definition: "; D$
END IF
CALL ErrorCheck(6, DP%, D$)
END SUB
'=====================================
SUB ErrorCheck (EMSG%, FLAG%, m$) STATIC
'Checks FLAG% for -1 (fatal error)
'returns otherwise
'------------------------------------
IF FLAG% = -1 THEN
ON EMSG% GOTO 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
1 EMSG$ = "Format error in netlist." + CHR$(13) + m$: GOTO DoneEC
2 EMSG$ = "Invalid codename " + m$ + " in netlist.": GOTO DoneEC
3 EMSG$ = "Invalid command " + m$ + " in netlist.": GOTO DoneEC
4 EMSG$ = "Invalid code definition " + m$ + " in netlist.": GOTO DoneEC
5 EMSG$ = "Invalid parameter " + m$ + " in netlist.": GOTO DoneEC
6 EMSG$ = "Undefined label " + m$ + " in netlist.": GOTO DoneEC
7 EMSG$ = "Unmatched parentheses in netlist." + CHR$(13) + m$: GOTO DoneEC
8 EMSG$ = "No cells specified in netlist.": GOTO DoneEC
9 EMSG$ = "Missing/invalid " + m$ + " connection.": GOTO DoneEC
10 EMSG$ = m$: GOTO DoneEC
DoneEC:
PRINT EMSG$; CHR$(7)
CLOSE #1
END
END IF
END SUB
'=========================================
SUB FixText (T$) STATIC
'Convert to upper-case and eliminate tabs
'----------------------------------------
FOR n% = 1 TO LEN(T$)
m% = ASC(MID$(T$, n%, 1))
IF m% > 96 AND m% < 123 THEN
m% = m% - 32 'see lower case as upper case
END IF
IF m% = 9 THEN
m% = 32 'see tabs as spaces
END IF
MID$(T$, n%, 1) = CHR$(m%)
NEXT n%
END SUB
'============================================
SUB FormatNumbers (f$) STATIC
'removes leading spaces from numbers found
'in parameter listings
'-------------------------------------------
WHILE INSTR(f$, "= ") > 0
s% = INSTR(f$, "= ")
f$ = LEFT$(f$, s%) + RIGHT$(f$, LEN(f$) - s% - 1)
WEND
END SUB
'=========================================
SUB FormFullName (CON$, SW$, cname$) STATIC
'Adds cell and cmpt names to a connection
'----------------------------------------
CALL CountSlash(CON$, NSL%, SP%)
IF NSL% = 0 THEN CON$ = cname$ + "/" + CON$
IF NSL% = 1 THEN CON$ = LEFT$(cname$, INSTR(cname$, "/")) + CON$
CON$ = CON$ + SW$
END SUB
SUB GetALine (a$)
'get a line from the netlist file
'or from queue.
SHARED queue$
IF queue$ = "" THEN
LINE INPUT #1, a$
CALL FixText(a$)
ELSE
a$ = queue$
queue$ = ""
END IF
END SUB
'=========================================
SUB GetBatchInfo (BFID$, B%) STATIC
'Look at configuration file, get info
'on .SBT translation table.
'----------------------------------------
OPEN "I", 1, BATDATA$
DO 'first line is file format code
LINE INPUT #1, BFID$ 'after all comments are ignored.
CALL Trim(BFID$)
CALL StripQuotes(BFID$)
LOOP WHILE (BFID$ = "" OR LEFT$(BFID$, 1) = Cmnt$)
FOR I% = 1 TO B%
DO
CALL GetCaps(a$)
CALL Trim(a$)
LOOP WHILE LEFT$(a$, 1) = Cmnt$
SP% = INSTR(a$, "=")
IF SP% = 0 THEN
PRINT "Framing error in "; BATDATA$; "."; CHR$(7)
PRINT "Unable to process batch file."
END
ELSE
B$ = LEFT$(a$, SP% - 1)
CALL Trim(B$)
BNAME$(I%) = B$
a$ = RIGHT$(a$, LEN(a$) - SP%)
END IF
P% = 0
DO
P% = P% + 1
BPARM$(I%, P%) = a$
CALL GetCaps(a$)
CALL Trim(a$)
LOOP UNTIL a$ = "END"
BPARM$(I%, 0) = STR$(P%)
NEXT I%
CLOSE #1
END SUB
'=========================================
SUB GetBatchSize (B%, MAXP%) STATIC
'Look at configuration file, get size of
'batch translation information table.
'----------------------------------------
OPEN "I", 1, BATDATA$
DO 'first line is file format code
LINE INPUT #1, BFID$ 'after all comments are ignored.
CALL Trim(BFID$)
CALL StripQuotes(BFID$)
LOOP WHILE (BFID$ = "" OR LEFT$(BFID$, 1) = Cmnt$)
WHILE NOT EOF(1)
CALL GetCaps(C$) 'Batch command name
CALL Trim(C$)
IF LEFT$(C$, 1) <> Cmnt$ AND C$ <> "" THEN 'If it's not a comment
B% = B% + 1 'count it as a command
P% = 0
WHILE C$ <> "END"
CALL GetCaps(C$)
CALL Trim(C$)
P% = P% + 1 'Another parameter
WEND
IF P% > MAXP% THEN MAXP% = P%
END IF
WEND
CLOSE #1
END SUB
'==========================================
SUB GetCaps (T$) STATIC
'Get a string from file#1, convert to caps
'-----------------------------------------
INPUT #1, T$
CALL FixText(T$)
END SUB
'=====================================================
SUB GetData (a$, B$, n%, D$) STATIC
'A$ is input to subroutine, a string to be parsed.
'D$ is a delimiting character, usually a '|' or '/'
'N% indicates which piece of data to extract from A$
' e.g. 1st, 2nd, 3rd item.
'and B$ is the actual string in A$ which is returned.
'This string is located between the (N%-1)th delimiter
'and the (N%)th delimiter... the first delimiter or
'initial character of A$ is assumed.
'
'This routine is non-destructive to A$.
'-----------------------------------------------------
Q% = 0
f$ = a$ + D$
FOR I% = 1 TO n%
P% = Q% + 1
Q% = INSTR(P%, f$, D$)
NEXT I%
IF Q% = 0 THEN
B$ = "-1"
ELSE
B$ = MID$(f$, P%, Q% - P%)
END IF
END SUB
'================================================================
SUB GetFileNames (NETFILE$, PRMFILE$, MSTFILE$, BATFILE$, SW$) STATIC
'Input .NET .PRM .MST and .SBT filenames
'---------------------------------------------------------------
CM$ = COMMAND$
CALL Trim(CM$)
IF CM$ <> "" THEN 'first remove any switches...
CALL FixText(CM$)
SP% = INSTR(CM$, "/")
IF SP% > 0 THEN
EP% = INSTR(SP%, CM$, " ")
IF EP% = 0 THEN EP% = LEN(CM$) + 1
SW$ = MID$(CM$, SP% + 1, EP% - SP% - 1)
CM$ = LEFT$(CM$, SP% - 1) + RIGHT$(CM$, LEN(CM$) - EP% + 1)
END IF
END IF
CALL Trim(CM$)
IF CM$ = "" THEN 'then pluck filenames.
PRINT
PRINT "Usage: net2prm netfile [prmfile] [mstfile] [sbtfile]"
PRINT
PRINT " where [prmfile], [mstfile], and [sbtfile], if omitted,"
PRINT " default to netfile."
PRINT
PRINT " Extensions, if omitted, default to:"
PRINT " netfile.NET prmfile.PRM mstfile.MST sbtfile.SBT"
PRINT
PRINT "Switches:"
PRINT
PRINT " /d ... compile using SYNETSIM 3.2D or earlier format"
PRINT " (affects calculated conductances)"
PRINT
PRINT " Default is compatibility with SYNETSIM 3.3.1 or"
PRINT " later, using conductance densities."
PRINT
END
ELSE
f% = 0
WHILE CM$ <> ""
f% = f% + 1
CALL GetNextParm(find$, CM$)
PHILE$(f%) = find$
CALL Trim(CM$)
WEND
NETFILE$ = PHILE$(1)
SP% = INSTR(NETFILE$, ".")
IF SP% = 0 THEN
FIRST$ = NETFILE$
NETFILE$ = NETFILE$ + ".NET"
ELSE
FIRST$ = LEFT$(NETFILE$, SP% - 1)
END IF
FOR I% = 2 TO 4
IF PHILE$(I%) = "" THEN PHILE$(I%) = FIRST$
NEXT I%
CALL MakeFileName(PRMFILE$, PHILE$(2), ".PRM")
CALL MakeFileName(MSTFILE$, PHILE$(3), ".MST")
CALL MakeFileName(BATFILE$, PHILE$(4), ".SBT")
END IF
END SUB
'=======================================================
SUB GetFormatSize (PFID$, SHC%, HC%, HP%, MTYP%, PHD%) STATIC
'Reads from file PRMDATA$ the necessary array sizes
'also checks for proper file format.
'------------------------------------------------------
'MTYP% = number of codes using the 'type=' format (i.e. POOL, POOLX)
' PHD% = max number of 'types' found (i.e. POOLX has 7 types)
' SHC% = the number of codes used by synetsim
' HC% = the number of total codes (including aliases) found
' HP% = the max number of parameters found (i.e. TRIGR has about 30)
SHC% = 0: HC% = 0: HP% = 0: PHD% = 0: MTYP% = 0: OLDC% = 0
OPEN "I", 1, PRMDATA$
DO
LINE INPUT #1, PFID$
CALL Trim(PFID$)
CALL StripQuotes(PFID$)
LOOP WHILE (PFID$ = "" OR LEFT$(PFID$, 1) = Cmnt$)
WHILE NOT EOF(1)
CALL GetCaps(C$) 'should be code number
CALL Trim(C$)
IF LEFT$(C$, 1) <> "'" THEN 'or a comment.
C% = VAL(C$)
IF RIGHT$(C$, 1) = "*" THEN SHC% = C% 'last code recognized by
' synetsim is marked with *.
IF C% <> 0 THEN
CALL GetCaps(C$) 'get code name
IF C% <> OLDC% THEN 'is this a new code number?
OLDC% = C%
BUMP% = -1
IF C% > HC% THEN HC% = C% 'highest code found
ELSE
IF BUMP% THEN
MTYP% = MTYP% + 1 'if it's the second occurrence
BUMP% = 0 'of codenumber, it must have
END IF 'TYPE structure. Increment TYPE.
END IF
P% = -1
DO
CALL GetCaps(P$) 'count parameters
P% = P% + 1
IF P% > HP% THEN HP% = P% 'highest param number found
IF INSTR(P$, "=") <> 0 THEN
D% = VAL(RIGHT$(P$, LEN(P$) - INSTR(P$, "=")))
IF D% > PHD% THEN PHD% = D% 'highest type number found
END IF
LOOP WHILE P$ <> "END"
END IF
END IF
WEND
CLOSE #1
END SUB
'=========================================
SUB GetMasterInfo (MIDD$, MPS%) STATIC
'Look at configuration file, get info
'on .MST file format.
'----------------------------------------
SHARED HIC%
FOR I% = 1 TO HIC% 'set initial conditions for toxin flags
TXFLG$(I%) = "-1"
NEXT I%
OPEN "I", 1, MSTDATA$
DO
LINE INPUT #1, MIDD$
CALL Trim(MIDD$)
LOOP WHILE (MIDD$ = "" OR LEFT$(MIDD$, 1) = Cmnt$)
FOR I% = 1 TO MPS%
INPUT #1, a$
MNAME$(I%) = a$
MVAL$(I%) = "0"
IF RIGHT$(MNAME$(I%), 4) = "FILE" THEN
MVAL$(I%) = "NONE"
END IF
NEXT I%
CLOSE #1
END SUB
'========================================
SUB GetMasterSize (MPS%) STATIC
'Look at configuration file, get size of
'.MST file format.
'---------------------------------------
OPEN "I", 1, MSTDATA$
MPS% = -1
DO
LINE INPUT #1, MIDD$
CALL Trim(MIDD$)
LOOP WHILE (MIDD$ = "" OR LEFT$(MIDD$, 1) = Cmnt$)
DO
INPUT #1, a$
MPS% = MPS% + 1
LOOP WHILE NOT EOF(1) AND a$ <> "END"
CLOSE #1
END SUB
'=========================================================
SUB GetNextParm (f$, s$) STATIC
'Sub to take leftmost data from SRCH$, up to first space.
'This routine also strips leading spaces from both SRCH$
'and FIND$, appending a trailing space to SRCH$ if needed.
'
'This routine is destructive to S$, and is used to process
'S$ piece by piece. F$ is the latest piece, so to speak.
'---------------------------------------------------------
CALL Trim(s$)
IF s$ = "" THEN
CALL GetALine(a$) 'get another line of text from netlist
CALL Trim(a$)
IF LEFT$(a$, 1) = "+" THEN
a$ = RIGHT$(a$, LEN(a$) - 1) 'continuation line
s$ = a$
ELSE
CALL StoreALine(a$) 'else put it back, so to speak.
s$ = ""
END IF
END IF
CALL Trim(s$)
s$ = s$ + " "
spl% = INSTR(s$, " ")
IF spl% = 0 THEN
f$ = ""
ELSE
f$ = LEFT$(s$, spl% - 1)
s$ = RIGHT$(s$, LEN(s$) - LEN(f$) - 1)
WHILE LEFT$(s$, 1) = " "
s$ = RIGHT$(s$, LEN(s$) - 1)
WEND
END IF
WHILE RIGHT$(s$, 1) = " "
s$ = LEFT$(s$, LEN(s$) - 1)
WEND
END SUB
'========================================================
SUB GetParentheses (f$, s$) STATIC
'If leftmost data in S$ is in parentheses, it is removed
'and placed in F$. Otherwise, S$ is untouched and F$ is
'null upon return.
'-------------------------------------------------------
CALL Trim(s$)
IF LEFT$(s$, 1) = "(" THEN
Try.again.with.more.text:
spl% = INSTR(s$, ")")
IF spl% = 0 THEN
CALL GetALine(a$)
CALL Trim(a$)
IF LEFT$(a$, 1) = "+" THEN
a$ = RIGHT$(a$, LEN(a$) - 1)
CALL Trim(a$)
s$ = s$ + " " + a$
GOTO Try.again.with.more.text
ELSE
CALL StoreALine(a$)
f$ = "-1"
END IF
ELSE
f$ = LEFT$(s$, spl%)
s$ = RIGHT$(s$, LEN(s$) - spl%)
WHILE LEFT$(s$, 1) = " "
s$ = RIGHT$(s$, LEN(s$) - 1)
WEND
END IF
ELSE
f$ = ""
END IF
WHILE RIGHT$(s$, 1) = " "
s$ = LEFT$(s$, LEN(s$) - 1)
WEND
END SUB
'============================================
SUB GetParmNames (HC%, HP%, MTYP%, PHID%) STATIC
'Loads codes and parameters into arrays
'from SYNETSIM parameter format file
'-------------------------------------------
OPEN "I", 1, PRMDATA$
PTYP% = 0
DO
LINE INPUT #1, T$
CALL Trim(T$)
CALL StripQuotes(T$)
LOOP WHILE (LEFT$(T$, 1) = Cmnt$ OR T$ = "")
WHILE NOT EOF(1)
INPUT #1, C$
C% = VAL(C$)
IF C% <> 0 THEN
CALL GetCaps(cname$)
IF COD$(C%) = "" THEN
COD$(C%) = cname$
BUMP% = -1
TYP% = 1
ELSE
TYP% = TYP% + 1
IF BUMP% THEN
PTYP% = PTYP% + 1
FOR P% = 0 TO VAL(PRM$(C%, 0))
PPRM$(PTYP%, 1, P%) = PRM$(C%, P%)
NEXT P%
PCNECT$(PTYP%, 1) = CNECT$(C%)
BUMP% = 0
END IF
PTYP$(PTYP%) = cname$
IF COD$(C%) <> cname$ THEN
m$ = "Error: Multiple code names for code" + STR$(C%) + CHR$(13)
m$ = m$ + "Check " + PRMDATA$ + " for errors."
CALL ErrorCheck(10, -1, m$)
END IF
END IF
P% = 1: CNECT1$ = "": CNECT2$ = ""
CALL GetCaps(PNAME$)
DO
IF LEFT$(PNAME$, 5) = "TYPE=" THEN
GTYP% = VAL(RIGHT$(PNAME$, LEN(PNAME$) - INSTR(PNAME$, "=")))
PNAME$ = "TYPE"
IF GTYP% <> TYP% THEN
m$ = "Warning: Missing/invalid TYPE specifications in " + PRMDATA$ + CHR$(13)
m$ = m$ + "Check " + PRMDATA$ + " for errors."
CALL ErrorCheck(10, -1, m$)
END IF
END IF
IF LEFT$(PNAME$, 1) = "<" THEN
IF LEFT$(PNAME$, 2) = "<<" THEN
CNECT2$ = "|" + RIGHT$(PNAME$, LEN(PNAME$) - 2)
ELSE
CNECT1$ = RIGHT$(PNAME$, LEN(PNAME$) - 1)
END IF
CNECT$ = CNECT1$ + CNECT2$
IF cname$ = PTYP$(PTYP%) THEN
PCNECT$(PTYP%, TYP%) = CNECT$
ELSE
CNECT$(C%) = CNECT$
END IF
END IF
IF cname$ = PTYP$(PTYP%) THEN
PPRM$(PTYP%, TYP%, P%) = PNAME$
END IF
PRM$(C%, P%) = PNAME$
P% = P% + 1
CALL GetCaps(PNAME$)
LOOP WHILE PNAME$ <> "END"
IF cname$ = PTYP$(PTYP%) THEN
PPRM$(PTYP%, TYP%, 0) = STR$(P% - 1)
END IF
PRM$(C%, 0) = STR$(P% - 1) 'store # of prms in zero pos.
END IF
WEND
CLOSE #1
END SUB
'==================================
SUB GetTyp (MOD$, code%, TYP%) STATIC
'For higher codes requiring a type
'designator, find type and load
'appropriate temporary set.
'---------------------------------
SHARED HIP%
CALL CheckForTyp(code%, TYPFLG%)
CALL PRMPointer("TYPE=?", code%, PP%)
TYP% = VAL(TMPRM$(PP%))
IF TYP% = 0 THEN
SP% = INSTR(MOD$, "TYPE=")
IF SP% = 0 THEN
m$ = "Code " + COD$(code%) + " requires a type designation."
PRINT m$
PRINT "Assuming TYPE=1"
TYP% = 1
TMPRM$(PP%) = "1"
ELSE
TYP% = VAL(RIGHT$(MOD$, LEN(MOD$) - SP% - 4))
END IF
END IF
CNECT$(code%) = PCNECT$(TYPFLG%, TYP%)
FOR J% = 0 TO HIP%
PRM$(code%, J%) = PPRM$(TYPFLG%, TYP%, J%)
NEXT J%
END SUB
'=========================================================
SUB MakeConnect (CON$, cname$, count%, DP%, CCD%, KC%) STATIC
'General purpose sub used in making netlist connections
'CON$ is the connection found in the netlist.
'CNAME$ is the name of the current compartment.
'COUNT% is an integer containing the number of net items.
'DP% is a pointer into the netlist to be used upon return.
'CCD% is the code number of the connection field.
'---------------------------------------------------------
J% = 1: KC% = 1
DO
SCD% = VAL(MID$(NSORT$(J%), 3, 2))
IF SCD% = CCD% THEN
DP% = J%
WHILE LEFT$(ntname$(J%), LEN(CON$)) <> CON$ AND DP% > 0
J% = J% + 1
KC% = KC% + 1
IF J% > count% THEN
DP% = -1
PRINT "Can't find connection "; CON$
PRINT "Connection ignored."; CHR$(7)
ELSE
DP% = J%
END IF
WEND
ELSE
J% = J% + 1
IF J% > count% THEN
DP% = -1
PRINT "Can't find connection "; CON$
PRINT "No "; COD$(CCD%); " branches exist in net."
PRINT "Connection ignored."; CHR$(7)
SCD% = CCD%
END IF
END IF
LOOP UNTIL CCD% = SCD%
IF DP% > 0 THEN
IF MID$(ntname$(DP%), LEN(CON$) + 1, 1) = "/" THEN
PRINT "Connection to "; CON$; " is ambiguous..."; CHR$(7)
PRINT
END IF
END IF
END SUB
'=========================================
SUB MakeFileName (f$, L$, R$) STATIC
'F$ is final product
'L$ is filename with or without extension
'R$ is default extension
'----------------------------------------
SP% = INSTR(L$, ".")
IF SP% > 0 THEN
f$ = L$
ELSE
f$ = L$ + R$
END IF
END SUB
'==============================================
SUB PRMPointer (f$, code%, DP%) STATIC
'F$ is of the form "GBAR=10.2" or PNAME$=PVAL$
'This routine checks PNAME$ against the arrays
'of legal parameters.
'It returns DP% as a pointer into PRM$(),
'and the value PVAL$ as a string in F$.
'A negative value of DP% signals a fatal error.
'----------------------------------------------
I% = 1: DP% = 1
IF INSTR(f$, "=") = 0 THEN
DP% = -1
ELSE
P$ = LEFT$(f$, INSTR(f$, "=") - 1)
f$ = RIGHT$(f$, LEN(f$) - LEN(P$) - 1)
END IF
WHILE P$ <> PRM$(code%, I%) AND DP% > 0
I% = I% + 1
IF I% > VAL(PRM$(code%, 0)) THEN
DP% = -1: I% = 1
ELSE
DP% = I%
END IF
WEND
END SUB
'=========================================
SUB ProcessBatch (BATFILE$) STATIC
'Interpret and write batch (.SBT) file
'----------------------------------------
SHARED HIBL%, HIBP%, MPS%
OPEN "O", 3, BATFILE$
L% = 1
s$ = BATCH$(L%)
CALL GetNextParm(find$, s$) 'name of batch command
DO
IF LEFT$(s$, 1) <> "(" THEN
PRINT "Syntax error in .BATCH command."
PRINT "Check netlist for errors."
PRINT
PRINT "S$="; s$
END
ELSE
s$ = RIGHT$(s$, LEN(s$) - 1) 'remove (
B% = 1
WHILE find$ <> BNAME$(B%) 'check for valid item
B% = B% + 1
IF B% > HIBL% THEN
PRINT "Invalid .BATCH command. Check to see that netlist"
PRINT "data matches with items listed in "; BATDATA$; "."; CHR$(7)
END
END IF
WEND
FOR I% = 0 TO HIBP%
BTEMP$(I%) = BPARM$(B%, I%) 'load temp array
NEXT I%
'begin parsing, continue until matching parenthesis is found
DO
IF s$ = "" THEN
L% = L% + 1
s$ = BATCH$(L%)
END IF
CALL GetNextParm(find$, s$)
CALL FixText(find$)
SP% = INSTR(find$, "=")
IF SP% = 0 THEN
PRINT "Syntax error in .BATCH command line. "
PRINT "Couldn't find '=' in parameter specifications."; CHR$(7)
END
ELSE
PNAME$ = LEFT$(find$, SP% - 1)
CALL Trim(PNAME$)
PVAL$ = RIGHT$(find$, LEN(find$) - SP%)
IF RIGHT$(PVAL$, 1) = ")" THEN
PVAL$ = LEFT$(PVAL$, LEN(PVAL$) - 1)
s$ = ")" + s$
END IF
END IF
P% = 1
WHILE PNAME$ <> BTEMP$(P%) 'check for valid item
P% = P% + 1
IF P% > HIBP% THEN
PRINT "Invalid .BATCH parameter "; PNAME$; ". Check to see that netlist"
PRINT "data matches with items listed in "; BATDATA$; "."; CHR$(7)
END
END IF
WEND
IF PNAME$ = "FLAG" THEN
IF PVAL$ = "ON" THEN
PVAL$ = "-1"
ELSEIF PVAL$ = "OFF" THEN
PVAL$ = "0"
ELSE
PRINT "Warning! Batch flags should be 'ON' or 'OFF' only."
PRINT "Flag "; PVAL$; " is set to OFF."; CHR$(7)
PRINT
PVAL$ = "0"
END IF
ELSEIF PNAME$ = "CODENAME" THEN
CALL CodePointer(PVAL$, DP%)
CALL ErrorCheck(2, DP%, "(.BATCH) " + PVAL$)
PVAL$ = STR$(DP%)
ELSEIF INSTR("POOL SPKFLG CMPT", PNAME$) <> 0 THEN
CALL TotalConnect(PVAL$, PNAME$, CRET$, "", TARG$, SW$, 0)
DP% = INSTR(CRET$, "=")
PVAL$ = STR$(VAL(RIGHT$(CRET$, LEN(CRET$) - DP%)))
ELSEIF PNAME$ = "TARGET" THEN
CALL TotalConnect(PVAL$, PNAME$, CRET$, "", TARG$, SW$, 0)
PVAL$ = ""
FOR I% = 1 TO 3
DP% = INSTR(CRET$, "=")
CRET$ = RIGHT$(CRET$, LEN(CRET$) - DP%)
P$ = STR$(ABS(VAL(CRET$)))
CALL Trim(P$)
PVAL$ = PVAL$ + P$ + ","
NEXT I%
PVAL$ = LEFT$(PVAL$, LEN(PVAL$) - 1)
ELSE
REM PVAL$ represents a valid parameter in all other cases.
END IF
CALL Trim(PVAL$)
BTEMP$(P%) = PVAL$
CALL Trim(s$)
LOOP UNTIL LEFT$(s$, 1) = ")"
s$ = LEFT$(s$, LEN(s$) - 1)
FOR I% = 1 TO (VAL(BTEMP$(0)) - 1)
CALL Trim(BTEMP$(I%))
PRINT #3, BTEMP$(I%); ",";
NEXT I%
PRINT #3, BTEMP$(VAL(BTEMP$(0)))
END IF
CALL Trim(s$)
IF s$ = "" THEN
L% = L% + 1
s$ = BATCH$(L%)
END IF
CALL GetNextParm(find$, s$)
LOOP UNTIL find$ = ".ENDBATCH"
PRINT #3, ENDBATCH$
CLOSE #3
END SUB
'==========================================
SUB PushSwitch (f$, s$) STATIC
'moves the /x switch from end of F$ to
'beginning of S$, leaving F$ with a code
'name and S$ with the switch and other
'parameters. If no switch exists, the
'strings are unchanged.
'-----------------------------------------
CALL CountSlash(f$, n%, ssl%)
IF n% <> 0 THEN
s$ = RIGHT$(f$, LEN(f$) - ssl% + 1) + " " + s$
f$ = LEFT$(f$, ssl% - 1)
END IF
CALL Trim(s$)
END SUB
'======================================
SUB ReadBatch (s$) STATIC
'read .BATCH to .ENDBATCH from netlist
'and store it in the array BATCH$
'-------------------------------------
SHARED MPS%, BATFILE$
IF VAL(BATCH$(0)) = 0 THEN
I% = 1
WHILE MNAME$(I%) <> "BATFILE" AND I% > 0
I% = I% + 1
IF I% > MPS% THEN
PRINT "Unable to find BATFILE placement in .MST configuration."
PRINT "Writing .SBT file, omitting information from .MST file."
PRINT CHR$(7)
I% = -1
END IF
WEND
IF I% > 0 THEN MVAL$(I%) = BATFILE$
B% = 1
ELSE
B% = VAL(BATCH$(0)) + 1
END IF
DO
CALL Trim(s$)
IF s$ <> "" THEN
IF LEFT$(s$, 1) <> Cmnt$ THEN
BATCH$(B%) = s$
B% = B% + 1
IF B% > BatchSize% THEN
PRINT ".BATCH information exceeds allowable size."
PRINT "Increase parameter BatchSize% and recompile NET2PRM."; CHR$(7)
END
END IF
END IF
END IF
IF EOF(1) THEN
PRINT ".BATCH without .ENDBATCH in netlist."; CHR$(7)
PRINT "Unable to continue compilation."
END
END IF
LINE INPUT #1, s$
LOOP UNTIL s$ = ".ENDBATCH"
BATCH$(B%) = s$
BATCH$(0) = STR$(B% - 1)
END SUB
'=========================================
SUB ReadBlock (s$) STATIC
'Reads code names to be blocked from
'master file selection.
'----------------------------------------
SHARED HIC%
s$ = RIGHT$(s$, LEN(s$) - 1)
DO
CALL GetNextParm(f$, s$)
code% = 2: DF% = 2
IF RIGHT$(f$, 1) = ")" THEN
G$ = LEFT$(f$, LEN(f$) - 1)
ELSE
G$ = f$
END IF
WHILE G$ <> COD$(code%) AND DF% > 0
code% = code% + 1
IF code% > HIC% THEN
DF% = -1
ELSE
DF% = code%
END IF
WEND
CALL ErrorCheck(2, DF%, G$)
TXFLG$(code%) = "BLOCK"
LOOP UNTIL RIGHT$(f$, 1) = ")"
END SUB
'=================================
SUB ReadDefinition (srch$) STATIC
'Loads information from a .DEFINE
'statement into the DFPRM array.
'--------------------------------
SHARED HIC%
count% = VAL(DFNAME$(0)) + 1
DFNAME$(0) = STR$(count%)
CALL GetNextParm(find$, srch$)
CALL CodePointer(find$, code%) 'Get code number
CALL ErrorCheck(4, code%, find$) 'and make sure it's valid.
CALL CheckForTyp(code%, TYPFLG%)
IF TYPFLG% > 0 THEN
SP% = INSTR(srch$, "TYPE=")
IF SP% = 0 THEN
PRINT ".DEFINE "; srch$
PRINT
PRINT "Error in .DEFINE statement:"
PRINT " Codes requiring TYPE designators (i.e. POOL and POOLX)"
PRINT " must include that TYPE designator in their .DEFINition."
PRINT "Assuming TYPE=1"
PRINT
TYP% = 1
ELSE
TYP% = VAL(RIGHT$(srch$, LEN(srch$) - SP% - 4))
END IF
FOR P% = 0 TO VAL(PPRM$(TYPFLG%, TYP%, 0))
PRM$(code%, P%) = PPRM$(TYPFLG%, TYP%, P%)
NEXT P%
END IF
CALL GetNextParm(find$, srch$)
DFNAME$(count%) = COD$(code%) + "/" + find$
IF LEFT$(srch$, 1) <> "(" THEN CALL ErrorCheck(1, -1, a$)
srch$ = RIGHT$(srch$, LEN(srch$) - 1)
DO
CALL GetNextParm(find$, srch$)
PNAME$ = LEFT$(find$, INSTR(find$, "="))
CALL PRMPointer(find$, (code%), PP%)
CALL ErrorCheck(5, PP%, PNAME$)
DFPRM(count%, PP%) = VAL(find$)
IF srch$ = "" AND RIGHT$(find$, 1) <> ")" THEN
LINE INPUT #1, srch$ 'get a new one
CALL FixText(srch$)
IF LEFT$(srch$, 1) <> "+" THEN CALL ErrorCheck(1, -1, srch$)
DO
srch$ = RIGHT$(srch$, LEN(srch$) - 1)
LOOP WHILE LEFT$(srch$, 1) = " "
END IF
LOOP WHILE RIGHT$(find$, 1) <> ")"
DFPRM(count%, 0) = VAL(PRM$(code%, 0)) 'store # of parms in 0 pos.
END SUB
'=========================================
SUB ReadMaster (s$) STATIC
'Loads information from a .MASTER state-
'ment into the MVAL$ array.
'----------------------------------------
SHARED MPS%
s$ = RIGHT$(s$, LEN(s$) - 1)
DO
CALL GetNextParm(f$, s$)
'Find parameter name and thus number
I% = 1: DP% = 1
IF INSTR(f$, "=") = 0 THEN
DP% = -1
ELSE
P$ = LEFT$(f$, INSTR(f$, "=") - 1)
f$ = RIGHT$(f$, LEN(f$) - LEN(P$) - 1)
END IF
WHILE P$ <> MNAME$(I%) AND DP% > 0
I% = I% + 1
IF I% > MPS% THEN
DP% = -1: I% = 1
ELSE
DP% = I%
END IF
WEND
CALL ErrorCheck(9, DP%, P$)
MVAL$(DP%) = f$
IF s$ = "" AND RIGHT$(f$, 1) <> ")" THEN
LINE INPUT #1, s$ 'get a new one
CALL FixText(s$)
IF LEFT$(s$, 1) <> "+" THEN CALL ErrorCheck(1, -1, s$)
DO
s$ = RIGHT$(s$, LEN(s$) - 1)
LOOP WHILE LEFT$(s$, 1) = " "
END IF
LOOP WHILE RIGHT$(f$, 1) <> ")"
MVAL$(DP%) = LEFT$(MVAL$(DP%), LEN(MVAL$(DP%)) - 1)
END SUB
SUB RefreshInputText (s$)
'make sure that s$ is current
'
CALL Trim(s$)
IF s$ = "" THEN
CALL GetALine(a$)
CALL Trim(a$)
IF LEFT$(a$, 1) = "+" THEN
a$ = RIGHT$(a$, LEN(a$) - 1)
CALL Trim(a$)
s$ = a$
ELSE
CALL StoreALine(a$)
END IF
END IF
END SUB
'========================================================================
' General Purpose Subroutines / Library Functions which accompany NET2PRM
'========================================================================
'===========================================
SUB Sort (a$(), B$(), n%) STATIC
'Sort A$, keeping B$ with it.
'------------------------------------------
s% = n% \ 2
DO WHILE s% > 0
FOR I% = s% TO n% - 1
J% = I% - s% + 1
FOR J% = (I% - s% + 1) TO 1 STEP -s%
FOR K% = 0 TO 1
Q = INSTR(a$(J% + K%), "|") - 1
IF Q = -1 THEN Q = LEN(a$(J% + K%))
C$(K%) = LEFT$(a$(J% + K%), Q)
NEXT K%
IF C$(0) <= C$(1) THEN EXIT FOR
SWAP a$(J%), a$(J% + s%)
SWAP B$(J%), B$(J% + s%)
NEXT J%
NEXT I%
s% = s% \ 2
LOOP
END SUB
SUB StoreALine (a$)
'take a line a$ that was removed from the netlist
'and put it back.
'
SHARED queue$
queue$ = a$
END SUB
'=============================
SUB StripQuotes (G$) STATIC
'Remove quotes, if they exist
'----------------------------
IF LEFT$(G$, 1) = CHR$(34) THEN G$ = RIGHT$(G$, LEN(G$) - 1)
IF RIGHT$(G$, 1) = CHR$(34) THEN G$ = LEFT$(G$, LEN(G$) - 1)
END SUB
'=======================================
SUB StuffDefinition (DEFT$, code%) STATIC
'Put a defined set of parms into
'the temporary array, to be
'written to the PRM file
'--------------------------------------
SHARED HIP%
IF DEFT$ = "" THEN
FOR P% = 1 TO HIP%: TMPRM$(P%) = "0": NEXT P%
TMPRM$(0) = PRM$(code%, 0)
ELSE
DEFT$ = COD$(code%) + "/" + DEFT$
CALL DEFPointer(DEFT$, DP%)
FOR P% = 0 TO DFPRM(DP%, 0)
TMPRM$(P%) = STR$(DFPRM(DP%, P%))
NEXT P%
END IF
END SUB
'======================================
SUB StuffMods (MOD$, code%, ECHK%) STATIC
'Modify tmprm parameter array with
'the parameters in mod$
'-------------------------------------
IF MOD$ <> "" THEN
MOD$ = RIGHT$(MOD$, LEN(MOD$) - 1)
DO
CALL GetNextParm(find$, MOD$)
PNAME$ = LEFT$(find$, INSTR(find$, "=") - 1)
CALL PRMPointer(find$, code%, PP%)
IF PP% < 0 AND ECHK% THEN
PRINT "Error in subroutine StuffMods."
PRINT "PNAME$='"; PNAME$; "'"
PRINT "Valid parameter names for "; COD$(code%); " are:"
FOR J% = 1 TO VAL(PRM$(code%, 0))
PRINT J%, PRM$(code%, J%)
IF J% = 20 THEN
PRINT " for more..";
LINE INPUT "", FOO$
END IF
NEXT J%
CALL ErrorCheck(10, -1, "") 'fatal error.
END IF
IF PP% > 0 THEN
IF RIGHT$(find$, 1) = ")" THEN
STUFF$ = LEFT$(find$, LEN(find$) - 1)
ELSE
STUFF$ = find$
END IF
TMPRM$(PP%) = STUFF$
END IF
LOOP WHILE RIGHT$(find$, 1) <> ")"
END IF
END SUB
'==============================================================
SUB TotalConnect (CHAV$, CEXP$, CRET$, cname$, TARG$, SW$, n%) STATIC
'This routine calls all other Connect subs.
'It is also used for .BATCH lookups, as it finds CODE and
'BRANCH numbers, parameter numbers for TARGETS, etc.
'It takes care of connection field format checking, and
'returns all necessary info in CRET$
'-------------------------------------------------------------
'CEXP$ = expected connection type
'CHAV$ = connection found in netlist
'CRET$ = the connection info returned to calling code
'CCD% = the code-number corresponding to the
' item in the connection field.
SHARED count%
n$ = STRING$(n%, "<")
IF n% > 0 THEN
T$ = "Connection " 'called from main prog.
ELSE
T$ = ".BATCH label " 'called from .BATCH processor.
END IF
CALL CodeCount("TRIGR", TRIG%) 'get number of TRIGRs in net.
CALL CodeCount("SPIKE", SPIKE%) 'and number of SPIKEs.
IF CEXP$ = "CMPT" THEN 'CMPT connections
CALL CountSlash(CHAV$, NSL%, SP%)
IF NSL% = 0 THEN CHAV$ = LEFT$(cname$, INSTR(cname$, "/")) + CHAV$
CHAV$ = CHAV$ + "|"
CCD% = 1
CALL MakeConnect(CHAV$, cname$, count%, DP%, CCD%, KC%)
CRET$ = n$ + CEXP$ + "=" + STR$(KC%)
ELSEIF CEXP$ = "SPKFLG" THEN 'SPKFLG connections
IF LEFT$(CHAV$, 4) = "STIM" THEN
HISTIM% = VAL(STIM$(0))
STIM% = 0
WHILE CHAV$ <> STIM$(STIM%)
STIM% = STIM% + 1
IF STIM% > HISTIM% THEN
PRINT CHAV$; " assigned to SPKFLG"; TRIG% + SPIKE% + STIM%
PRINT
STIM$(STIM%) = CHAV$
STIM$(0) = STR$(STIM%)
END IF
WEND
KC% = TRIG% + SPIKE% + STIM%
ELSE
CALL CheckConnect(CHAV$, SW$, CCD%)
IF INSTR(SPKFLG$, COD$(CCD%)) = 0 THEN
m$ = T$ + CHAV$ + " is not a SPKFLG."
CALL ErrorCheck(10, -1, m$)
END IF
CALL FormFullName(CHAV$, SW$, cname$)
CALL MakeConnect(CHAV$, cname$, count%, DP%, CCD%, KC%)
IF COD$(CCD%) = "SPIKE" THEN
REM SPKFLG's are assigned to TRIGR first, then SPIKE.
KC% = KC% + TRIG%
END IF
END IF
CRET$ = n$ + CEXP$ + "=" + STR$(KC%)
ELSEIF CEXP$ = "TARGET" THEN 'Target connections
CALL CountSlash(CHAV$, NSL%, SP%)
CALL GetData(CHAV$, TARG$, NSL% + 1, "/")
CHAV$ = LEFT$(CHAV$, LEN(CHAV$) - LEN(TARG$) - 1)
CALL CheckConnect(CHAV$, SW$, CCD%)
CALL FormFullName(CHAV$, SW$, cname$)
CALL MakeConnect(CHAV$, cname$, count%, DP%, CCD%, KC%)
IF TARG$ = "P" THEN
IF COD$(CCD%) = "POOL" THEN
CRET$ = n$ + CEXP$ + "=" + STR$(KC%) + " XBRN%=0 XPRM%=0"
ELSE
m$ = "Illegal modulation target: P is a reserved word."
CALL ErrorCheck(10, -1, m$)
END IF
ELSE
CALL PRMPointer(TARG$ + "=?", CCD%, PP%)
CALL ErrorCheck(5, PP%, "target " + TARG$)
NONMOD% = 0
FOR J% = 1 TO PP% - 1
J$ = PRM$(CCD%, J%)
IF LEFT$(J$, 1) = "<" OR RIGHT$(J$, 1) = "%" OR INSTR(J$, "=") <> 0 THEN
NONMOD% = NONMOD% + 1
END IF
NEXT J%
PP% = PP% - NONMOD%
CRET$ = n$ + CEXP$ + "=" + STR$(-CCD%) + " XBRN%=" + STR$(KC%) + " XPRM%=" + STR$(PP%)
PRINT TARG$; " is targeted for ";
IF n% > 0 THEN
PRINT "modulation."
ELSE
PRINT "batch file adjustment."
END IF
PRINT
END IF
ELSEIF CEXP$ = "" THEN
REM No Connect
CRET$ = ""
ELSE 'else it must be a regular code
CALL CheckConnect(CHAV$, SW$, CCD%)
CALL FormFullName(CHAV$, SW$, cname$)
CALL MakeConnect(CHAV$, cname$, count%, DP%, CCD%, KC%)
CRET$ = n$ + COD$(CCD%) + "=" + STR$(KC%)
END IF
END SUB
'====================================
SUB Trim (G$) STATIC
'removes leading and trailing spaces
'-----------------------------------
WHILE LEFT$(G$, 1) = " "
G$ = RIGHT$(G$, LEN(G$) - 1)
WEND
WHILE RIGHT$(G$, 1) = " "
G$ = LEFT$(G$, LEN(G$) - 1)
WEND
END SUB
'===================================================================
SUB WriteMaster (MPS%, TITLE$, MIDD$, PRMFILE$, MSTFILE$, MSWITCH%) STATIC
'Writes output to .MST file
'------------------------------------------------------------------
SHARED SHIC%
IF MSWITCH% THEN
PRINT "Writing master file "; TAB(25); MSTFILE$
OPEN "O", 1, MSTFILE$
WRITE #1, TITLE$ 'Title
WRITE #1, MIDD$ 'SYNETSIM format code
FOR I% = 1 TO MPS%
IF MNAME$(I%) = "(TXFLGS)" THEN
FOR J% = 2 TO SHIC%
IF TXFLG$(J%) = "BLOCK" THEN TXFLG$(J%) = "-1"
PRINT #1, TXFLG$(J%)
NEXT J%
ELSEIF MNAME$(I%) = "PRMFILE" THEN
PRINT #1, LEFT$(PRMFILE$, INSTR(PRMFILE$, ".") - 1)
ELSE
PRINT #1, MVAL$(I%)
END IF
NEXT I%
ELSE
PRINT
PRINT "Warning! No .MASTER information found in netlist."
PRINT " No .MST file has been written."; CHR$(7)
PRINT
END IF
CLOSE #1
END SUB
'===============================
SUB WriteToPRMfile (code%) STATIC
'Write a line to .PRM file
'------------------------------
PRINT #1, COD$(code%); 'print code name.
PMS% = VAL(PRM$(code%, 0)) 'number of parameters to output.
'Special case for SYNAPSE with no facilitation
IF COD$(code%) = "SYNAPSE" THEN
CALL PRMPointer("TAUF=?", code%, PP%)
IF VAL(TMPRM$(PP%)) = 0 THEN
PMS% = PP%
END IF
END IF
FOR P% = 1 TO PMS%
a$ = TMPRM$(P%)
CALL Trim(a$)
IF INSTR(a$, "/") <> 0 THEN CALL AddQuotes(a$)
PRINT #1, ","; a$;
NEXT P%
PRINT #1, "" 'CR/LF to start new line.
END SUB
###################################################################