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)
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., 675 Mass Ave, Cambridge, MA 02139, USA.
21 ;;; Various support functions shamelessly stolen from the verilog code and
22 ;;; reshaped for vhdl. Doing this now saves labour when the implementations
23 ;;; starts to divert further.
25 ;;; Get port list of top-level Entity
26 ;;; THHE changed this to the urefs of the I/O-PAD symbols rather than the
27 ;;; net names. So the uref of the I/O port will become the port name in
28 ;;; the VHDLport clause.
32 ;;; Since VHDL know about port directions, pins need a additional attribute.
33 ;;; The code assumes the attribute "type" (IN, OUT, INOUT) on each pin of a symbol.
34 ;;; In addition you can add the attribute "width" for a very simple definition of
35 ;;; busses. (Not complete yet!)
38 (define vhdl:get-top-port-list
41 (list (vhdl:get-matching-urefs "device" "IPAD" packages)
42 (vhdl:get-matching-urefs "device" "OPAD" packages)
43 (vhdl:get-matching-urefs "device" "IOPAD" packages))))
45 ;;; Get matching urefs
46 (define vhdl:get-matching-urefs
47 (lambda (attribute value package-list)
48 (cond ((null? package-list) '())
49 ((string=? (gnetlist:get-package-attribute (car package-list)
52 (cons (car package-list) (gnetlist:get-package-attribute (car package-list) "width"))
53 (vhdl:get-matching-urefs attribute value (cdr package-list))))
54 (else (vhdl:get-matching-urefs attribute value (cdr package-list))))
59 ;;; THHE did not need it anymore
62 ; (lambda (attribute value package-list)
63 ; (cond ((null? package-list) '())
64 ; ((string=? (gnetlist:get-package-attribute (car package-list)
68 ; (car (gnetlist:get-nets (car package-list) pin)))
69 ; (pins (car package-list)))
70 ; (vhdl:filter attribute value (cdr package-list))))
71 ; (else (vhdl:filter attribute value (cdr package-list)))))
76 ;;; According to IEEE 1076-1993 1.1.1:
79 ;;; [ formal_generic_clause ]
80 ;;; [ formal_port_clause ]
83 ;;; GENERIC ( generic_list ) ;
86 ;;; PORT ( port_list ) ;
88 ;;; According to IEEE 1076-1993 1.1.1.2:
90 ;;; port_list := port_interface_list
92 ;;; According to IEEE 1076-1993 4.3.2.1:
94 ;;; interface_list := interface_element { ; interface_element }
96 ;;; interface_element := interface_declaration
98 ;;; According to IEEE 1076-1993 4.3.2:
100 ;;; interface_declaration :=
101 ;;; interface_constant_declaration
102 ;;; | interface_signal_declaration
103 ;;; | interface_variable_declaration
104 ;;; | interface_file_declaration
106 ;;; interface_signal_declaration :=
107 ;;; [ SIGNAL ] identifier_list : [ mode ] subtype_indication [ BUS ]
108 ;;; [ := static_expression ]
110 ;;; mode := IN | OUT | INOUT | BUFFER | LINKAGE
112 ;;; Implementation note:
113 ;;; Since the port list must contain signals will only the interface
114 ;;; signal declaration of the interface declaration be valid. Further,
115 ;;; we may safely assume that the SIGNAL symbol will not be needed.
116 ;;; The identifier list is reduced to a signle name entry, mode is set
117 ;;; to in, out or inout due to which part of the port list it comes from.
118 ;;; The mode types supported are in, out and inout where as buffer and
119 ;;; linkage mode is not supported. The subtype indication is currently
120 ;;; hardwired to standard logic, but should be controlled by attribute.
121 ;;; There is currently no support for busses and thus is the BUS symbol
122 ;;; no being applied. Also, there is currently no static expression
123 ;;; support, this too may be conveyed using attributes.
126 ;;; This little routine writes a single pin on the port clause.
127 ;;; It assumes a list containing (portname, mode, type) such as
128 ;;; (CLK in Std_Logic width).
130 ;;; THHE If you added a attribute width=n to a pin or to a I/O-PAD, you get
131 ;;; portname : IN Std_Logic_Vector(width-1 downto 0)
133 (define vhdl:write-port
135 (if (not (null? port))
137 (if (string=? (cadddr port) "unknown")
139 (display (car port) p)
141 (display (cadr port) p)
143 (display (caddr port) p)
146 (if (not (string=? (cadddr port) "unknown"))
148 (display (car port) p)
150 (display (cadr port) p)
152 (display (caddr port) p)
153 (display "_Vector(" p)
154 (display (- (string->number(cadddr port)) 1) p)
155 (display " downto 0)" p)
163 ;;; This little routine will actually write the full port clause given a list
164 ;;; of pins, such as ((CLK in Std_Logic) (D in Std_Logic) (Q out Std_Logic))
166 (define vhdl:write-port-list
168 (if (not (null? list))
170 (display " PORT (" p)
173 (vhdl:write-port (car list) p)
174 (for-each (lambda (pin)
179 (vhdl:write-port pin p)
190 ;;; This is the real thing. It will take a port-list arrangement.
192 ;;; The port-list is a list containing three list:
193 ;;; (in-port-list, out-port-list, inout-port-list)
195 ;;; These lists will be transformed into a single list containing the full
196 ;;; pin information. Currently is this done with hardwired to Std_Logic.
198 (define vhdl:write-port-clause
199 (lambda (port-list p)
200 (let ((in (car port-list))
201 (out (cadr port-list))
202 (inout (caddr port-list)))
203 (vhdl:write-port-list
206 (list (car pin) "in" "Std_Logic" (cdr pin))) in)
208 (list (car pin) "out" "Std_Logic" (cdr pin))) out)
210 (list (car pin) "inout" "Std_Logic" (cdr pin))) inout)
220 ;;; According to IEEE 1076-1993 11.1:
223 ;;; entity_declaration
224 ;;; | configuration_declaration
225 ;;; | package_declaration
227 ;;; Implementation note:
228 ;;; We assume that gEDA does not generate either a configuration or
229 ;;; package declaration. Thus, only a entity declaration will be generated.
231 ;;; According to IEEE 1076-1993 1.1:
233 ;;; entity_declaration :=
234 ;;; ENTITY identifier IS
236 ;;; entity_declarative_part
238 ;;; entity_statement_part ]
239 ;;; END [ ENTITY ] [ entity_simple_name ] ;
241 ;;; Implementation note:
242 ;;; We assume that no entity declarative part and no entity statement part
243 ;;; is to be produced. Further, it is good custom in VHDL-93 to append
244 ;;; both the entity keyword as well as the entity simple name to the
245 ;;; trailer, therefore this is done to keep VHDL compilers happy.
247 ;;; According to IEEE 1076-1993 1.1.1:
250 ;;; [ formal_generic_clause ]
251 ;;; [ formal_port_clause ]
253 ;;; Implementation note:
254 ;;; Initially we will assume that there is no generic clause but that there
255 ;;; is an port clause. We would very much like to have generic and the port
256 ;;; clause should be conditional (consider writting a test-bench).
259 (define vhdl:write-primary-unit
260 (lambda (module-name port-list p)
263 (display "-- Entity declaration" p)
266 (display "ENTITY " p)
267 (display module-name p)
270 ; entity_header := [ generic_clause port_clause ]
271 ; Insert generic_clause here when time comes
275 ;(display "The schematic contains the following devices:")
277 ;(display unique-devices)
281 (vhdl:write-port-clause port-list p)
282 ; entity_declarative_part is assumed not to be used
283 ; entity_statement_part is assumed not to be used
286 (display module-name p)
295 ;; Secondary Unit Section
298 ;;; Component Declaration
300 ;;; According to IEEE 1076-1993 4.5:
302 ;;; component_declaration :=
303 ;;; COMPONENT identifier [ IS ]
304 ;;; [ local_generic_clause ]
305 ;;; [ local_port_clause ]
306 ;;; END COMPONENT [ component_simple_name ] ;
308 ;;; Implementation note:
309 ;;; The component declaration should match the entity declaration of the
310 ;;; same name as the component identifier indicates. Since we do not yeat
311 ;;; support the generic clause in the entity declaration we shall not
312 ;;; support it here either. We will however support the port clause.
314 ;;; In the same fassion as before we will use the conditional IS symbol
315 ;;; as well as replicating the identifier as component simple name just to
316 ;;; be in line with good VHDL-93 practice and keep compilers happy.
318 (define vhdl:write-component-declarations
319 (lambda (device-list p)
322 ;(display "refdes : package : (( IN )( OUT )(INOUT ))")
324 ;(display "========================================")
330 ; Hmm... I just grabbed this if stuff... do I need it?
331 (if (not (memv (string->symbol device) ; ignore specials
332 (map string->symbol (list "IOPAD" "IPAD" "OPAD" "HIGH" "LOW"))))
334 (display " COMPONENT " p)
338 ; Generic clause should be inserted here
340 ;(display (find-device packages device))
344 ;(display (vhdl:get-device-port-list
345 ; (find-device packages device)
350 (vhdl:write-port-clause (vhdl:get-device-port-list
351 (find-device packages device))
353 (display " END COMPONENT " p)
367 ;;; Build the port list from the symbols
369 ;;; ... wouldn't it be better to feed get-pins, get-attribute-by-pinnumber and co.
370 ;;; with the device rather than the component? pin names and atributes are locked to
371 ;;; the symbol and not to the instance of the symbol in the sheet!
373 (define vhdl:get-device-port-list
376 (list (vhdl:get-device-matching-pins device (gnetlist:get-pins device) "IN")
377 (vhdl:get-device-matching-pins device (gnetlist:get-pins device) "OUT")
378 (vhdl:get-device-matching-pins device (gnetlist:get-pins device) "INOUT")
384 ;;; get a list of all pins of a given type
387 (define vhdl:get-device-matching-pins
388 (lambda (device pin-list value)
389 (cond ((null? pin-list) '())
390 ((string=? (gnetlist:get-attribute-by-pinnumber device (car pin-list) "pintype" )
393 (cons (car pin-list) (gnetlist:get-attribute-by-pinnumber device (car pin-list) "width"))
394 (vhdl:get-device-matching-pins device (cdr pin-list) value))
396 (else (vhdl:get-device-matching-pins device (cdr pin-list) value))
402 ;;; build a list of all unique devices in in the list
405 (define vhdl:get-unique-devices
406 (lambda (device-list)
407 (cond ((null? device-list) '())
408 ((not (contains? (cdr device-list) (car device-list)))
409 (append (vhdl:get-unique-devices (cdr device-list))
410 (list (car device-list))))
411 (else (vhdl:get-unique-devices (cdr device-list)))
417 ;;; build a list of all unique devices in the schematic
420 (define unique-devices
422 (vhdl:get-unique-devices (map get-device packages))
426 ;;; Signal Declaration
428 ;;; According to IEEE 1076-1993 4.3.1.2:
430 ;;; signal_declaration :=
431 ;;; SIGNAL identifier_list : subtype_indication [ signal_kind ]
432 ;;; [ := expression ] ;
434 ;;; signal_kind := REGISTER | BUS
436 ;;; Implementation note:
437 ;;; Currently will the identifier list be reduced to a single entry.
438 ;;; There is no support for either register or bus type of signal kind.
439 ;;; Further, no default expression is being supported.
440 ;;; The subtype indication is hardwired to Std_Logic.
442 (define vhdl:write-signal-declarations
448 (display " SIGNAL " p)
450 (display " : Std_Logic;" p)
459 ;;; Architecture Declarative Part
461 ;;; According to IEEE 1076-1993 1.2.1:
463 ;;; architecture_declarative_part :=
464 ;;; { block_declarative_item }
466 ;;; block_declarative_item :=
467 ;;; subprogram_declaration
468 ;;; | subprogram_body
469 ;;; | type_declaration
470 ;;; | subtype_declaration
471 ;;; | constant_declaration
472 ;;; | signal_declaration
473 ;;; | shared_variable_declaration
474 ;;; | file_declaration
475 ;;; | alias_declaration
476 ;;; | component_declaration
477 ;;; | attribute_declaration
478 ;;; | attribute_specification
479 ;;; | configuration_specification
480 ;;; | disconnection_specification
482 ;;; | group_template_declaration
483 ;;; | group_declaration
485 ;;; Implementation note:
486 ;;; There is currently no support for programs or procedural handling in
487 ;;; gEDA, thus will all declarations above involved in thus activites be
488 ;;; left unused. This applies to subprogram declaration, subprogram body,
489 ;;; shared variable declaration and file declaration.
491 ;;; Further, there is currently no support for type handling and therefore
492 ;;; will not the type declaration and subtype declaration be used.
494 ;;; The is currently no support for constants, aliases, configuration
495 ;;; and groups so the constant declaration, alias declaration, configuration
496 ;;; specification, group template declaration and group declaration will not
499 ;;; The attribute passing from a gEDA netlist into VHDL attributes must
500 ;;; wait, therefore will the attribute declaration and attribute
501 ;;; specification not be used.
503 ;;; The disconnection specification will not be used.
505 ;;; The use clause will not be used since we pass the responsibility to the
506 ;;; primary unit (where it Ãs not yet supported).
508 ;;; The signal declation will be used to convey signals held within the
511 ;;; The component declaration will be used to convey the declarations of
512 ;;; any external entity being used within the architecture.
514 (define vhdl:write-architecture-declarative-part
517 ; Due to my taste will the component declarations go first
518 ; XXX - Broken until someday
519 ; THHE fixed today ;-)
520 (vhdl:write-component-declarations (unique-devices) p)
521 ; Then comes the signal declatations
522 (vhdl:write-signal-declarations p)
527 ;;; Architecture Statement Part
529 ;;; According to IEEE 1076-1993 1.2.2:
531 ;;; architecture_statement_part :=
532 ;;; { concurrent_statement }
534 ;;; According to IEEE 1076-1993 9:
536 ;;; concurrent_statement :=
538 ;;; | process_statement
539 ;;; | concurrent_procedure_call_statement
540 ;;; | concurrent_assertion_statement
541 ;;; | concurrent_signal_assignment_statement
542 ;;; | component_instantiation_statement
543 ;;; | generate_statement
545 ;;; Implementation note:
546 ;;; We currently does not support block statements, process statements,
547 ;;; concurrent procedure call statements, concurrent assertion statements,
548 ;;; concurrent signal assignment statements or generarte statements.
550 ;;; Thus, we only support component instantiation statements.
552 ;;; According to IEEE 1076-1993 9.6:
554 ;;; component_instantiation_statement :=
555 ;;; instantiation_label : instantiation_unit
556 ;;; [ generic_map_aspect ] [ port_map_aspect ] ;
558 ;;; instantiated_unit :=
559 ;;; [ COMPONENT ] component_name
560 ;;; | ENTITY entity_name [ ( architecture_identifier ) ]
561 ;;; | CONFIGURATION configuration_name
563 ;;; Implementation note:
564 ;;; Since we are not supporting the generic parameters we will thus not
565 ;;; suppport the generic map aspect. We will support the port map aspect.
567 ;;; Since we do not yeat support the component form we will not yet use
568 ;;; the component symbol based instantiated unit.
570 ;;; Since we do not yeat support configurations we will not support the
571 ;;; we will not support the configuration symbol based form.
573 ;;; This leaves us with the entity form, which we will support initially
574 ;;; using only the entity name. The architecture identifier could possibly
575 ;;; be supported by attribute value.
577 (define vhdl:write-architecture-statement-part
580 (display "-- Architecture statement part" p)
582 (vhdl:write-component-instantiation-statements packages p)
583 (display "-- Signal assignment part" p)
585 (vhdl:write-signal-assignment-statements packages p)
590 ;;; write component instantiation for each component in the sheet
593 (define vhdl:write-component-instantiation-statements
595 (for-each (lambda (package)
597 (let ((device (get-device package)))
598 (if (not (memv (string->symbol device)
600 (list "IOPAD" "IPAD" "OPAD"
608 (display (get-device package) p)
610 ; Generic map aspect should go in here
612 (vhdl:write-port-map package p)
626 ;;; Write the signal assignment for the top-level ports
627 ;;; Since I like to have the urefs as port names in the top
628 ;;; level entity, I have to assign them to the correspinding nets as well
630 (define vhdl:write-signal-assignment-statements
633 (for-each (lambda (port-ass) (vhdl:write-in-signal-assignment port-ass p))
634 (vhdl:get-top-level-ports packages "IPAD"))
635 (for-each (lambda (port-ass) (vhdl:write-out-signal-assignment port-ass p))
636 (vhdl:get-top-level-ports packages "OPAD"))
637 (for-each (lambda (port-ass) (vhdl:write-inout-signal-assignment port-ass p))
638 (vhdl:get-top-level-ports packages "IOPAD"))
643 ;;; get a list of the top-level ports (the urefs of the I/O-PADs)
645 (define vhdl:get-top-level-ports
646 (lambda (package-list pad-type)
647 (cond ((null? package-list) '())
648 ((string=? (get-device (car package-list)) pad-type)
649 (cons (cons (car package-list)
650 (cdar (gnetlist:get-pins-nets (car package-list))) )
651 (vhdl:get-top-level-ports (cdr package-list ) pad-type )))
652 (else (vhdl:get-top-level-ports (cdr package-list ) pad-type ))
659 (define vhdl:write-in-signal-assignment
660 (lambda (port-assignment p)
662 (display (cdr port-assignment) p)
664 (display (car port-assignment) p)
672 (define vhdl:write-out-signal-assignment
673 (lambda (port-assignment p)
675 (display (car port-assignment) p)
677 (display (cdr port-assignment) p)
686 (define vhdl:write-inout-signal-assignment
687 (lambda (port-assignment p)
689 (vhdl:write-in-signal-assignment port-assignment p)
690 (vhdl:write-out-signal-assignment port-assignment p)
697 ;;; According to IEEE 1076-1993 5.6.1.2:
699 ;;; port_map_aspect := PORT MAP ( port_association_list )
701 ;;; According to IEEE 1076-1993 4.3.2.2:
703 ;;; association_list :=
704 ;;; association_element { , association_element }
706 (define vhdl:write-port-map
709 (let ((pin-list (gnetlist:get-pins-nets package)))
710 (if (not (null? pin-list))
712 (display " PORT MAP (" p)
715 (vhdl:write-association-element (car pin-list) p)
716 (for-each (lambda (pin)
720 (vhdl:write-association-element pin p))
731 ;;; Association element
733 ;;; According to IEEE 1076-1993 4.3.2.2:
735 ;;; association_element :=
736 ;;; [ formal_part => ] actual_part
739 ;;; formal_designator
740 ;;; | function_name ( formal_designator )
741 ;;; | type_mark ( formal_designator )
743 ;;; formal_designator :=
749 ;;; actual_designator
750 ;;; | function_name ( actual_designator )
751 ;;; | type_mark ( actual_designator )
753 ;;; actual_designator :=
760 ;;; Implementation note:
761 ;;; In the association element one may have a formal part or relly on
762 ;;; positional association. The later is doomed out as bad VHDL practice
763 ;;; and thus will the formal part allways be present.
765 ;;; The formal part will not support either the function name or type mark
766 ;;; based forms, thus only the formal designator form is supported.
768 ;;; Of the formal designator forms will generic name and port name be used
769 ;;; as appropriate (this currently means that only port name will be used).
771 ;;; The actual part will not support either the function name or type mark
772 ;;; based forms, thus only the actual designator form is supported.
774 (define vhdl:write-association-element
777 (display (car pin) p)
779 (if (strncmp? "unconnected_pin" (cdr pin) 15)
781 (display (cdr pin) p)))))
785 ;;; According to IEEE 1076-1993 11.1:
787 ;;; secondary_unit :=
788 ;;; architecture_body
791 ;;; Implementation note:
792 ;;; Since we are not likely to create packages in gEDA in the near future
793 ;;; we will only support the architecture body.
795 ;;; According to IEEE 1076-1993 1.2:
797 ;;; architecture_body :=
798 ;;; ARCHITECTURE identifier OF entity_name IS
799 ;;; architecture_declarative_part
801 ;;; architecture_statement_part
802 ;;; END [ ARCHITECTURE ] [ architecture_simple_name ] ;
804 ;;; Implementation note:
805 ;;; The identifier will identify one of many architectures for an entity.
806 ;;; Since we generate only an netlist architecture we will lock this to be
807 ;;; "netlist" for the time being. Just as with the entity declaration we
808 ;;; will use good VHDL-93 custom to add the architecture keyword as well
809 ;;; as the architecture simple name to the trailer to keep compilers happy.
811 (define vhdl:write-secondary-unit
812 (lambda (module-name p)
813 (display "-- Secondary unit" p)
815 (display "ARCHITECTURE netlist OF " p)
816 (display module-name p)
819 ; architecture_declarative_part
820 (vhdl:write-architecture-declarative-part p)
823 ; architecture_statement_part
824 (vhdl:write-architecture-statement-part packages p)
825 (display "END netlist;" p)
830 ;;; Top level function
831 ;;; Write structural VHDL representation of the schematic
834 (lambda (output-filename)
835 (let ((port (open-output-file output-filename))
836 (module-name (gnetlist:get-toplevel-attribute "module-name"))
837 (port-list (vhdl:get-top-port-list)))
840 ;; No longer needed... especially since VHDL isn't a valid mode. :-)
841 ;; (gnetlist:set-netlist-mode "VHDL")
842 (display "-- Structural VHDL generated by gnetlist" port)
844 ; design_file := design_unit { design_unit }
845 ; design_unit := context_clause library_unit
846 (vhdl:write-context-clause port)
847 ; library_unit := primary_unit secondary_unit
848 (vhdl:write-primary-unit module-name port-list port)
850 (vhdl:write-secondary-unit module-name port)
852 (close-output-port port)
859 ;;; According to IEEE 1076-1993 11.3:
861 ;;; context_clause := { context_item }
862 ;;; context_item := library_clause | use_clause
864 ;;; Implementation note:
865 ;;; Both library and use clauses will be generated, eventually...
866 ;;; What is missing is the information from gEDA itself, i think.
868 (define vhdl:write-context-clause
870 (display "-- Context clause" p)
872 (display "library IEEE;" p)
874 (display "use IEEE.Std_Logic_1164.all;" p)