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)
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.
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.
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.
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!)
39 (define vhdl:get-top-port-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)
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))))
62 ;;; According to IEEE 1076-1993 1.1.1:
65 ;;; [ formal_generic_clause ]
66 ;;; [ formal_port_clause ]
69 ;;; GENERIC ( generic_list ) ;
72 ;;; PORT ( port_list ) ;
74 ;;; According to IEEE 1076-1993 1.1.1.2:
76 ;;; port_list := port_interface_list
78 ;;; According to IEEE 1076-1993 4.3.2.1:
80 ;;; interface_list := interface_element { ; interface_element }
82 ;;; interface_element := interface_declaration
84 ;;; According to IEEE 1076-1993 4.3.2:
86 ;;; interface_declaration :=
87 ;;; interface_constant_declaration
88 ;;; | interface_signal_declaration
89 ;;; | interface_variable_declaration
90 ;;; | interface_file_declaration
92 ;;; interface_signal_declaration :=
93 ;;; [ SIGNAL ] identifier_list : [ mode ] subtype_indication [ BUS ]
94 ;;; [ := static_expression ]
96 ;;; mode := IN | OUT | INOUT | BUFFER | LINKAGE
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
121 (if (not (null? port))
123 (if (string=? (cadddr port) "unknown")
127 (display (cadr port))
129 (display (caddr port))
132 (if (not (string=? (cadddr port) "unknown"))
136 (display (cadr port))
138 (display (caddr port))
140 (display (- (string->number(cadddr port)) 1))
141 (display " downto 0)")
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
154 (if (not (null? port-list))
159 (vhdl:write-port (car port-list))
160 (for-each (lambda (pin)
165 (vhdl:write-port pin)
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
186 (let ((in (car port-list))
187 (out (cadr port-list))
188 (inout (caddr port-list)))
189 (vhdl:write-port-list
192 (list (car pin) "in" "Std_Logic" (cdr pin))) in)
194 (list (car pin) "out" "Std_Logic" (cdr pin))) out)
196 (list (car pin) "inout" "Std_Logic" (cdr pin))) inout)
205 ;;; According to IEEE 1076-1993 11.1:
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
221 ;;; entity_declarative_part
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:
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)
248 (display "-- Entity declaration")
252 (display module-name)
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
260 (display module-name)
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)
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"))))
302 (display " COMPONENT ")
305 (vhdl:write-port-clause (vhdl:get-device-port-list
306 (find-device packages device)))
307 (display " END COMPONENT ")
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
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")
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" )
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))
350 (else (vhdl:get-device-matching-pins device (cdr pin-list) value))
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)))
371 ;;; build a list of all unique devices in the schematic
374 (define unique-devices
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)
403 (display " : Std_Logic;")
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
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
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
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)
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)
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 :=
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
530 (display "-- Architecture statement part")
532 (vhdl:write-component-instantiation-statements packages)
533 (display "-- Signal assignment part")
535 (vhdl:write-signal-assignment-statements packages)
540 ;;; write component instantiation for each component in the sheet
543 (define vhdl:write-component-instantiation-statements
545 (for-each (lambda (package)
547 (let ((device (get-device package)))
548 (if (not (memv (string->symbol device)
550 (list "IOPAD" "IPAD" "OPAD"
558 (display (get-device package))
560 ; Generic map aspect should go in here
562 (vhdl:write-port-map package)
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
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"))
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 ))
609 (define vhdl:write-in-signal-assignment
610 (lambda (port-assignment)
612 (display (cdr port-assignment))
614 (display (car port-assignment))
622 (define vhdl:write-out-signal-assignment
623 (lambda (port-assignment)
625 (display (car port-assignment))
627 (display (cdr port-assignment))
636 (define vhdl:write-inout-signal-assignment
637 (lambda (port-assignment)
639 (vhdl:write-in-signal-assignment port-assignment)
640 (vhdl:write-out-signal-assignment port-assignment)
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
659 (let ((pin-list (gnetlist:get-pins-nets package)))
660 (if (not (null? pin-list))
662 (display " PORT MAP (")
665 (vhdl:write-association-element (car pin-list))
666 (for-each (lambda (pin)
670 (vhdl:write-association-element pin))
681 ;;; Association element
683 ;;; According to IEEE 1076-1993 4.3.2.2:
685 ;;; association_element :=
686 ;;; [ formal_part => ] actual_part
689 ;;; formal_designator
690 ;;; | function_name ( formal_designator )
691 ;;; | type_mark ( formal_designator )
693 ;;; formal_designator :=
699 ;;; actual_designator
700 ;;; | function_name ( actual_designator )
701 ;;; | type_mark ( actual_designator )
703 ;;; actual_designator :=
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
729 (if (strncmp? "unconnected_pin" (cdr pin) 15)
731 (display (cdr pin))))))
735 ;;; According to IEEE 1076-1993 11.1:
737 ;;; secondary_unit :=
738 ;;; architecture_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
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")
765 (display "ARCHITECTURE netlist OF ")
766 (display module-name)
769 ; architecture_declarative_part
770 (vhdl:write-architecture-declarative-part)
773 ; architecture_statement_part
774 (vhdl:write-architecture-statement-part packages)
775 (display "END netlist;")
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)))
788 (display "-- Structural VHDL generated by gnetlist")
790 (vhdl:write-context-clause)
791 (vhdl:write-primary-unit module-name port-list)
793 (vhdl:write-secondary-unit module-name)
796 (close-output-port (current-output-port))
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")
813 (display "library IEEE;")
815 (display "use IEEE.Std_Logic_1164.all;")