1;;; gEDA - GPL Electronic Design Automation
2;;; gnetlist - gEDA Netlist
3;;; Copyright (C) 1998-2010 Ales Hvezda
4;;; Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
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,
19;;; MA 02111-1301 USA.
20
21;;; --------------------------------------------------------------------------
22;;;
23;;;  VHDL-AMS netlist backend written by Eduard Moser and Martin Lehmann.
24;;;  Build on the VHDL backend from Magnus Danielson
25;;;
26;;; --------------------------------------------------------------------------
27
28(use-modules (srfi srfi-1))
29
30;;; ===================================================================================
31;;;                  TOP LEVEL FUNCTION
32;;;                        BEGIN
33
34;;;   Write structural VAMS representation of the schematic
35
36;;;   absolutly toplevel function of gEDA gnelist vams mode.
37;;;   its evaluate things like output-file, generate-mode, top-attribs
38;;;   and starts the major subroutines.
39
40;; guile didn't like this code:
41;;
42;; (if (string-index output-filename #\.)
43;;    (string-rindex output-filename #\.)
44;;   ofl)
45;;
46;; as a replacement for line below:
47;;
48;; (lpi (string-rindex output-filename #\. 0 ofl))
49;;
50;; why? (avh)
51
52(define vams
53  (lambda (output-filename)
54    (let* ((port '())                         ;; output-port for architecture
55	   (port-entity '())                  ;; output-port for entity
56	   (ofl (string-length output-filename))
57	   (lpi (string-rindex output-filename #\. 0 ofl))
58
59	   ;; generate correctly architecture name
60	   (architecture (vams:change-all-whitespaces-to-underlines
61			  (cond
62			   ((string=?
63			     (gnetlist:get-toplevel-attribute "architecture")
64			     "not found") "default_architecture")
65			   (else
66			    (gnetlist:get-toplevel-attribute "architecture")))))
67
68	   ;; generate correctly entity name
69	   (entity (vams:change-all-whitespaces-to-underlines
70		    (cond ((string=?
71			    (gnetlist:get-toplevel-attribute "entity")
72			    "not found")
73			   "default_entity")
74			  (else (gnetlist:get-toplevel-attribute "entity")))))
75
76	   ;; search all ports of a schematic. for entity generation only.
77	   (port-list  (vams:generate-port-list (vams:get-uref top-attribs)))
78
79	   ;; search all generic of a schematic. for entity generatin only.
80	   (generic-list (vams:generate-generic-list top-attribs)))
81
82
83      ;; generate-mode : 1 (default) -> generate a architecture (netlist) of a
84      ;;                                schematic
85      ;;                 2           -> is selected a component then generate
86      ;;                                a entity of this, else generate
87      ;;                                a toplevel entity. called from gschem
88      ;;                                normally.
89
90      (cond ((= generate-mode 1)
91	     (begin
92	       (display "\ngenerating architecture of current schematic in ")
93
94	       ;; generate output-filename, like
95	       ;; (<entity>_arc.<output-file-extension>)
96               (set! output-filename
97                (string-append
98                 (if (string-index output-filename #\/)
99                     (substring output-filename 0
100                                (+ (string-rindex
101                                    output-filename #\/ 0 ofl) 1))
102                     "./")
103                 (string-downcase! entity)
104                 "_arc"
105                 (substring output-filename lpi ofl)))
106
107	       (set!  port (open-output-file output-filename))
108	       (display output-filename)
109	       (newline)
110	       (display "-- Structural VAMS generated by gnetlist\n" port)
111	       (vams:write-secondary-unit architecture entity  port)
112	       (close-output-port port)))
113
114	    ((= generate-mode 2)
115	     (display "\n\ngenerating entity of current schematic in ")
116
117	     ;; if one component selected, then generate output-filename
118	     ;; (<device of selected component>.vhdl), else
119	     ;; <entity>.vhdl
120	     (if (not (null? top-attribs))
121		 (set! output-filename
122		       (string-append
123                        (if (string-index output-filename #\/)
124			   (substring output-filename 0
125				   (+ (string-rindex
126				       output-filename #\/ 0 ofl) 1))
127                            "./")
128			(string-downcase!
129			 (get-device (vams:get-uref top-attribs)))
130			".vhdl"))
131		 (set! output-filename
132		       (string-append
133                        (if (string-index output-filename #\/)
134			   (substring output-filename 0
135				   (+ (string-rindex
136				       output-filename #\/ 0 ofl) 1))
137                            "./")
138			(string-downcase! entity)
139			".vhdl")))
140
141	     (display output-filename)
142	     (newline)
143	     (set! port-entity (open-output-file output-filename))
144
145	     ;; decide about the right parameters for entity-declaration
146	     (if (not (null? (vams:get-uref top-attribs)))
147		 (vams:write-primary-unit (get-device (vams:get-uref top-attribs))
148					  port-list
149					  generic-list port-entity)
150		 (vams:write-primary-unit  entity port-list generic-list
151					   port-entity))
152
153	     (close-output-port port-entity))))))
154
155
156;;;                  TOP LEVEL FUNCTION
157;;;                        END
158
159;;; ===================================================================================
160
161;;;
162;;;              ENTITY GENERATING PART
163;;;                     BEGIN
164
165
166;;; Context clause
167;;;
168;;; According to IEEE 1076-1993 11.3:
169;;;
170;;; context_clause := { context_item }
171;;; context_item := library_clause | use_clause
172;;;
173;;; Implementation note:
174;;;    Both library and use clauses will be generated, eventually...
175;;;    What is missing is the information from gEDA itself, i think.
176
177
178;;; writes some needed library insertions staticly
179;;; not really clever, but a first solution
180
181(define vams:write-context-clause
182  (lambda (p)
183    (display "LIBRARY ieee,disciplines;\n" p)
184    (display "USE ieee.math_real.all;\n" p)
185    (display "USE ieee.math_real.all;\n" p)
186    (display "USE work.electrical_system.all;\n" p)
187    (display "USE work.all;\n" p)))
188
189
190
191;;; Primary unit
192;;;
193;;; According to IEEE 1076-1993 11.1:
194;;;
195;;; primary_unit :=
196;;;    entity_declaration
197;;;  | configuration_declaration
198;;;  | package_declaration
199;;;
200;;; Implementation note:
201;;;    We assume that gEDA does not generate either a configuration or
202;;;    package declaration. Thus, only a entity declaration will be generated.
203;;;
204;;; According to IEEE 1076-1993 1.1:
205;;;
206;;; entity_declaration :=
207;;;    ENTITY identifier IS
208;;;       entity_header
209;;;       entity_declarative_part
210;;;  [ BEGIN
211;;;       entity_statement_part ]
212;;;    END [ ENTITY ] [ entity_simple_name ] ;
213;;;
214;;; Implementation note:
215;;;    We assume that no entity declarative part and no entity statement part
216;;;    is to be produced. Further, it is good custom in VAMS-93 to append
217;;;    both the entity keyword as well as the entity simple name to the
218;;;    trailer, therefore this is done to keep VAMS compilers happy.
219;;;
220;;; According to IEEE 1076-1993 1.1.1:
221;;;
222;;; entity_header :=
223;;;  [ formal_generic_clause ]
224;;;  [ formal_port_clause ]
225;;;
226;;; Implementation note:
227;;;    Initially we will assume that there is no generic clause but that there
228;;;    is an port clause. We would very much like to have generic and the port
229;;;    clause should be conditional (consider writting a test-bench).
230
231
232;;; this routine managed the complete entity-declaration of a component
233;;; or a schematic. It requires the entity-name, all ports and generics
234;;; of this entity and the output-port. the output-port defines where
235;;; this all should wrote to.
236
237(define vams:write-primary-unit
238  (lambda (entity port-list generic-list p)
239    (begin
240      (vams:write-context-clause p)
241      (display "-- Entity declaration -- \n\n" p)
242      (display "ENTITY " p)
243      (display entity p)
244      (display " IS\n" p)
245      (vams:write-generic-clause generic-list p)
246      (vams:write-port-clause port-list p)
247      (display "END ENTITY " p)
248      (display entity p)
249      (display "; \n\n" p))))
250
251
252
253;;; GENERIC & PORT Clause
254;;;
255;;; According to IEEE 1076-1993 1.1.1:
256;;;
257;;; entity_header :=
258;;;  [ formal_generic_clause ]
259;;;  [ formal_port_clause ]
260;;;
261;;; generic_clause :=
262;;;    GENERIC ( generic_list ) ;
263;;;
264;;; port_clause :=
265;;;    PORT ( port_list ) ;
266;;;
267;;; According to IEEE 1076-1993 1.1.1.2:
268;;;
269;;; port_list := port_interface_list
270;;;
271;;; According to IEEE 1076-1993 4.3.2.1:
272;;;
273;;; interface_list := interface_element { ; interface_element }
274;;;
275;;; interface_element := interface_declaration
276;;;
277;;; According to IEEE 1076-1993 4.3.2:
278;;;
279;;; interface_declaration :=
280;;;    interface_constant_declaration
281;;;  | interface_signal_declaration
282;;;  | interface_variable_declaration
283;;;  | interface_file_declaration
284;;;
285;;; interface_signal_declaration :=
286;;;  [ SIGNAL ] identifier_list : [ mode ] subtype_indication [ BUS ]
287;;;  [ := static_expression ]
288;;;
289;;; mode := IN | OUT | INOUT | BUFFER | LINKAGE
290;;;
291;;; Implementation note:
292;;;    Since the port list must contain signals will only the interface
293;;;    signal declaration of the interface declaration be valid. Further,
294;;;    we may safely assume that the SIGNAL symbol will not be needed.
295;;;    The identifier list is reduced to a signle name entry, mode is set
296;;;    to in, out or inout due to which part of the port list it comes from.
297;;;    The mode types supported are in, out and inout where as buffer and
298;;;    linkage mode is not supported. The subtype indication is currently
299;;;    hardwired to standard logic, but should be controlled by attribute.
300;;;    There is currently no support for busses and thus is the BUS symbol
301;;;    no being applied. Also, there is currently no static expression
302;;;    support, this too may be conveyed using attributes.
303
304
305;;; this next two functions are writing the generic-clause
306;;; in the entity declaration
307;;; vams:write-generic-clause requires a list of all generics and
308;;; its values, such like ((power 12.2) (velocity 233.34))
309
310(define vams:write-generic-clause
311  (lambda (generic-list p)
312    (if (not (null? generic-list))
313	(begin
314	  (display "\t GENERIC (" p)
315	  (display "\t" p)
316	  (if (= 2 (length (car generic-list)))
317	      (begin
318		(display (caar generic-list) p)
319		(display " : REAL := " p)
320		(display (cadar generic-list) p)))
321	  (vams:write-generic-list (cdr generic-list) p)
322	  (display " );\n" p)))))
323
324(define vams:write-generic-list
325  (lambda (generic-list p)
326    (if (not (null? generic-list))
327	(begin
328	  (display ";\n\t\t\t" p)
329	  (if (= 2 (length (car generic-list)))
330	      (begin
331		(display (caar generic-list) p)
332		(display " : REAL := " p)
333		(display (cadar generic-list) p)))
334	  (vams:write-generic-list (cdr generic-list) p)))))
335
336
337;;; this function writes the port-clause in the entity-declarartion
338;;; It requires a list of ports. ports stand for a list of all
339;;; pin-attributes.
340
341(define vams:write-port-clause
342  (lambda (port-list p)
343    (if (not (null? port-list))
344	(begin
345	  (display "\t PORT (\t" p)
346	  (display "\t" p)
347	  (if (list? (car port-list))
348	      (begin
349		(display (cadar port-list) p)
350		(display " \t" p)
351		(display (caar port-list) p)
352		(display " \t: " p)
353		(if (equal? (cadar port-list) 'quantity)
354		    (display (car (cdddar port-list)) p))
355		(display " \t" p)
356		(display (caddar port-list) p)))
357	  (vams:write-port-list (cdr port-list) p)
358	  (display " );\n" p)))))
359
360;;; This little routine writes a single pin on the port-clause.
361;;; It requires a list containing (port_name, port_object, port_type, port_mode)
362;;; such like
363;;; ((heat quantity thermal in) (base terminal electrical unknown) .. )
364
365(define vams:write-port-list
366  (lambda (port-list p)
367    (if (not (null? port-list))
368	(begin
369	  (display ";\n\t\t\t" p)
370	  (if (equal? (length (car port-list)) 4)
371	      (begin
372		(display (cadar port-list) p)
373		(display " \t" p)
374		(display (caar port-list) p)
375		(display " \t: " p)
376		(if (equal? (cadar port-list) 'quantity)
377		    (display (car (cdddar port-list)) p))
378		(display " \t" p)
379		(display (caddar port-list) p)))
380	  (vams:write-port-list (cdr port-list) p)))))
381
382
383
384;;;              ENTITY GENERATING PART
385;;;                     END
386
387;;; ===================================================================================
388
389;;;           ARCHITECTURE GENERATING PART
390;;;                   BEGIN
391
392
393
394;; Secondary Unit Section
395;;
396
397;;; Architecture Declarative Part
398;;;
399;;; According to IEEE 1076-1993 1.2.1:
400;;;
401;;; architecture_declarative_part :=
402;;;  { block_declarative_item }
403;;;
404;;; block_declarative_item :=
405;;;    subprogram_declaration
406;;;  | subprogram_body
407;;;  | type_declaration
408;;;  | subtype_declaration
409;;;  | constant_declaration
410;;;  | signal_declaration
411;;;  | shared_variable_declaration
412;;;  | file_declaration
413;;;  | alias_declaration
414;;;  | component_declaration
415;;;  | attribute_declaration
416;;;  | attribute_specification
417;;;  | configuration_specification
418;;;  | disconnection_specification
419;;;  | use_clause
420;;;  | group_template_declaration
421;;;  | group_declaration
422;;;
423;;; Implementation note:
424;;;    There is currently no support for programs or procedural handling in
425;;;    gEDA, thus will all declarations above involved in thus activites be
426;;;    left unused. This applies to subprogram declaration, subprogram body,
427;;;    shared variable declaration and file declaration.
428;;;
429;;;    Further, there is currently no support for type handling and therefore
430;;;    will not the type declaration and subtype declaration be used.
431;;;
432;;;    The is currently no support for constants, aliases, configuration
433;;;    and groups so the constant declaration, alias declaration, configuration
434;;;    specification, group template declaration and group declaration will not
435;;;    be used.
436;;;
437;;;    The attribute passing from a gEDA netlist into VAMS attributes must
438;;;    wait, therefore will the attribute declaration and attribute
439;;;    specification not be used.
440;;;
441;;;    The disconnection specification will not be used.
442;;;
443;;;    The use clause will not be used since we pass the responsibility to the
444;;;    primary unit (where it �s not yet supported).
445;;;
446;;;    The signal declation will be used to convey signals held within the
447;;;    architecture.
448;;;
449;;;    The component declaration will be used to convey the declarations of
450;;;    any external entity being used within the architecture.
451
452
453;;; toplevel-subfunction for architecture generation.
454;;; requires architecture and entity name and the port, where
455;;; the architecture should wrote to.
456
457(define vams:write-secondary-unit
458  (lambda (architecture entity p)
459    (display "-- Secondary unit\n\n" p)
460    (display "ARCHITECTURE " p)
461    (display architecture p)
462    (display " OF " p)
463    (display entity p)
464    (display " IS\n" p)
465    (vams:write-architecture-declarative-part p)
466    (display "BEGIN\n" p)
467    (vams:write-architecture-statement-part packages p)
468    (display "END ARCHITECTURE " p)
469    (display architecture p)
470    (display ";\n" p)))
471
472
473;;;
474;;; at this time, it only calls the signal declarations
475
476(define vams:write-architecture-declarative-part
477  (lambda (p)
478    (begin
479      ; Due to my taste will the component declarations go first
480      ; XXX - Broken until someday
481      ; (vams:write-component-declarations packages p)
482      ; Then comes the signal declatations
483      (vams:write-signal-declarations p))))
484
485
486;;; Signal Declaration
487;;;
488;;; According to IEEE 1076-1993 4.3.1.2:
489;;;
490;;; signal_declaration :=
491;;;    SIGNAL identifier_list : subtype_indication [ signal_kind ]
492;;;    [ := expression ] ;
493;;;
494;;; signal_kind := REGISTER | BUS
495;;;
496;;; Implementation note:
497;;;    Currently will the identifier list be reduced to a single entry.
498;;;    There is no support for either register or bus type of signal kind.
499;;;    Further, no default expression is being supported.
500;;;    The subtype indication is hardwired to Std_Logic.
501
502
503;;; the really signal-declaration-writing function
504;;; it's something more complex, because it's checking all signals
505;;; for consistence. it only needs the output-port as parameter.
506
507(define vams:write-signal-declarations
508  (lambda (p)
509    (begin
510      (for-each
511       (lambda (net)
512	 (let*((connlist (gnetlist:get-all-connections net))
513	       (port_object (vams:net-consistence "port_object" connlist))
514	       (port_type (vams:net-consistence "port_type" connlist))
515	       ;;(if (equal? port_object "quantity")
516	       ;;(port_mode (vams:net-consistence 'port_mode connlist)))
517	       )
518	   (if (and port_object
519		    port_type
520		    (if (equal? port_object "quantity")
521			(port_mode (vams:net-consistence 'port_mode connlist))))
522	       (begin
523		 (display "\t" p)
524		 (display port_object p)
525		 (display " " p)
526		 (display net p)
527		 (display " \t: " p)
528		 ;;		 (if (equal? "quantity" (cadr signallist))
529		 ;;		     (display (cadddr signallist) p))
530		 (display " " p)
531		 (display port_type p)
532		 (display ";\n" p))
533	       (begin
534		 (display "-- error in subnet : " p)
535		 (display net p)
536		 (newline p)))))
537       (vams:all-necessary-nets)))))
538
539
540;;; Architecture Statement Part
541;;;
542;;; According to IEEE 1076-1993 1.2.2:
543;;;
544;;; architecture_statement_part :=
545;;;  { concurrent_statement }
546;;;
547;;; According to IEEE 1076-1993 9:
548;;;
549;;; concurrent_statement :=
550;;;    block_statement
551;;;  | process_statement
552;;;  | concurrent_procedure_call_statement
553;;;  | concurrent_assertion_statement
554;;;  | concurrent_signal_assignment_statement
555;;;  | component_instantiation_statement
556;;;  | generate_statement
557;;;
558;;; Implementation note:
559;;;    We currently does not support block statements, process statements,
560;;;    concurrent procedure call statements, concurrent assertion statements,
561;;;    concurrent signal assignment statements or generarte statements.
562;;;
563;;;    Thus, we only support component instantiation statements.
564;;;
565;;; According to IEEE 1076-1993 9.6:
566;;;
567;;; component_instantiation_statement :=
568;;;    instantiation_label : instantiation_unit
569;;;  [ generic_map_aspect ] [ port_map_aspect ] ;
570;;;
571;;; instantiated_unit :=
572;;;    [ COMPONENT ] component_name
573;;;  | ENTITY entity_name [ ( architecture_identifier ) ]
574;;;  | CONFIGURATION configuration_name
575;;;
576;;; Implementation note:
577;;;    Since we are not supporting the generic parameters we will thus not
578;;;    suppport the generic map aspect. We will support the port map aspect.
579;;;
580;;;    Since we do not yeat support the component form we will not yet use
581;;;    the component symbol based instantiated unit.
582;;;
583;;;    Since we do not yeat support configurations we will not support the
584;;;    we will not support the configuration symbol based form.
585;;;
586;;;    This leaves us with the entity form, which we will support initially
587;;;    using only the entity name. The architecture identifier could possibly
588;;;    be supported by attribute value.
589
590;;; Component Declaration
591;;;
592;;; According to IEEE 1076-1993 4.5:
593;;;
594;;; component_declaration :=
595;;;    COMPONENT identifier [ IS ]
596;;;     [ local_generic_clause ]
597;;;     [ local_port_clause ]
598;;;    END COMPONENT [ component_simple_name ] ;
599;;;
600;;; Implementation note:
601;;;    The component declaration should match the entity declaration of the
602;;;    same name as the component identifier indicates. Since we do not yeat
603;;;    support the generic clause in the entity declaration we shall not
604;;;    support it here either. We will however support the port clause.
605;;;
606;;;    In the same fassion as before we will use the conditional IS symbol
607;;;    as well as replicating the identifier as component simple name just to
608;;;    be in line with good VAMS-93 practice and keep compilers happy.
609
610;;; writes the architecture body.
611;;; required all used packages, which are necessary for netlist-
612;;; generation, and the output-port.
613
614(define vams:write-architecture-statement-part
615  (lambda (packages p)
616    (begin
617      (display "-- Architecture statement part" p)
618      (newline p)
619      (for-each (lambda (package)
620		  (begin
621		    (let ((device (get-device package))
622			  (architecture
623			   (gnetlist:get-package-attribute
624			    package
625			    "architecture")))
626		      (if (not (memv (string->symbol device)
627				     (map string->symbol
628					  (list "IOPAD" "IPAD" "OPAD" "HIGH" "LOW"))))
629			  (begin
630			    (display " \n  " p)
631
632			    ;; writes instance-label
633			    (display package p)
634			    (display " : ENTITY " p)
635
636			    ;; writes entity name, which should instanciated
637			    (display (get-device package) p)
638
639			    ;; write the architecture of an entity in brackets after
640			    ;; the entity, when necessary.
641			    (if (not (equal? architecture "unknown"))
642				(begin
643				  (display "(" p)
644				  (if (equal?
645				       (string-ref
646					(gnetlist:get-package-attribute package
647									"architecture") 0)
648				       #\?)
649				      (display (substring architecture 1) p)
650				      (display architecture p))
651				  (display ")" p)))
652			    (newline p)
653
654			    ;; writes generic map
655			    (vams:write-generic-map p package)
656
657			    ;; writes port map
658			    (vams:write-port-map package p)
659
660			    (display ";\n" p))))))
661		(vams:all-necessary-packages)))))
662
663
664
665;; Given a uref, prints all generics attribute => values, without some
666;; special attribs, like uref,source and architecture.
667;; Don't ask why .... it's not the right place to discuss this.
668;; requires the output-port and a uref
669
670(define vams:write-generic-map
671  (lambda (port uref)
672    (let ((new-ls (vams:all-used-generics
673		   (vams:list-without-str-attrib
674		    (vams:list-without-str-attrib
675		     (vams:list-without-str-attrib
676		      (gnetlist:vams-get-package-attributes uref)
677		      "refdes") "source") "architecture") uref)))
678      (if (not (null? new-ls))
679	  (begin
680	    (display "\tGENERIC MAP (\n" port)
681	    (vams:write-component-attributes port uref new-ls)
682	    (display ")\n" port))))))
683
684
685
686;;; Port map aspect
687;;;
688;;; According to IEEE 1076-1993 5.6.1.2:
689;;;
690;;; port_map_aspect := PORT MAP ( port_association_list )
691;;;
692;;; According to IEEE 1076-1993 4.3.2.2:
693;;;
694;;; association_list :=
695;;;    association_element { , association_element }
696
697;;; writes the port map of the component.
698;;; required output-port and uref.
699
700(define vams:write-port-map
701  (lambda (uref p)
702    (begin
703      (let ((pin-list (gnetlist:get-pins-nets uref)))
704	(if (not (null? pin-list))
705	    (begin
706	      (display "\tPORT MAP (\t" p)
707	      (vams:write-association-element (car pin-list) p)
708	      (for-each (lambda (pin)
709			  (display ",\n" p)
710			  (display "\t\t\t" p)
711			  (vams:write-association-element pin p))
712			(cdr pin-list))
713	      (display ")" p)))))))
714
715
716;;; Association element
717;;;
718;;; According to IEEE 1076-1993 4.3.2.2:
719;;;
720;;; association_element :=
721;;;  [ formal_part => ] actual_part
722;;;
723;;; formal_part :=
724;;;    formal_designator
725;;;  | function_name ( formal_designator )
726;;;  | type_mark ( formal_designator )
727;;;
728;;; formal_designator :=
729;;;    generic_name
730;;;  | port_name
731;;;  | parameter_name
732;;;
733;;; actual_part :=
734;;;    actual_designator
735;;;  | function_name ( actual_designator )
736;;;  | type_mark ( actual_designator )
737;;;
738;;; actual_designator :=
739;;;    expression
740;;;  | signal_name
741;;;  | variable_name
742;;;  | file_name
743;;;  | OPEN
744;;;
745;;; Implementation note:
746;;;    In the association element one may have a formal part or relly on
747;;;    positional association. The later is doomed out as bad VAMS practice
748;;;    and thus will the formal part allways be present.
749;;;
750;;;    The formal part will not support either the function name or type mark
751;;;    based forms, thus only the formal designator form is supported.
752;;;
753;;;    Of the formal designator forms will generic name and port name be used
754;;;    as appropriate (this currently means that only port name will be used).
755;;;
756;;;    The actual part will not support either the function name or type mark
757;;;    based forms, thus only the actual designator form is supported.
758
759
760;;; the purpose of this function is very easy: write OPEN if pin
761;;; unconnected and normal output if it connected.
762
763(define vams:write-association-element
764  (lambda (pin p)
765    (begin
766      (display (car pin) p)
767      (display " => " p)
768      (if (strncmp? (cdr pin) "unconnected_pin" 15)
769	  (display "OPEN" p)
770	  (display (vams:port-test pin) p)))))
771
772
773
774;;; writes all generics of a component into the
775;;; generic map. needs components uref, the generic-list and
776;;; an output-port
777
778(define vams:write-component-attributes
779 (lambda (port uref generic-list)
780   (if (not (null? generic-list))
781       (let ((attrib (car generic-list))
782	     (value (gnetlist:get-package-attribute uref (car generic-list))))
783	 (begin
784
785	   (if (string=? value "unknown")
786	     (vams:write-component-attributes port uref (cdr generic-list))
787	     (begin
788	       (display "\t\t\t" port)
789	       (display attrib port)
790	       (display " => " port)
791	       (display value port)
792	       (vams:write-component-attributes-helper port uref (cdr generic-list)))))))))
793
794(define vams:write-component-attributes-helper
795 (lambda (port uref generic-list)
796   (if (not (null? generic-list))
797       (let ((attrib (car generic-list))
798	     (value (gnetlist:get-package-attribute uref (car generic-list))))
799	 (begin
800
801	   (if (not (string=? value "unknown"))
802	     (begin
803               (display ", " port)
804               (newline port)
805	       (display "\t\t\t" port)
806	       (display attrib port)
807	       (display " => " port)
808	       (display value port)
809	       (vams:write-component-attributes-helper port uref (cdr generic-list)))))))))
810
811
812;;;           ARCHITECTURE GENERATING PART
813;;;                       END
814
815;;; ===================================================================================
816
817;;;
818;;;           REALLY IMPORTANT HELP FUNCTIONS
819
820
821;;; returns a list, whitout the specified string.
822;;; requires: a list and a string
823
824(define vams:list-without-str-attrib
825  (lambda (ls str)
826    (cond ((null? ls) '())
827	  (else
828	   (append
829	    (cond ((string=? (car ls) str) '())
830		  (else (list (car ls))))
831	    (vams:list-without-str-attrib (cdr ls) str))))))
832
833
834
835;; returns all not default-setted generics
836;; After our definitions, all attribs, which values not started with a
837;; '?' - character.
838
839(define vams:all-used-generics
840  (lambda (ls uref)
841    (begin
842      (if (null? ls)
843	  '()
844	  (append
845	   (if (equal? (string-ref (gnetlist:get-package-attribute uref (car ls)) 0) #\?)
846	       '()
847	       (list (car ls)))
848	   (vams:all-used-generics (cdr ls) uref))))))
849
850
851
852;; checks all pins of a net for consistence, under different points
853;; of view (pin-attributes).
854;; requires: a pin-attribute and the subnet
855
856(define vams:net-consistence
857  (lambda (attribute connlist)
858    (begin
859      (if (equal? connlist '())
860	  #f
861	  (if (= (length connlist) 1)
862	      (if (equal? attribute 'port_mode)
863		  (if (equal? (gnetlist:get-attribute-by-pinnumber (car (car connlist))
864							  (car (cdr (car connlist)))
865							  attribute)
866			      'out)
867		      #t
868		      #f)
869		  (append (gnetlist:get-attribute-by-pinnumber (car (car connlist))
870						      (car (cdr (car connlist)))
871						      attribute)))
872	      (if (equal? attribute 'port_mode)
873		  (if (equal? (gnetlist:get-attribute-by-pinnumber (car (car connlist))
874							  (car (cdr (car connlist)))
875							  attribute)
876			      'out)
877		      #t
878		      (vams:net-consistence attribute (cdr connlist)))
879		  (if (equal? (gnetlist:get-attribute-by-pinnumber (car (car connlist))
880							  (car (cdr (car connlist)))
881							  attribute)
882			      (vams:net-consistence attribute (cdr connlist)))
883		      (append (gnetlist:get-attribute-by-pinnumber (car (car connlist))
884							  (car (cdr (car connlist)))
885							  attribute))
886		      #f)))))))
887
888
889
890;; returns a string, where are all whitespaces replaced to underlines
891;; requires: a string only
892
893(define vams:change-all-whitespaces-to-underlines
894  (lambda (str)
895    (begin
896      (if (string-index str #\ )
897	  (begin
898	    (if (= (string-index str #\ ) (- (string-length str) 1))
899		(vams:change-all-whitespaces-to-underlines
900		 (substring str 0 (- (string-length str) 1)))
901		(begin
902		  (string-set! str (string-index str #\ ) #\_ )
903		  (vams:change-all-whitespaces-to-underlines str))))
904	  (append str)))))
905
906
907
908;; returns all nets, which a given list of pins are conneted to.
909;; requires: uref and its pins
910
911(define vams:all-pins-nets
912  (lambda (uref pins)
913    (if (null? pins)
914	'()
915	(append (list (car (gnetlist:get-nets uref (car pins))))
916		(vams:all-pins-nets uref (cdr pins))))))
917
918
919
920;; returns all nets, which a given list of urefs are connetd to
921;; requires: list of urefs :-)
922
923(define vams:all-packages-nets
924  (lambda (urefs)
925    (if (null? urefs)
926	'()
927	(append
928	 (vams:all-pins-nets (car urefs)
929			     (gnetlist:get-pins (car urefs)))
930	 (vams:all-packages-nets (cdr urefs))))))
931
932
933
934;; returns all ports from a list of urefs.
935;; important for hierachical netlists. in our definition ports are
936;; special components, which device-attributes a setted to "PORT".
937;; The port-attributes are saved on toplevel of this special component.
938;; requires: list of urefs
939
940(define vams:all-ports-in-list
941  (lambda (urefs)
942    (begin
943      (if (null? urefs)
944	  '()
945	  (append
946	   (if (equal? "PORT" (get-device (car urefs)))
947	       (list (car urefs))
948	       '())
949	   (vams:all-ports-in-list (cdr urefs)))))))
950
951
952
953;; returns all nets in the schematic, which not
954;; directly connected to a port.
955
956(define vams:all-necessary-nets
957  (lambda ()
958    (vams:only-different-nets all-unique-nets
959			      (vams:all-packages-nets
960			       (vams:all-ports-in-list packages)))))
961
962
963
964;; returns all elements from ls, that are not in without-ls.
965;; a simple list function.
966(define (vams:only-different-nets ls without-ls)
967  (lset-difference equal? ls without-ls))
968
969
970;; sort all port-components out
971
972(define vams:all-necessary-packages
973  (lambda ()
974    (vams:only-different-nets packages
975			      (vams:all-ports-in-list packages))))
976
977
978
979;; if pin connetected to a port (special component), then return port.
980;; else return the net, which the pin is connetcted to.
981;; requires: a pin only
982
983(define vams:port-test
984  (lambda (pin)
985    (if (member (cdr pin)
986		(vams:all-packages-nets (vams:all-ports-in-list packages)))
987	(append (vams:which-port
988		 pin
989		 (vams:all-ports-in-list packages)))
990	(append (cdr pin)))))
991
992
993
994;; returns the port, when is in port-list, which the pin is connected to
995;; requires: a pin and a port-list
996
997(define vams:which-port
998  (lambda (pin ports)
999    (begin
1000       (if (null? ports)
1001	  '()
1002	  (if (equal? (cdr pin)
1003		      (car (gnetlist:get-nets
1004		       (car ports)
1005		       (car (gnetlist:get-pins (car ports))))))
1006	      (append (car ports))
1007	      (append
1008	       (vams:which-port pin (cdr ports))))))))
1009
1010
1011
1012;; generate generic list for generic clause
1013;;((generic value) (generic value) .. ())
1014
1015(define vams:generate-generic-list
1016  (lambda (ls)
1017    (if (null? ls)
1018	'()
1019	(append
1020	 (if (not (or (string-prefix=? "refdes=" (car ls))
1021		      (string-prefix=? "source=" (car ls))
1022		      (string-prefix=? "architecture=" (car ls))))
1023	     (list
1024	      (if (string-index (car ls) #\=)
1025		  (list
1026		   (substring (car ls) 0 (string-rindex (car ls) #\= 0))
1027		   (substring (car ls) (+ (string-rindex (car ls) #\= 0)
1028					  (if (equal? (string-ref
1029						       (car ls)
1030						       (1+ (string-rindex (car ls) #\= 0)))
1031						       #\?)
1032					      2 1))
1033			      (string-length (car ls))))
1034		  (car ls)))
1035	     '())
1036	 (vams:generate-generic-list (cdr ls))))))
1037
1038
1039
1040;;; generates a port list of the current schematic, or returns
1041;;; a empty list, if no port reachable.
1042
1043(define vams:generate-port-list
1044  (lambda (uref)
1045    (let ((port-list  (list '())))
1046      (if (null? uref)
1047	  '()
1048	  (begin
1049	    (for-each (lambda (pin)
1050			(append! port-list
1051				 (list (list pin
1052					     (gnetlist:get-attribute-by-pinnnumber uref pin "port_object")
1053					     (gnetlist:get-attribute-by-pinnumber uref pin "port_type")
1054					     (gnetlist:get-attribute-by-pinnumber uref pin "port_mode")))))
1055		      (gnetlist:get-pins uref))
1056	    (append (cdr port-list)))))))
1057
1058
1059
1060;;; gets the uref value from the top-attribs-list, which is assigned from gschem.
1061;;; only important for automatic-gnetlist-calls from gschem !!!
1062
1063(define vams:get-uref
1064  (lambda (liste)
1065    (begin
1066      (if (null? liste)
1067	  '()
1068	  (if (string-prefix=? "refdes=" (symbol->string (car liste)))
1069	      (begin
1070		(append (substring (car liste) 5
1071				   (string-length (car liste)))))
1072	      (vams:get-uref (cdr liste)))))))
1073
1074
1075;;; set generate-mode to default (1), when not defined before.
1076(define generate-mode (if (defined? 'generate-mode) generate-mode '1))
1077
1078
1079;;; set to-attribs list empty, when not needed.
1080(define top-attribs (if (defined? 'top-attribs) top-attribs '()))
1081
1082(display "loaded gnet-vams.scm\n")
1083
1084