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;;; Various support functions shamelessly stolen from the verilog code and
23;;; reshaped for vhdl. Doing this now saves labour when the implementations
24;;; starts to divert further.
25
26;;; Get port list of top-level Entity
27;;; THHE changed this to the urefs of the I/O-PAD symbols rather than the
28;;; net names. So the uref of the I/O port will become the port name in
29;;; the VHDLport clause.
30
31;;; THHE
32;;;
33;;; Since VHDL know about port directions, pins need a additional attribute.
34;;; The code assumes the attribute "type" (IN, OUT, INOUT) on each pin of a symbol.
35;;; In addition you can add the attribute "width" for a very simple definition of
36;;; busses. (Not complete yet!)
37;;;
38
39(define vhdl:get-top-port-list
40  (lambda ()
41    ;; construct list
42    (list (vhdl:get-matching-urefs "device" "IPAD"  packages)
43	  (vhdl:get-matching-urefs "device" "OPAD"  packages)
44	  (vhdl:get-matching-urefs "device" "IOPAD" packages))))
45
46;;; Get matching urefs
47(define vhdl:get-matching-urefs
48  (lambda (attribute value package-list)
49     (cond ((null? package-list) '())
50          ((string=? (gnetlist:get-package-attribute (car package-list)
51                                                      attribute) value)
52           (cons
53            (cons (car package-list) (gnetlist:get-package-attribute (car package-list) "width"))
54            (vhdl:get-matching-urefs attribute value (cdr package-list))))
55          (else (vhdl:get-matching-urefs attribute value (cdr package-list))))
56
57  )
58)
59
60;;; THHE did not need it anymore
61;
62;(define vhdl:filter
63;  (lambda (attribute value package-list)
64;    (cond ((null? package-list) '())
65;	  ((string=? (gnetlist:get-package-attribute (car package-list)
66;						      attribute) value)
67;	   (cons
68;	    (map (lambda (pin)
69;		   (car (gnetlist:get-nets (car package-list) pin)))
70;		 (pins (car package-list)))
71;	    (vhdl:filter attribute value (cdr package-list))))
72;	  (else (vhdl:filter attribute value (cdr package-list)))))
73;)
74
75;;; Port Clause
76;;;
77;;; According to IEEE 1076-1993 1.1.1:
78;;;
79;;; entity_header :=
80;;;  [ formal_generic_clause ]
81;;;  [ formal_port_clause ]
82;;;
83;;; generic_clause :=
84;;;    GENERIC ( generic_list ) ;
85;;;
86;;; port_clause :=
87;;;    PORT ( port_list ) ;
88;;;
89;;; According to IEEE 1076-1993 1.1.1.2:
90;;;
91;;; port_list := port_interface_list
92;;;
93;;; According to IEEE 1076-1993 4.3.2.1:
94;;;
95;;; interface_list := interface_element { ; interface_element }
96;;;
97;;; interface_element := interface_declaration
98;;;
99;;; According to IEEE 1076-1993 4.3.2:
100;;;
101;;; interface_declaration :=
102;;;    interface_constant_declaration
103;;;  | interface_signal_declaration
104;;;  | interface_variable_declaration
105;;;  | interface_file_declaration
106;;;
107;;; interface_signal_declaration :=
108;;;  [ SIGNAL ] identifier_list : [ mode ] subtype_indication [ BUS ]
109;;;  [ := static_expression ]
110;;;
111;;; mode := IN | OUT | INOUT | BUFFER | LINKAGE
112;;;
113;;; Implementation note:
114;;;    Since the port list must contain signals will only the interface
115;;;    signal declaration of the interface declaration be valid. Further,
116;;;    we may safely assume that the SIGNAL symbol will not be needed.
117;;;    The identifier list is reduced to a signle name entry, mode is set
118;;;    to in, out or inout due to which part of the port list it comes from.
119;;;    The mode types supported are in, out and inout where as buffer and
120;;;    linkage mode is not supported. The subtype indication is currently
121;;;    hardwired to standard logic, but should be controlled by attribute.
122;;;    There is currently no support for busses and thus is the BUS symbol
123;;;    no being applied. Also, there is currently no static expression
124;;;    support, this too may be conveyed using attributes.
125;;;
126
127;;; This little routine writes a single pin on the port clause.
128;;; It assumes a list containing (portname, mode, type) such as
129;;; (CLK in Std_Logic width).
130;;;
131;;; THHE If you added a attribute width=n to a pin or to a I/O-PAD, you get
132;;;      portname : IN Std_Logic_Vector(width-1 downto 0)
133;;;
134(define vhdl:write-port
135  (lambda (port p)
136    (if (not (null? port))
137        (begin
138          (if (string=? (cadddr port) "unknown")
139	    (begin
140	      (display (car port) p)
141	      (display " : " p)
142	      (display (cadr port) p)
143	      (display " " p)
144	      (display (caddr port) p)
145            )
146          )
147          (if (not (string=? (cadddr port) "unknown"))
148	    (begin
149	      (display (car port) p)
150	      (display " : " p)
151	      (display (cadr port) p)
152	      (display " " p)
153	      (display (caddr port) p)
154              (display "_Vector(" p)
155              (display (- (string->number(cadddr port)) 1) p)
156              (display " downto 0)" p)
157            )
158          )
159	)
160    )
161  )
162)
163
164;;; This little routine will actually write the full port clause given a list
165;;; of pins, such as ((CLK in Std_Logic) (D in Std_Logic) (Q out Std_Logic))
166
167(define vhdl:write-port-list
168  (lambda (list p)
169    (if (not (null? list))
170	(begin
171	  (display "    PORT (" p)
172	  (newline p)
173	  (display "        " p)
174	  (vhdl:write-port (car list) p)
175	  (for-each (lambda (pin)
176		      (begin
177			(display ";" p)
178			(newline p)
179			(display "        " p)
180			(vhdl:write-port pin p)
181		      )
182		    )
183		    (cdr list))
184	  (display ");" p)
185	  (newline p)
186	)
187    )
188  )
189)
190
191;;; This is the real thing. It will take a port-list arrangement.
192;;;
193;;; The port-list is a list containing three list:
194;;;  (in-port-list, out-port-list, inout-port-list)
195;;;
196;;; These lists will be transformed into a single list containing the full
197;;; pin information. Currently is this done with hardwired to Std_Logic.
198
199(define vhdl:write-port-clause
200  (lambda (port-list p)
201    (let ((in (car port-list))
202	  (out (cadr port-list))
203	  (inout (caddr port-list)))
204      (vhdl:write-port-list
205        (append
206	  (map (lambda (pin)
207		      (list (car pin) "in" "Std_Logic" (cdr pin))) in)
208	  (map (lambda (pin)
209		      (list (car pin) "out" "Std_Logic" (cdr pin))) out)
210	  (map (lambda (pin)
211		      (list (car pin) "inout" "Std_Logic" (cdr pin))) inout)
212	)
213	p
214      )
215    )
216  )
217)
218
219;;; Primary unit
220;;;
221;;; According to IEEE 1076-1993 11.1:
222;;;
223;;; primary_unit :=
224;;;    entity_declaration
225;;;  | configuration_declaration
226;;;  | package_declaration
227;;;
228;;; Implementation note:
229;;;    We assume that gEDA does not generate either a configuration or
230;;;    package declaration. Thus, only a entity declaration will be generated.
231;;;
232;;; According to IEEE 1076-1993 1.1:
233;;;
234;;; entity_declaration :=
235;;;    ENTITY identifier IS
236;;;       entity_header
237;;;       entity_declarative_part
238;;;  [ BEGIN
239;;;       entity_statement_part ]
240;;;    END [ ENTITY ] [ entity_simple_name ] ;
241;;;
242;;; Implementation note:
243;;;    We assume that no entity declarative part and no entity statement part
244;;;    is to be produced. Further, it is good custom in VHDL-93 to append
245;;;    both the entity keyword as well as the entity simple name to the
246;;;    trailer, therefore this is done to keep VHDL compilers happy.
247;;;
248;;; According to IEEE 1076-1993 1.1.1:
249;;;
250;;; entity_header :=
251;;;  [ formal_generic_clause ]
252;;;  [ formal_port_clause ]
253;;;
254;;; Implementation note:
255;;;    Initially we will assume that there is no generic clause but that there
256;;;    is an port clause. We would very much like to have generic and the port
257;;;    clause should be conditional (consider writting a test-bench).
258;;;
259
260(define vhdl:write-primary-unit
261  (lambda (module-name port-list p)
262    (begin
263      ; Entity header
264      (display "-- Entity declaration" p)
265      (newline p)
266      (newline p)
267      (display "ENTITY " p)
268      (display module-name p)
269      (display " IS" p)
270      (newline p)
271      ; entity_header := [ generic_clause port_clause ]
272      ; Insert generic_clause here when time comes
273      ; port_clause
274      ;;; <DEBUG>
275      ;(newline)
276      ;(display "The schematic contains the following devices:")
277      ;(newline)
278      ;(display unique-devices)
279      ;(newline)
280      ;(newline)
281      ;;; </DEBUG>
282      (vhdl:write-port-clause port-list p)
283      ; entity_declarative_part is assumed not to be used
284      ; entity_statement_part is assumed not to be used
285      ; Entity trailer
286      (display "END " p)
287      (display module-name p)
288      (display ";" p)
289      (newline p)
290      (newline p)
291    )
292  )
293)
294
295;;
296;; Secondary Unit Section
297;;
298
299;;; Component Declaration
300;;;
301;;; According to IEEE 1076-1993 4.5:
302;;;
303;;; component_declaration :=
304;;;    COMPONENT identifier [ IS ]
305;;;     [ local_generic_clause ]
306;;;     [ local_port_clause ]
307;;;    END COMPONENT [ component_simple_name ] ;
308;;;
309;;; Implementation note:
310;;;    The component declaration should match the entity declaration of the
311;;;    same name as the component identifier indicates. Since we do not yeat
312;;;    support the generic clause in the entity declaration we shall not
313;;;    support it here either. We will however support the port clause.
314;;;
315;;;    In the same fassion as before we will use the conditional IS symbol
316;;;    as well as replicating the identifier as component simple name just to
317;;;    be in line with good VHDL-93 practice and keep compilers happy.
318
319(define vhdl:write-component-declarations
320  (lambda (device-list p)
321    (begin
322      ;;; <DEBUG>
323      ;(display "refdes : package : (( IN )( OUT )(INOUT ))")
324      ;(newline)
325      ;(display "========================================")
326      ;(newline)
327      ;;; </DEBUG>
328      (for-each
329        (lambda (device)
330          (begin
331            ; Hmm... I just grabbed this if stuff... do I need it?
332	    (if (not (memv (string->symbol device) ; ignore specials
333	  	           (map string->symbol (list "IOPAD" "IPAD" "OPAD" "HIGH" "LOW"))))
334		(begin
335		     (display "    COMPONENT " p)
336		     (display device p)
337		     ;(display " IS" p)
338		     (newline p)
339		     ; Generic clause should be inserted here
340                     ;;; <DEBUG>
341                     ;(display (find-device packages device))
342                     ;(display " : ")
343                     ;(display device)
344                     ;(display " : ")
345                     ;(display (vhdl:get-device-port-list
346                     ;                    (find-device packages device)
347                     ;         )
348                     ;)
349                     ;(newline)
350                     ;;; </DEBUG>
351                     (vhdl:write-port-clause (vhdl:get-device-port-list
352                                                (find-device packages device))
353                                             p)
354		     (display "    END COMPONENT " p)
355		     (display ";" p)
356		     (newline p)
357		     (newline p)
358                )
359            )
360          )
361        ) device-list
362      )
363    )
364  )
365)
366
367;;; THHE
368;;; Build the port list from the symbols
369;;;
370;;; ... wouldn't it be better to feed get-pins, get-attribute-by-pinnumber and co.
371;;;     with the device rather than the component? pin names and atributes are locked to
372;;;     the symbol and not to the instance of the symbol in the sheet!
373
374(define vhdl:get-device-port-list
375  (lambda (device)
376    ;; construct list
377    (list (vhdl:get-device-matching-pins device (gnetlist:get-pins device) "IN")
378	  (vhdl:get-device-matching-pins device (gnetlist:get-pins device) "OUT")
379	  (vhdl:get-device-matching-pins device (gnetlist:get-pins device) "INOUT")
380    )
381  )
382)
383
384;;; THHE
385;;; get a list of all pins of a given type
386;;;
387
388(define vhdl:get-device-matching-pins
389  (lambda (device pin-list value)
390    (cond ((null? pin-list) '())
391	  ((string=? (gnetlist:get-attribute-by-pinnumber device (car pin-list) "pintype" )
392                     value)
393	   (cons
394            (cons (car pin-list) (gnetlist:get-attribute-by-pinnumber device (car pin-list) "width"))
395	    (vhdl:get-device-matching-pins device (cdr pin-list) value))
396           )
397	  (else (vhdl:get-device-matching-pins device (cdr pin-list) value))
398    )
399  )
400)
401
402;;; THHE
403;;; build a list of all unique devices in in the list
404;;;
405
406(define vhdl:get-unique-devices
407  (lambda (device-list)
408      (cond ((null? device-list) '())
409            ((not (contains? (cdr device-list) (car device-list)))
410             (append (vhdl:get-unique-devices (cdr device-list))
411                     (list (car device-list))))
412            (else (vhdl:get-unique-devices (cdr device-list)))
413      )
414  )
415)
416
417;;; THHE
418;;; build a list of  all unique devices in the schematic
419;;;
420
421(define unique-devices
422  (lambda nil
423    (vhdl:get-unique-devices (map get-device packages))
424))
425
426
427;;; Signal Declaration
428;;;
429;;; According to IEEE 1076-1993 4.3.1.2:
430;;;
431;;; signal_declaration :=
432;;;    SIGNAL identifier_list : subtype_indication [ signal_kind ]
433;;;    [ := expression ] ;
434;;;
435;;; signal_kind := REGISTER | BUS
436;;;
437;;; Implementation note:
438;;;    Currently will the identifier list be reduced to a single entry.
439;;;    There is no support for either register or bus type of signal kind.
440;;;    Further, no default expression is being supported.
441;;;    The subtype indication is hardwired to Std_Logic.
442
443(define vhdl:write-signal-declarations
444  (lambda (p)
445    (begin
446      (for-each
447       (lambda (signal)
448	 (begin
449	   (display "    SIGNAL " p)
450	   (display signal p)
451	   (display " : Std_Logic;" p)
452	   (newline p)
453	 )
454       )
455       all-unique-nets)
456    )
457  )
458)
459
460;;; Architecture Declarative Part
461;;;
462;;; According to IEEE 1076-1993 1.2.1:
463;;;
464;;; architecture_declarative_part :=
465;;;  { block_declarative_item }
466;;;
467;;; block_declarative_item :=
468;;;    subprogram_declaration
469;;;  | subprogram_body
470;;;  | type_declaration
471;;;  | subtype_declaration
472;;;  | constant_declaration
473;;;  | signal_declaration
474;;;  | shared_variable_declaration
475;;;  | file_declaration
476;;;  | alias_declaration
477;;;  | component_declaration
478;;;  | attribute_declaration
479;;;  | attribute_specification
480;;;  | configuration_specification
481;;;  | disconnection_specification
482;;;  | use_clause
483;;;  | group_template_declaration
484;;;  | group_declaration
485;;;
486;;; Implementation note:
487;;;    There is currently no support for programs or procedural handling in
488;;;    gEDA, thus will all declarations above involved in thus activites be
489;;;    left unused. This applies to subprogram declaration, subprogram body,
490;;;    shared variable declaration and file declaration.
491;;;
492;;;    Further, there is currently no support for type handling and therefore
493;;;    will not the type declaration and subtype declaration be used.
494;;;
495;;;    The is currently no support for constants, aliases, configuration
496;;;    and groups so the constant declaration, alias declaration, configuration
497;;;    specification, group template declaration and group declaration will not
498;;;    be used.
499;;;
500;;;    The attribute passing from a gEDA netlist into VHDL attributes must
501;;;    wait, therefore will the attribute declaration and attribute
502;;;    specification not be used.
503;;;
504;;;    The disconnection specification will not be used.
505;;;
506;;;    The use clause will not be used since we pass the responsibility to the
507;;;    primary unit (where it �s not yet supported).
508;;;
509;;;    The signal declation will be used to convey signals held within the
510;;;    architecture.
511;;;
512;;;    The component declaration will be used to convey the declarations of
513;;;    any external entity being used within the architecture.
514
515(define vhdl:write-architecture-declarative-part
516  (lambda (p)
517    (begin
518      ; Due to my taste will the component declarations go first
519      ; XXX - Broken until someday
520      ; THHE fixed today ;-)
521      (vhdl:write-component-declarations (unique-devices) p)
522      ; Then comes the signal declatations
523      (vhdl:write-signal-declarations p)
524    )
525  )
526)
527
528;;; Architecture Statement Part
529;;;
530;;; According to IEEE 1076-1993 1.2.2:
531;;;
532;;; architecture_statement_part :=
533;;;  { concurrent_statement }
534;;;
535;;; According to IEEE 1076-1993 9:
536;;;
537;;; concurrent_statement :=
538;;;    block_statement
539;;;  | process_statement
540;;;  | concurrent_procedure_call_statement
541;;;  | concurrent_assertion_statement
542;;;  | concurrent_signal_assignment_statement
543;;;  | component_instantiation_statement
544;;;  | generate_statement
545;;;
546;;; Implementation note:
547;;;    We currently does not support block statements, process statements,
548;;;    concurrent procedure call statements, concurrent assertion statements,
549;;;    concurrent signal assignment statements or generarte statements.
550;;;
551;;;    Thus, we only support component instantiation statements.
552;;;
553;;; According to IEEE 1076-1993 9.6:
554;;;
555;;; component_instantiation_statement :=
556;;;    instantiation_label : instantiation_unit
557;;;  [ generic_map_aspect ] [ port_map_aspect ] ;
558;;;
559;;; instantiated_unit :=
560;;;    [ COMPONENT ] component_name
561;;;  | ENTITY entity_name [ ( architecture_identifier ) ]
562;;;  | CONFIGURATION configuration_name
563;;;
564;;; Implementation note:
565;;;    Since we are not supporting the generic parameters we will thus not
566;;;    suppport the generic map aspect. We will support the port map aspect.
567;;;
568;;;    Since we do not yeat support the component form we will not yet use
569;;;    the component symbol based instantiated unit.
570;;;
571;;;    Since we do not yeat support configurations we will not support the
572;;;    we will not support the configuration symbol based form.
573;;;
574;;;    This leaves us with the entity form, which we will support initially
575;;;    using only the entity name. The architecture identifier could possibly
576;;;    be supported by attribute value.
577
578(define vhdl:write-architecture-statement-part
579  (lambda (packages p)
580    (begin
581      (display "-- Architecture statement part" p)
582      (newline p)
583      (vhdl:write-component-instantiation-statements packages p)
584      (display "-- Signal assignment part" p)
585      (newline p)
586      (vhdl:write-signal-assignment-statements packages p)
587    )
588  )
589)
590;;; THHE
591;;; write component instantiation for each component in the sheet
592;;;
593
594(define vhdl:write-component-instantiation-statements
595  (lambda (packages p)
596    (for-each (lambda (package)
597      (begin
598        (let ((device (get-device package)))
599          (if (not (memv (string->symbol device)
600                         (map string->symbol
601                                (list "IOPAD" "IPAD" "OPAD"
602                                 "HIGH" "LOW"))))
603            (begin
604              (display "    " p)
605              ; label
606              (display package p)
607              (display " : " p)
608              ; entity name
609              (display (get-device package) p)
610              (newline p)
611              ; Generic map aspect should go in here
612              ; Port map aspect
613              (vhdl:write-port-map package p)
614              (display ";" p)
615              (newline p)
616              (newline p)
617            )
618          )
619        )
620      )
621    )
622    packages)
623  )
624)
625
626;;; THHE
627;;; Write the signal assignment for the top-level ports
628;;; Since I like to have the urefs as port names in the top
629;;; level entity, I have to assign them to the correspinding nets as well
630
631(define vhdl:write-signal-assignment-statements
632  (lambda (packages p)
633    (begin
634      (for-each (lambda (port-ass) (vhdl:write-in-signal-assignment port-ass p))
635        (vhdl:get-top-level-ports packages "IPAD"))
636      (for-each (lambda (port-ass) (vhdl:write-out-signal-assignment port-ass p))
637        (vhdl:get-top-level-ports packages "OPAD"))
638      (for-each (lambda (port-ass) (vhdl:write-inout-signal-assignment port-ass p))
639        (vhdl:get-top-level-ports packages "IOPAD"))
640    )
641  )
642)
643;;; THHE
644;;; get a list of the top-level ports (the urefs of the I/O-PADs)
645
646(define vhdl:get-top-level-ports
647  (lambda (package-list pad-type)
648    (cond ((null? package-list) '())
649          ((string=? (get-device (car package-list)) pad-type)
650           (cons (cons (car package-list)
651                       (cdar (gnetlist:get-pins-nets (car package-list))) )
652                 (vhdl:get-top-level-ports (cdr package-list ) pad-type )))
653           (else (vhdl:get-top-level-ports (cdr package-list ) pad-type ))
654
655    )
656  )
657)
658
659;;;THHE
660(define vhdl:write-in-signal-assignment
661  (lambda (port-assignment p)
662    (begin
663      (display (cdr port-assignment) p)
664      (display " <= " p)
665      (display (car port-assignment) p)
666      (display ";" p)
667      (newline p)
668    )
669  )
670)
671
672;;;THHE
673(define vhdl:write-out-signal-assignment
674  (lambda (port-assignment p)
675    (begin
676      (display (car port-assignment) p)
677      (display " <= " p)
678      (display (cdr port-assignment) p)
679      (display ";" p)
680      (newline p)
681    )
682  )
683)
684
685
686;;;THHE
687(define vhdl:write-inout-signal-assignment
688  (lambda (port-assignment p)
689    (begin
690      (vhdl:write-in-signal-assignment port-assignment p)
691      (vhdl:write-out-signal-assignment port-assignment p)
692    )
693  )
694)
695
696;;; Port map aspect
697;;;
698;;; According to IEEE 1076-1993 5.6.1.2:
699;;;
700;;; port_map_aspect := PORT MAP ( port_association_list )
701;;;
702;;; According to IEEE 1076-1993 4.3.2.2:
703;;;
704;;; association_list :=
705;;;    association_element { , association_element }
706
707(define vhdl:write-port-map
708  (lambda (package p)
709    (begin
710      (let ((pin-list (gnetlist:get-pins-nets package)))
711	(if (not (null? pin-list))
712	    (begin
713	      (display "    PORT MAP (" p)
714	      (newline p)
715	      (display "        " p)
716	      (vhdl:write-association-element (car pin-list) p)
717	      (for-each (lambda (pin)
718			  (display "," p)
719			  (newline p)
720			  (display "        " p)
721			  (vhdl:write-association-element pin p))
722			(cdr pin-list))
723	      (display ")" p)
724	    )
725	)
726      )
727
728    )
729  )
730)
731
732;;; Association element
733;;;
734;;; According to IEEE 1076-1993 4.3.2.2:
735;;;
736;;; association_element :=
737;;;  [ formal_part => ] actual_part
738;;;
739;;; formal_part :=
740;;;    formal_designator
741;;;  | function_name ( formal_designator )
742;;;  | type_mark ( formal_designator )
743;;;
744;;; formal_designator :=
745;;;    generic_name
746;;;  | port_name
747;;;  | parameter_name
748;;;
749;;; actual_part :=
750;;;    actual_designator
751;;;  | function_name ( actual_designator )
752;;;  | type_mark ( actual_designator )
753;;;
754;;; actual_designator :=
755;;;    expression
756;;;  | signal_name
757;;;  | variable_name
758;;;  | file_name
759;;;  | OPEN
760;;;
761;;; Implementation note:
762;;;    In the association element one may have a formal part or relly on
763;;;    positional association. The later is doomed out as bad VHDL practice
764;;;    and thus will the formal part allways be present.
765;;;
766;;;    The formal part will not support either the function name or type mark
767;;;    based forms, thus only the formal designator form is supported.
768;;;
769;;;    Of the formal designator forms will generic name and port name be used
770;;;    as appropriate (this currently means that only port name will be used).
771;;;
772;;;    The actual part will not support either the function name or type mark
773;;;    based forms, thus only the actual designator form is supported.
774
775(define vhdl:write-association-element
776  (lambda (pin p)
777    (begin
778      (display (car pin) p)
779      (display " => " p)
780      (if (strncmp? "unconnected_pin" (cdr pin) 15)
781	  (display "OPEN" p)
782	  (display (cdr pin) p)))))
783
784;;; Secondary unit
785;;;
786;;; According to IEEE 1076-1993 11.1:
787;;;
788;;; secondary_unit :=
789;;;    architecture_body
790;;;  | package_body
791;;;
792;;; Implementation note:
793;;;    Since we are not likely to create packages in gEDA in the near future
794;;;    we will only support the architecture body.
795;;;
796;;; According to IEEE 1076-1993 1.2:
797;;;
798;;; architecture_body :=
799;;;    ARCHITECTURE identifier OF entity_name IS
800;;;       architecture_declarative_part
801;;;    BEGIN
802;;;       architecture_statement_part
803;;;    END [ ARCHITECTURE ] [ architecture_simple_name ] ;
804;;;
805;;; Implementation note:
806;;;    The identifier will identify one of many architectures for an entity.
807;;;    Since we generate only an netlist architecture we will lock this to be
808;;;    "netlist" for the time being. Just as with the entity declaration we
809;;;    will use good VHDL-93 custom to add the architecture keyword as well
810;;;    as the architecture simple name to the trailer to keep compilers happy.
811
812(define vhdl:write-secondary-unit
813  (lambda (module-name p)
814    (display "-- Secondary unit" p)
815    (newline p)
816    (display "ARCHITECTURE netlist OF " p)
817    (display module-name p)
818    (display " IS" p)
819    (newline p)
820    ; architecture_declarative_part
821    (vhdl:write-architecture-declarative-part p)
822    (display "BEGIN" p)
823    (newline p)
824    ; architecture_statement_part
825    (vhdl:write-architecture-statement-part packages p)
826    (display "END netlist;" p)
827    (newline p)
828  )
829)
830
831;;; Top level function
832;;; Write structural VHDL representation of the schematic
833;;;
834(define vhdl
835  (lambda (output-filename)
836    (let ((port (open-output-file output-filename))
837	  (module-name (gnetlist:get-toplevel-attribute "module-name"))
838	  (port-list (vhdl:get-top-port-list)))
839      (begin
840
841;; No longer needed... especially since VHDL isn't a valid mode. :-)
842;;	(gnetlist:set-netlist-mode "VHDL")
843	(display "-- Structural VHDL generated by gnetlist" port)
844	(newline port)
845	; design_file := design_unit { design_unit }
846	; design_unit := context_clause library_unit
847	(vhdl:write-context-clause port)
848	; library_unit := primary_unit secondary_unit
849	(vhdl:write-primary-unit module-name port-list port)
850        (newline port)
851	(vhdl:write-secondary-unit module-name port)
852      )
853      (close-output-port port)
854    )
855  )
856)
857
858;;; Context clause
859;;;
860;;; According to IEEE 1076-1993 11.3:
861;;;
862;;; context_clause := { context_item }
863;;; context_item := library_clause | use_clause
864;;;
865;;; Implementation note:
866;;;    Both library and use clauses will be generated, eventually...
867;;;    What is missing is the information from gEDA itself, i think.
868
869(define vhdl:write-context-clause
870  (lambda (p)
871    (display "-- Context clause" p)
872    (newline p)
873    (display "library IEEE;" p)
874    (newline p)
875    (display "use IEEE.Std_Logic_1164.all;" p)
876    (newline p)
877  )
878)
879
880
881