1;;; Lepton EDA netlister 2;;; Copyright (C) 2003, 2005-2010 Dan McMahill 3;;; Copyright (C) 2003-2017 gEDA Contributors 4;;; Copyright (C) 2018-2020 Lepton EDA Contributors 5;;; 6;;; This program is free software; you can redistribute it and/or modify 7;;; it under the terms of the GNU General Public License as published by 8;;; the Free Software Foundation; either version 2 of the License, or 9;;; (at your option) any later version. 10;;; 11;;; This program is distributed in the hope that it will be useful, 12;;; but WITHOUT ANY WARRANTY; without even the implied warranty of 13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14;;; GNU General Public License for more details. 15;;; 16;;; You should have received a copy of the GNU General Public License 17;;; along with this program; if not, write to the Free Software 18;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 20;; -------------------------------------------------------------------------- 21;; This is gnetlist backend for the SWITCAP switched capacitor 22;; simulator. This backend was written by Dan McMahill 23;; 'mcmahill at alum dot mit dotedu' who used the SPICE backend by 24;; S. Gieltjes as a starting point. 25 26;; The following is needed to make guile 1.8.x happy. 27(use-modules (ice-9 rdelim) 28 (netlist error) 29 (netlist schematic) 30 (netlist schematic toplevel)) 31 32;; ---------------------------------------------------------------------------- 33;; Utility functions used by this netlister 34;; ---------------------------------------------------------------------------- 35 36;; This procedure takes a net name as determined by gnetlist and 37;; modifies it to be a valid SWITCAP net name. 38;; 39(define switcap:map-net-names 40 (lambda (net-name) 41 (let ((rx (make-regexp "^unnamed_net")) 42 (net-alias net-name) 43 ) 44 ;; XXX we should use a dynamic regexp based on the current value 45 ;; for the unnamed net base string. 46 47 (cond 48 ;; Change "GND" to "0" 49 ((string=? net-name "GND") (set! net-alias "0")) 50 ;; remove the 'unnamed_net' part 51 ((regexp-exec rx net-name) (set! net-alias (substring net-name 11))) 52 (else net-name) 53 ) 54 55 ;; Truncate to 7 characters 56 (if (> (string-length net-alias) 7) 57 (set! net-alias (substring net-alias 0 7)) 58 ) 59 ;; Convert to all upper case 60 (string-upcase net-alias) 61 62 ) 63 ) 64 ) 65 66;; This procedure takes a refdes as determined by gnetlist and 67;; modifies it to be a valid SWITCAP refdes. In particular, 68;; we need to make sure that 69;; 70;; - the first character is correct for the component type 71;; 72;; - we do not exceed 8 characters. Note the 8 comes from 73;; the first character which denotes component type plus 74;; 7 for the unique identifier part. 75;; 76;; - we are all caps (switcap is not case sensitive) 77;; 78(define switcap:map-refdes 79 (lambda (refdes) 80 (let ((refdes-alias refdes) 81 ) 82 83 ;; Convert to all upper case 84 (string-upcase refdes-alias) 85 86 ;; Make sure the first character is correct for 87 ;; this component type 88 (cond 89 ( (string=? (get-device refdes) "SWITCAP-switch") 90 (if (not (string=? (substring refdes-alias 0 1) "S")) 91 (set! refdes-alias (string-append "S" refdes-alias)))) 92 93 ( (string=? (get-device refdes) "SWITCAP-capacitor") 94 (if (not (string=? (substring refdes-alias 0 1) "C")) 95 (set! refdes-alias (string-append "C" refdes-alias)))) 96 97 ( (string=? (get-device refdes) "SWITCAP-vcvs") 98 (if (not (string=? (substring refdes-alias 0 1) "E")) 99 (set! refdes-alias (string-append "E" refdes-alias)))) 100 101 ( (string=? (get-device refdes) "SWITCAP-vsrc") 102 (if (not (string=? (substring refdes-alias 0 1) "V")) 103 (set! refdes-alias (string-append "V" refdes-alias)))) 104 105 ) 106 107 ;; Truncate to 8 characters (1 for the first character and 108 ;; 7 for the identifier) 109 (if (> (string-length refdes-alias) 8) 110 (set! refdes-alias (substring refdes-alias 0 8)) 111 ) 112 113 ;; set to #t for debugging 114 (if #f 115 (let () 116 (display "(switcap:map-refdes ") 117 (display refdes) 118 (display ") ===> " ) 119 (display refdes-alias ) 120 (display "\n") 121 ) 122 ) 123 124 refdes-alias 125 ) 126 ) 127 ) 128 129;; 130;; Given a reference designator and pin number 131;; write out the net name 132;; 133(define switcap:write-pin-net 134 (lambda (package pin) 135 (display (gnetlist:alias-net (pin-netname package pin))) 136 ) 137 ) 138 139;; 140;; Given a reference designator and attribute name 141;; write out the attribute with warnings if the attribute has 142;; not been set 143;; 144(define switcap:write-attrib 145 (lambda (package attrib) 146 (let ((val (gnetlist:get-package-attribute package attrib))) 147 (if (string=? val "unknown") 148 (begin 149 (display "*** WARNING ***\n") 150 (display "Required attribute \"") 151 (display attrib) 152 (display "\" is not set on component \"") 153 (display package) 154 (display "\". Please correct this.\n\n") 155 )) 156 (display val) 157 val 158 ))) 159 160;; ---------------------------------------------------------------------------- 161;; Individual component netlist functions 162;; ---------------------------------------------------------------------------- 163 164;; 165;; capacitor 166;; 167;; Form is: 168;; 169;; C### (N1 N2) value; 170;; 171;; 172(define switcap:write-cap 173 (lambda (package) 174 ( begin 175 ;; Write out the refdes 176 (display " ") 177 (display (gnetlist:alias-refdes package)) 178 (display " ") 179 180 ;; Write out the nodes 181 ;; Write out the nodes 182 (display "(") 183 (switcap:write-pin-net package "1") 184 (display " ") 185 (switcap:write-pin-net package "2") 186 (display ") ") 187 188 ;; Write the value 189 (switcap:write-attrib package "value") 190 191 ;; finish the line 192 (display ";\n") 193 ))) 194 195;; 196;; switch 197;; 198;; Form is: 199;; 200;; S### (N1 N2) clk; 201;; 202;; 203(define switcap:write-switch 204 (lambda (package) 205 ( begin 206 ;; Write out the refdes 207 (display " ") 208 (display (gnetlist:alias-refdes package)) 209 (display " ") 210 211 ;; Write out the nodes 212 (display "(") 213 (switcap:write-pin-net package "1") 214 (display " ") 215 (switcap:write-pin-net package "2") 216 (display ") ") 217 218 ;; Write the clock 219 (switcap:write-attrib package "clock") 220 221 ;; finish the line 222 (display ";\n") 223 ))) 224 225;; 226;; voltage controlled voltage source 227;; 228;; Form is: 229;; 230;; E### (OUTP OUTM INP INM) gain; 231;; 232;; 233(define switcap:write-vcvs 234 (lambda (package) 235 ( begin 236 ;; Write out the refdes 237 (display " ") 238 (display (gnetlist:alias-refdes package)) 239 (display " ") 240 241 ;; Write out the nodes 242 (display "(") 243 (switcap:write-pin-net package "1") 244 (display " ") 245 (switcap:write-pin-net package "2") 246 (display " ") 247 (switcap:write-pin-net package "3") 248 (display " ") 249 (switcap:write-pin-net package "4") 250 (display ") ") 251 252 ;; Write the clock 253 (switcap:write-attrib package "gain") 254 255 ;; finish the line 256 (display ";\n") 257 ))) 258 259;; 260;; voltage source 261;; 262;; Form is: 263;; 264;; V### (OUTP OUTM); 265;; 266;; 267(define switcap:write-vsrc 268 (lambda (package) 269 ( begin 270 ;; Write out the refdes 271 (display " ") 272 (display (gnetlist:alias-refdes package)) 273 (display " ") 274 275 ;; Write out the nodes 276 (display "(") 277 (switcap:write-pin-net package "1") 278 (display " ") 279 (switcap:write-pin-net package "2") 280 (display ")") 281 282 ;; finish the line 283 (display ";\n") 284 ))) 285 286;; 287;; Timing block -- clock definition 288;; 289;; Form is: 290;; 291;; CLOCK clock_name period (phi_start phi_stop) 292;; 293;; 294(define switcap:write-clock 295 (lambda (package) 296 ( begin 297 (display " CLOCK ") 298 (display (string-append package " ")) 299 (switcap:write-attrib package "PERIOD") 300 (display " (") 301 (switcap:write-attrib package "PSTART") 302 (display " ") 303 (switcap:write-attrib package "PSTOP") 304 (display ");\n") 305 ))) 306 307;; 308;; Timing block -- master clock period 309;; 310;; Form is: 311;; 312;; PERIOD clock_period; 313;; 314;; 315(define switcap:write-timing 316 (lambda (package) 317 ( begin 318 (display " PERIOD ") 319 (switcap:write-attrib package "PERIOD") 320 321 ;; finish the line 322 (display ";\n") 323 ))) 324 325;; 326;; Title 327;; 328;; Form is: 329;; 330;; TITLE: my title; 331;; 332;; Can only have 64 characters in the title 333;; XXX - need to truncate to 64 chars 334(define switcap:write-title 335 (lambda (package) 336 ( begin 337 (display "TITLE:") 338 (switcap:write-attrib package "TITLE") 339 340 ;; finish the line 341 (display ";\n\n") 342 ))) 343 344;; 345;; Options 346;; 347;; Form is: 348;; 349;; OPTIONS; OPT1; OPT2; ...; END; 350;; 351;; valid options are: 352;; WIDTH132 353;; NOLIST 354;; REPORT 355;; NOOVRLAY 356;; GRID 357(define switcap:write-options 358 (lambda (package) 359 ( begin 360 (display "OPTIONS; ") 361 (switcap:write-attrib package "OPTIONS") 362 363 ;; finish the line 364 (display " END;\n\n") 365 ))) 366 367;; 368;; Analysis block 369;; 370;; For now, we only support writing the analysis blocks in a file 371;; and including that via a switcap-analysis-1.sym instantiation 372;; 373(define switcap:write-analysis 374 (lambda (package) 375 (display "/* reading analysis from \"") 376 (let ((fname (switcap:write-attrib package "file"))) 377 (display "\" */\n") 378 (if (file-exists? fname) 379 (switcap:cat-file (open-input-file fname) (current-output-port)) 380 (netlist-error 1 "ERROR: Analysis file ~S not found.\n" fname))))) 381 382(define switcap:cat-file 383 (lambda (ip op) 384 (define line "") 385 (set! line (read-line ip)) 386 (if (not (eof-object? line)) 387 (begin 388 (write-line line op) 389 (switcap:cat-file ip op) 390 ) 391 (close-port ip)) 392 )) 393 394;; ---------------------------------------------------------------------------- 395;; Netlist functions for each of the blocks in the switcap netlist 396;; ---------------------------------------------------------------------------- 397 398 399;; 400;; Switcap netlist header 401;; 402(define switcap:write-top-header 403 (lambda () 404 (display "/* Switcap netlist produced by lepton-netlist (part of Lepton EDA) */\n") 405 (display "/* See http://www.geda-project.org/ for more information. */\n") 406 (display "/* Switcap backend written by Dan McMahill */\n") 407 (display "\n\n") 408 ) 409 ) 410 411;; 412;; The main TITLE and OPTIONS block dispatcher 413;; 414(define switcap:write-title-block 415 (lambda (ls) 416 (if (not (null? ls)) 417 (let ((package (car ls))) 418 (cond 419 ( (string=? (get-device package) "SWITCAP-options") 420 (switcap:write-options package)) 421 ( (string=? (get-device package) "SWITCAP-title") 422 (switcap:write-title package)) 423 ) 424 (switcap:write-title-block (cdr ls)) )))) 425 426;; 427;; The main TIMING block dispatcher 428;; 429(define switcap:write-timing-block 430 (lambda (ls) 431 (if (not (null? ls)) 432 (let ((package (car ls))) 433 (cond 434 ( (string=? (get-device package) "SWITCAP-clock") 435 (switcap:write-clock package)) 436 ( (string=? (get-device package) "SWITCAP-timing") 437 (switcap:write-timing package)) 438 ) 439 (switcap:write-timing-block (cdr ls)) )))) 440 441;; 442;; The main CIRCUIT block netlist dispatcher. 443;; 444(define switcap:write-netlist 445 (lambda (ls) 446 (if (not (null? ls)) 447 (let ((package (car ls))) 448 (cond 449 ( (string=? (get-device package) "SWITCAP-switch") 450 (switcap:write-switch package)) 451 ( (string=? (get-device package) "SWITCAP-capacitor") 452 (switcap:write-cap package)) 453 ( (string=? (get-device package) "SWITCAP-vcvs") 454 (switcap:write-vcvs package)) 455 ( (string=? (get-device package) "SWITCAP-vsrc") 456 (switcap:write-vsrc package)) 457 ) 458 (switcap:write-netlist (cdr ls)) )))) 459 460;; 461;; The main ANALYSIS block dispatcher 462;; 463(define switcap:write-analysis-block 464 (lambda (ls) 465 (if (not (null? ls)) 466 (let ((package (car ls))) 467 (cond 468 ( (string=? (get-device package) "SWITCAP-analysis") 469 (switcap:write-analysis package)) 470 ) 471 (switcap:write-analysis-block (cdr ls)) )))) 472 473 474;; ---------------------------------------------------------------------------- 475;; Switcap netlist generation -- top level 476;; ---------------------------------------------------------------------------- 477(define (switcap output-filename) 478 (let ((nets (schematic-nets (toplevel-schematic))) 479 (packages (schematic-package-names (toplevel-schematic)))) 480 481 ;; initialize the net-name aliasing 482 (gnetlist:build-net-aliases switcap:map-net-names nets) 483 484 ;; initialize the refdes aliasing 485 (gnetlist:build-refdes-aliases switcap:map-refdes packages) 486 487 (switcap:write-top-header) 488 (switcap:write-title-block packages) 489 (display "TIMING;\n") 490 (switcap:write-timing-block packages) 491 (display "END;\n\n") 492 (display "CIRCUIT;\n") 493 (switcap:write-netlist packages) 494 (display "END;\n\n") 495 (switcap:write-analysis-block packages) 496 (display "\n\n/* End of SWITCAP netlist */\n") 497 (display "END;\n"))) 498 499 500;; -------------------------------------------------------------------------- 501