Avoid GNUism '\|' by using extended REs.
[geda-gaf.git] / gnetlist-legacy / scheme / gnet-vhdl.scm
blobbb3fed6985847ce76e55905286fabcf43cadf0c7
1 ;;; gEDA - GPL Electronic Design Automation
2 ;;; gnetlist - gEDA Netlist
3 ;;; Copyright (C) 1998-2010 Ales Hvezda
4 ;;; Copyright (C) 1998-2020 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.
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.
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.
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 ;;;
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))))
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))))
57   )
60 ;;; Port Clause
61 ;;;
62 ;;; According to IEEE 1076-1993 1.1.1:
63 ;;;
64 ;;; entity_header :=
65 ;;;  [ formal_generic_clause ]
66 ;;;  [ formal_port_clause ]
67 ;;;
68 ;;; generic_clause :=
69 ;;;    GENERIC ( generic_list ) ;
70 ;;;
71 ;;; port_clause :=
72 ;;;    PORT ( port_list ) ;
73 ;;;
74 ;;; According to IEEE 1076-1993 1.1.1.2:
75 ;;;
76 ;;; port_list := port_interface_list
77 ;;;
78 ;;; According to IEEE 1076-1993 4.3.2.1:
79 ;;;
80 ;;; interface_list := interface_element { ; interface_element }
81 ;;;
82 ;;; interface_element := interface_declaration
83 ;;;
84 ;;; According to IEEE 1076-1993 4.3.2:
85 ;;;
86 ;;; interface_declaration :=
87 ;;;    interface_constant_declaration
88 ;;;  | interface_signal_declaration
89 ;;;  | interface_variable_declaration
90 ;;;  | interface_file_declaration
91 ;;;
92 ;;; interface_signal_declaration :=
93 ;;;  [ SIGNAL ] identifier_list : [ mode ] subtype_indication [ BUS ]
94 ;;;  [ := static_expression ]
95 ;;;
96 ;;; mode := IN | OUT | INOUT | BUFFER | LINKAGE
97 ;;;
98 ;;; Implementation note:
99 ;;;    Since the port list must contain signals will only the interface
100 ;;;    signal declaration of the interface declaration be valid. Further,
101 ;;;    we may safely assume that the SIGNAL symbol will not be needed.
102 ;;;    The identifier list is reduced to a signle name entry, mode is set
103 ;;;    to in, out or inout due to which part of the port list it comes from.
104 ;;;    The mode types supported are in, out and inout where as buffer and
105 ;;;    linkage mode is not supported. The subtype indication is currently
106 ;;;    hardwired to standard logic, but should be controlled by attribute.
107 ;;;    There is currently no support for busses and thus is the BUS symbol
108 ;;;    no being applied. Also, there is currently no static expression
109 ;;;    support, this too may be conveyed using attributes.
112 ;;; This little routine writes a single pin on the port clause.
113 ;;; It assumes a list containing (portname, mode, type) such as
114 ;;; (CLK in Std_Logic width).
116 ;;; THHE If you added a attribute width=n to a pin or to a I/O-PAD, you get
117 ;;;      portname : IN Std_Logic_Vector(width-1 downto 0)
119 (define vhdl:write-port
120   (lambda (port)
121     (if (not (null? port))
122         (begin
123           (if (string=? (cadddr port) "unknown")
124             (begin
125               (display (car port))
126               (display " : ")
127               (display (cadr port))
128               (display " ")
129               (display (caddr port))
130             )
131           )
132           (if (not (string=? (cadddr port) "unknown"))
133             (begin
134               (display (car port))
135               (display " : ")
136               (display (cadr port))
137               (display " ")
138               (display (caddr port))
139               (display "_Vector(")
140               (display (- (string->number(cadddr port)) 1))
141               (display " downto 0)")
142             )
143           )
144         )
145     )
146   )
149 ;;; This little routine will actually write the full port clause given a list
150 ;;; of pins, such as ((CLK in Std_Logic) (D in Std_Logic) (Q out Std_Logic))
152 (define vhdl:write-port-list
153   (lambda (port-list)
154     (if (not (null? port-list))
155         (begin
156           (display "    PORT (")
157           (newline)
158           (display "        ")
159           (vhdl:write-port (car port-list))
160           (for-each (lambda (pin)
161                       (begin
162                         (display ";")
163                         (newline)
164                         (display "        ")
165                         (vhdl:write-port pin)
166                       )
167                     )
168                     (cdr port-list))
169           (display ");")
170           (newline)
171         )
172     )
173   )
176 ;;; This is the real thing. It will take a port-list arrangement.
178 ;;; The port-list is a list containing three list:
179 ;;;  (in-port-list, out-port-list, inout-port-list)
181 ;;; These lists will be transformed into a single list containing the full
182 ;;; pin information. Currently is this done with hardwired to Std_Logic.
184 (define vhdl:write-port-clause
185   (lambda (port-list)
186     (let ((in (car port-list))
187           (out (cadr port-list))
188           (inout (caddr port-list)))
189       (vhdl:write-port-list
190         (append
191           (map (lambda (pin)
192                       (list (car pin) "in" "Std_Logic" (cdr pin))) in)
193           (map (lambda (pin)
194                       (list (car pin) "out" "Std_Logic" (cdr pin))) out)
195           (map (lambda (pin)
196                       (list (car pin) "inout" "Std_Logic" (cdr pin))) inout)
197         )
198       )
199     )
200   )
203 ;;; Primary unit
205 ;;; According to IEEE 1076-1993 11.1:
207 ;;; primary_unit :=
208 ;;;    entity_declaration
209 ;;;  | configuration_declaration
210 ;;;  | package_declaration
212 ;;; Implementation note:
213 ;;;    We assume that gEDA does not generate either a configuration or
214 ;;;    package declaration. Thus, only a entity declaration will be generated.
216 ;;; According to IEEE 1076-1993 1.1:
218 ;;; entity_declaration :=
219 ;;;    ENTITY identifier IS
220 ;;;       entity_header
221 ;;;       entity_declarative_part
222 ;;;  [ BEGIN
223 ;;;       entity_statement_part ]
224 ;;;    END [ ENTITY ] [ entity_simple_name ] ;
226 ;;; Implementation note:
227 ;;;    We assume that no entity declarative part and no entity statement part
228 ;;;    is to be produced. Further, it is good custom in VHDL-93 to append
229 ;;;    both the entity keyword as well as the entity simple name to the
230 ;;;    trailer, therefore this is done to keep VHDL compilers happy.
232 ;;; According to IEEE 1076-1993 1.1.1:
234 ;;; entity_header :=
235 ;;;  [ formal_generic_clause ]
236 ;;;  [ formal_port_clause ]
238 ;;; Implementation note:
239 ;;;    Initially we will assume that there is no generic clause but that there
240 ;;;    is an port clause. We would very much like to have generic and the port
241 ;;;    clause should be conditional (consider writting a test-bench).
244 (define vhdl:write-primary-unit
245   (lambda (module-name port-list)
246     (begin
247       ; Entity header
248       (display "-- Entity declaration")
249       (newline)
250       (newline)
251       (display "ENTITY ")
252       (display module-name)
253       (display " IS")
254       (newline)
255       (vhdl:write-port-clause port-list)
256       ; entity_declarative_part is assumed not to be used
257       ; entity_statement_part is assumed not to be used
258       ; Entity trailer
259       (display "END ")
260       (display module-name)
261       (display ";")
262       (newline)
263       (newline)
264     )
265   )
269 ;; Secondary Unit Section
272 ;;; Component Declaration
274 ;;; According to IEEE 1076-1993 4.5:
276 ;;; component_declaration :=
277 ;;;    COMPONENT identifier [ IS ]
278 ;;;     [ local_generic_clause ]
279 ;;;     [ local_port_clause ]
280 ;;;    END COMPONENT [ component_simple_name ] ;
282 ;;; Implementation note:
283 ;;;    The component declaration should match the entity declaration of the
284 ;;;    same name as the component identifier indicates. Since we do not yeat
285 ;;;    support the generic clause in the entity declaration we shall not
286 ;;;    support it here either. We will however support the port clause.
288 ;;;    In the same fassion as before we will use the conditional IS symbol
289 ;;;    as well as replicating the identifier as component simple name just to
290 ;;;    be in line with good VHDL-93 practice and keep compilers happy.
292 (define vhdl:write-component-declarations
293   (lambda (device-list)
294     (begin
295       (for-each
296         (lambda (device)
297           (begin
298             ; Hmm... I just grabbed this if stuff... do I need it?
299             (if (not (memv (string->symbol device) ; ignore specials
300                            (map string->symbol (list "IOPAD" "IPAD" "OPAD" "HIGH" "LOW"))))
301                 (begin
302                      (display "    COMPONENT ")
303                      (display device)
304                      (newline)
305                      (vhdl:write-port-clause (vhdl:get-device-port-list
306                                                 (find-device packages device)))
307                      (display "    END COMPONENT ")
308                      (display ";")
309                      (newline)
310                      (newline)
311                 )
312             )
313           )
314         ) device-list
315       )
316     )
317   )
320 ;;; THHE
321 ;;; Build the port list from the symbols
323 ;;; ... wouldn't it be better to feed get-pins, get-attribute-by-pinnumber and co.
324 ;;;     with the device rather than the component? pin names and atributes are locked to
325 ;;;     the symbol and not to the instance of the symbol in the sheet!
327 (define vhdl:get-device-port-list
328   (lambda (device)
329     ;; construct list
330     (list (vhdl:get-device-matching-pins device (gnetlist:get-pins device) "IN")
331           (vhdl:get-device-matching-pins device (gnetlist:get-pins device) "OUT")
332           (vhdl:get-device-matching-pins device (gnetlist:get-pins device) "INOUT")
333     )
334   )
337 ;;; THHE
338 ;;; get a list of all pins of a given type
341 (define vhdl:get-device-matching-pins
342   (lambda (device pin-list value)
343     (cond ((null? pin-list) '())
344           ((string=? (gnetlist:get-attribute-by-pinnumber device (car pin-list) "pintype" )
345                      value)
346            (cons
347             (cons (car pin-list) (gnetlist:get-attribute-by-pinnumber device (car pin-list) "width"))
348             (vhdl:get-device-matching-pins device (cdr pin-list) value))
349            )
350           (else (vhdl:get-device-matching-pins device (cdr pin-list) value))
351     )
352   )
355 ;;; THHE
356 ;;; build a list of all unique devices in in the list
359 (define vhdl:get-unique-devices
360   (lambda (device-list)
361       (cond ((null? device-list) '())
362             ((not (contains? (cdr device-list) (car device-list)))
363              (append (vhdl:get-unique-devices (cdr device-list))
364                      (list (car device-list))))
365             (else (vhdl:get-unique-devices (cdr device-list)))
366       )
367   )
370 ;;; THHE
371 ;;; build a list of  all unique devices in the schematic
374 (define unique-devices
375   (lambda nil
376     (vhdl:get-unique-devices (map get-device packages))
380 ;;; Signal Declaration
382 ;;; According to IEEE 1076-1993 4.3.1.2:
384 ;;; signal_declaration :=
385 ;;;    SIGNAL identifier_list : subtype_indication [ signal_kind ]
386 ;;;    [ := expression ] ;
388 ;;; signal_kind := REGISTER | BUS
390 ;;; Implementation note:
391 ;;;    Currently will the identifier list be reduced to a single entry.
392 ;;;    There is no support for either register or bus type of signal kind.
393 ;;;    Further, no default expression is being supported.
394 ;;;    The subtype indication is hardwired to Std_Logic.
396 (define (vhdl:write-signal-declarations)
397   (begin
398     (for-each
399      (lambda (signal)
400        (begin
401          (display "    SIGNAL ")
402          (display signal)
403          (display " : Std_Logic;")
404          (newline)
405        )
406      )
407      all-unique-nets)
408   )
411 ;;; Architecture Declarative Part
413 ;;; According to IEEE 1076-1993 1.2.1:
415 ;;; architecture_declarative_part :=
416 ;;;  { block_declarative_item }
418 ;;; block_declarative_item :=
419 ;;;    subprogram_declaration
420 ;;;  | subprogram_body
421 ;;;  | type_declaration
422 ;;;  | subtype_declaration
423 ;;;  | constant_declaration
424 ;;;  | signal_declaration
425 ;;;  | shared_variable_declaration
426 ;;;  | file_declaration
427 ;;;  | alias_declaration
428 ;;;  | component_declaration
429 ;;;  | attribute_declaration
430 ;;;  | attribute_specification
431 ;;;  | configuration_specification
432 ;;;  | disconnection_specification
433 ;;;  | use_clause
434 ;;;  | group_template_declaration
435 ;;;  | group_declaration
437 ;;; Implementation note:
438 ;;;    There is currently no support for programs or procedural handling in
439 ;;;    gEDA, thus will all declarations above involved in thus activites be
440 ;;;    left unused. This applies to subprogram declaration, subprogram body,
441 ;;;    shared variable declaration and file declaration.
443 ;;;    Further, there is currently no support for type handling and therefore
444 ;;;    will not the type declaration and subtype declaration be used.
446 ;;;    The is currently no support for constants, aliases, configuration
447 ;;;    and groups so the constant declaration, alias declaration, configuration
448 ;;;    specification, group template declaration and group declaration will not
449 ;;;    be used.
451 ;;;    The attribute passing from a gEDA netlist into VHDL attributes must
452 ;;;    wait, therefore will the attribute declaration and attribute
453 ;;;    specification not be used.
455 ;;;    The disconnection specification will not be used.
457 ;;;    The use clause will not be used since we pass the responsibility to the
458 ;;;    primary unit (where it is not yet supported).
460 ;;;    The signal declation will be used to convey signals held within the
461 ;;;    architecture.
463 ;;;    The component declaration will be used to convey the declarations of
464 ;;;    any external entity being used within the architecture.
466 (define (vhdl:write-architecture-declarative-part)
467   (begin
468     ; Due to my taste will the component declarations go first
469     ; XXX - Broken until someday
470     ; THHE fixed today ;-)
471     (vhdl:write-component-declarations (unique-devices))
472     ; Then comes the signal declatations
473     (vhdl:write-signal-declarations)
474   )
477 ;;; Architecture Statement Part
479 ;;; According to IEEE 1076-1993 1.2.2:
481 ;;; architecture_statement_part :=
482 ;;;  { concurrent_statement }
484 ;;; According to IEEE 1076-1993 9:
486 ;;; concurrent_statement :=
487 ;;;    block_statement
488 ;;;  | process_statement
489 ;;;  | concurrent_procedure_call_statement
490 ;;;  | concurrent_assertion_statement
491 ;;;  | concurrent_signal_assignment_statement
492 ;;;  | component_instantiation_statement
493 ;;;  | generate_statement
495 ;;; Implementation note:
496 ;;;    We currently does not support block statements, process statements,
497 ;;;    concurrent procedure call statements, concurrent assertion statements,
498 ;;;    concurrent signal assignment statements or generarte statements.
500 ;;;    Thus, we only support component instantiation statements.
502 ;;; According to IEEE 1076-1993 9.6:
504 ;;; component_instantiation_statement :=
505 ;;;    instantiation_label : instantiation_unit
506 ;;;  [ generic_map_aspect ] [ port_map_aspect ] ;
508 ;;; instantiated_unit :=
509 ;;;    [ COMPONENT ] component_name
510 ;;;  | ENTITY entity_name [ ( architecture_identifier ) ]
511 ;;;  | CONFIGURATION configuration_name
513 ;;; Implementation note:
514 ;;;    Since we are not supporting the generic parameters we will thus not
515 ;;;    suppport the generic map aspect. We will support the port map aspect.
517 ;;;    Since we do not yeat support the component form we will not yet use
518 ;;;    the component symbol based instantiated unit.
520 ;;;    Since we do not yeat support configurations we will not support the
521 ;;;    we will not support the configuration symbol based form.
523 ;;;    This leaves us with the entity form, which we will support initially
524 ;;;    using only the entity name. The architecture identifier could possibly
525 ;;;    be supported by attribute value.
527 (define vhdl:write-architecture-statement-part
528   (lambda (packages)
529     (begin
530       (display "-- Architecture statement part")
531       (newline)
532       (vhdl:write-component-instantiation-statements packages)
533       (display "-- Signal assignment part")
534       (newline)
535       (vhdl:write-signal-assignment-statements packages)
536     )
537   )
539 ;;; THHE
540 ;;; write component instantiation for each component in the sheet
543 (define vhdl:write-component-instantiation-statements
544   (lambda (packages)
545     (for-each (lambda (package)
546       (begin
547         (let ((device (get-device package)))
548           (if (not (memv (string->symbol device)
549                          (map string->symbol
550                                 (list "IOPAD" "IPAD" "OPAD"
551                                  "HIGH" "LOW"))))
552             (begin
553               (display "    ")
554               ; label
555               (display package)
556               (display " : ")
557               ; entity name
558               (display (get-device package))
559               (newline)
560               ; Generic map aspect should go in here
561               ; Port map aspect
562               (vhdl:write-port-map package)
563               (display ";")
564               (newline)
565               (newline)
566             )
567           )
568         )
569       )
570     )
571     packages)
572   )
575 ;;; THHE
576 ;;; Write the signal assignment for the top-level ports
577 ;;; Since I like to have the urefs as port names in the top
578 ;;; level entity, I have to assign them to the correspinding nets as well
580 (define vhdl:write-signal-assignment-statements
581   (lambda (packages)
582     (begin
583       (for-each (lambda (port-ass) (vhdl:write-in-signal-assignment port-ass))
584         (vhdl:get-top-level-ports packages "IPAD"))
585       (for-each (lambda (port-ass) (vhdl:write-out-signal-assignment port-ass))
586         (vhdl:get-top-level-ports packages "OPAD"))
587       (for-each (lambda (port-ass) (vhdl:write-inout-signal-assignment port-ass))
588         (vhdl:get-top-level-ports packages "IOPAD"))
589     )
590   )
592 ;;; THHE
593 ;;; get a list of the top-level ports (the urefs of the I/O-PADs)
595 (define vhdl:get-top-level-ports
596   (lambda (package-list pad-type)
597     (cond ((null? package-list) '())
598           ((string=? (get-device (car package-list)) pad-type)
599            (cons (cons (car package-list)
600                        (cdar (gnetlist:get-pins-nets (car package-list))) )
601                  (vhdl:get-top-level-ports (cdr package-list ) pad-type )))
602            (else (vhdl:get-top-level-ports (cdr package-list ) pad-type ))
604     )
605   )
608 ;;;THHE
609 (define vhdl:write-in-signal-assignment
610   (lambda (port-assignment)
611     (begin
612       (display (cdr port-assignment))
613       (display " <= ")
614       (display (car port-assignment))
615       (display ";")
616       (newline)
617     )
618   )
621 ;;;THHE
622 (define vhdl:write-out-signal-assignment
623   (lambda (port-assignment)
624     (begin
625       (display (car port-assignment))
626       (display " <= ")
627       (display (cdr port-assignment))
628       (display ";")
629       (newline)
630     )
631   )
635 ;;;THHE
636 (define vhdl:write-inout-signal-assignment
637   (lambda (port-assignment)
638     (begin
639       (vhdl:write-in-signal-assignment port-assignment)
640       (vhdl:write-out-signal-assignment port-assignment)
641     )
642   )
645 ;;; Port map aspect
647 ;;; According to IEEE 1076-1993 5.6.1.2:
649 ;;; port_map_aspect := PORT MAP ( port_association_list )
651 ;;; According to IEEE 1076-1993 4.3.2.2:
653 ;;; association_list :=
654 ;;;    association_element { , association_element }
656 (define vhdl:write-port-map
657   (lambda (package)
658     (begin
659       (let ((pin-list (gnetlist:get-pins-nets package)))
660         (if (not (null? pin-list))
661             (begin
662               (display "    PORT MAP (")
663               (newline)
664               (display "        ")
665               (vhdl:write-association-element (car pin-list))
666               (for-each (lambda (pin)
667                           (display ",")
668                           (newline)
669                           (display "        ")
670                           (vhdl:write-association-element pin))
671                         (cdr pin-list))
672               (display ")")
673             )
674         )
675       )
677     )
678   )
681 ;;; Association element
683 ;;; According to IEEE 1076-1993 4.3.2.2:
685 ;;; association_element :=
686 ;;;  [ formal_part => ] actual_part
688 ;;; formal_part :=
689 ;;;    formal_designator
690 ;;;  | function_name ( formal_designator )
691 ;;;  | type_mark ( formal_designator )
693 ;;; formal_designator :=
694 ;;;    generic_name
695 ;;;  | port_name
696 ;;;  | parameter_name
698 ;;; actual_part :=
699 ;;;    actual_designator
700 ;;;  | function_name ( actual_designator )
701 ;;;  | type_mark ( actual_designator )
703 ;;; actual_designator :=
704 ;;;    expression
705 ;;;  | signal_name
706 ;;;  | variable_name
707 ;;;  | file_name
708 ;;;  | OPEN
710 ;;; Implementation note:
711 ;;;    In the association element one may have a formal part or relly on
712 ;;;    positional association. The later is doomed out as bad VHDL practice
713 ;;;    and thus will the formal part allways be present.
715 ;;;    The formal part will not support either the function name or type mark
716 ;;;    based forms, thus only the formal designator form is supported.
718 ;;;    Of the formal designator forms will generic name and port name be used
719 ;;;    as appropriate (this currently means that only port name will be used).
721 ;;;    The actual part will not support either the function name or type mark
722 ;;;    based forms, thus only the actual designator form is supported.
724 (define vhdl:write-association-element
725   (lambda (pin)
726     (begin
727       (display (car pin))
728       (display " => ")
729       (if (strncmp? "unconnected_pin" (cdr pin) 15)
730           (display "OPEN")
731           (display (cdr pin))))))
733 ;;; Secondary unit
735 ;;; According to IEEE 1076-1993 11.1:
737 ;;; secondary_unit :=
738 ;;;    architecture_body
739 ;;;  | package_body
741 ;;; Implementation note:
742 ;;;    Since we are not likely to create packages in gEDA in the near future
743 ;;;    we will only support the architecture body.
745 ;;; According to IEEE 1076-1993 1.2:
747 ;;; architecture_body :=
748 ;;;    ARCHITECTURE identifier OF entity_name IS
749 ;;;       architecture_declarative_part
750 ;;;    BEGIN
751 ;;;       architecture_statement_part
752 ;;;    END [ ARCHITECTURE ] [ architecture_simple_name ] ;
754 ;;; Implementation note:
755 ;;;    The identifier will identify one of many architectures for an entity.
756 ;;;    Since we generate only an netlist architecture we will lock this to be
757 ;;;    "netlist" for the time being. Just as with the entity declaration we
758 ;;;    will use good VHDL-93 custom to add the architecture keyword as well
759 ;;;    as the architecture simple name to the trailer to keep compilers happy.
761 (define vhdl:write-secondary-unit
762   (lambda (module-name)
763     (display "-- Secondary unit")
764     (newline)
765     (display "ARCHITECTURE netlist OF ")
766     (display module-name)
767     (display " IS")
768     (newline)
769     ; architecture_declarative_part
770     (vhdl:write-architecture-declarative-part)
771     (display "BEGIN")
772     (newline)
773     ; architecture_statement_part
774     (vhdl:write-architecture-statement-part packages)
775     (display "END netlist;")
776     (newline)
777   )
780 ;;; Top level function
781 ;;; Write structural VHDL representation of the schematic
783 (define (vhdl output-filename)
784   (set-current-output-port (gnetlist:output-port output-filename))
785   (let ((module-name (gnetlist:get-toplevel-attribute "module-name"))
786         (port-list (vhdl:get-top-port-list)))
787     (begin
788       (display "-- Structural VHDL generated by gnetlist")
789       (newline)
790       (vhdl:write-context-clause)
791       (vhdl:write-primary-unit module-name port-list)
792       (newline)
793       (vhdl:write-secondary-unit module-name)
794     )
795   )
796   (close-output-port (current-output-port))
799 ;;; Context clause
801 ;;; According to IEEE 1076-1993 11.3:
803 ;;; context_clause := { context_item }
804 ;;; context_item := library_clause | use_clause
806 ;;; Implementation note:
807 ;;;    Both library and use clauses will be generated, eventually...
808 ;;;    What is missing is the information from gEDA itself, i think.
810 (define (vhdl:write-context-clause)
811   (display "-- Context clause")
812   (newline)
813   (display "library IEEE;")
814   (newline)
815   (display "use IEEE.Std_Logic_1164.all;")
816   (newline)