2 * Copyright (c) 1998-2006 Stephen Williams (steve@icarus.com)
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 #ident "$Id: pform_dump.cc,v 1.101 2007/06/04 02:19:07 steve Exp $"
26 * This file provides the pform_dump function, that dumps the module
27 * passed as a parameter. The dump is as much as possible in Verilog
28 * syntax, so that a human can tell that it really does describe the
33 # include "PGenerate.h"
39 ostream
& operator << (ostream
&out
, const PExpr
&obj
)
45 ostream
& operator << (ostream
&o
, const PDelays
&d
)
51 ostream
& operator<< (ostream
&o
, PGate::strength_t str
)
75 ostream
& operator<< (ostream
&out
, perm_string that
)
81 ostream
& operator<< (ostream
&out
, const index_component_t
&that
)
85 case index_component_t::SEL_BIT
:
88 case index_component_t::SEL_PART
:
89 out
<< *that
.msb
<< ":" << *that
.lsb
;
91 case index_component_t::SEL_IDX_UP
:
92 out
<< *that
.msb
<< "+:" << *that
.lsb
;
94 case index_component_t::SEL_IDX_DO
:
95 out
<< *that
.msb
<< "-:" << *that
.lsb
;
105 ostream
& operator<< (ostream
&out
, const name_component_t
&that
)
107 out
<< that
.name
.str();
109 typedef std::list
<index_component_t
>::const_iterator index_it_t
;
110 for (index_it_t idx
= that
.index
.begin()
111 ; idx
!= that
.index
.end() ; idx
++) {
118 ostream
& operator<< (ostream
&o
, const pform_name_t
&that
)
120 pform_name_t::const_iterator cur
;
126 while (cur
!= that
.end()) {
134 void PExpr::dump(ostream
&out
) const
136 out
<< typeid(*this).name();
139 void PEConcat::dump(ostream
&out
) const
142 out
<< "{" << *repeat_
;
144 if (parms_
.count() == 0) {
150 if (parms_
[0]) out
<< *parms_
[0];
151 for (unsigned idx
= 1 ; idx
< parms_
.count() ; idx
+= 1) {
153 if (parms_
[idx
]) out
<< *parms_
[idx
];
158 if (repeat_
) out
<< "}";
161 void PECallFunction::dump(ostream
&out
) const
165 if (parms_
.count() > 0) {
166 if (parms_
[0]) parms_
[0]->dump(out
);
167 for (unsigned idx
= 1; idx
< parms_
.count(); ++idx
) {
169 if (parms_
[idx
]) parms_
[idx
]->dump(out
);
175 void PEEvent::dump(ostream
&out
) const
178 case PEEvent::ANYEDGE
:
180 case PEEvent::POSEDGE
:
183 case PEEvent::NEGEDGE
:
186 case PEEvent::POSITIVE
:
194 void PEFNumber::dump(ostream
&out
) const
199 void PENumber::dump(ostream
&out
) const
204 void PEIdent::dump(ostream
&out
) const
209 void PEString::dump(ostream
&out
) const
211 out
<< "\"" << text_
<< "\"";
214 void PETernary::dump(ostream
&out
) const
216 out
<< "(" << *expr_
<< ")?(" << *tru_
<< "):(" << *fal_
<< ")";
219 void PEUnary::dump(ostream
&out
) const
221 out
<< op_
<< "(" << *expr_
<< ")";
224 void PEBinary::dump(ostream
&out
) const
226 out
<< "(" << *left_
<< ")";
253 out
<< "(" << *right_
<< ")";
257 void PWire::dump(ostream
&out
, unsigned ind
) const
259 out
<< setw(ind
) << "" << type_
;
261 switch (port_type_
) {
262 case NetNet::PIMPLICIT
:
263 out
<< " implicit input";
268 case NetNet::POUTPUT
:
274 case NetNet::NOT_A_PORT
:
278 out
<< " " << data_type_
;
285 if (port_msb_
== 0) {
286 out
<< " port<scalar>";
288 out
<< " port[" << *port_msb_
<< ":" << *port_lsb_
<< "]";
293 out
<< " net<scalar>";
295 out
<< " net[" << *net_msb_
<< ":" << *net_lsb_
<< "]";
299 out
<< " " << hname_
;
301 // If the wire has indices, dump them.
302 if (lidx_
|| ridx_
) {
304 if (lidx_
) out
<< *lidx_
;
305 if (ridx_
) out
<< ":" << *ridx_
;
310 for (map
<perm_string
,PExpr
*>::const_iterator idx
= attributes
.begin()
311 ; idx
!= attributes
.end()
313 out
<< " " << (*idx
).first
;
315 out
<< " = " << *(*idx
).second
;
320 void PGate::dump_pins(ostream
&out
) const
323 if (pin(0)) out
<< *pin(0);
325 for (unsigned idx
= 1 ; idx
< pin_count() ; idx
+= 1) {
327 if (pin(idx
)) out
<< *pin(idx
);
332 void PDelays::dump_delays(ostream
&out
) const
334 if (delay_
[0] && delay_
[1] && delay_
[2])
335 out
<< "#(" << *delay_
[0] << "," << *delay_
[1] << "," <<
338 out
<< "#" << *delay_
[0];
344 void PGate::dump_delays(ostream
&out
) const
346 delay_
.dump_delays(out
);
349 void PGate::dump(ostream
&out
, unsigned ind
) const
351 out
<< setw(ind
) << "" << typeid(*this).name() << " ";
352 delay_
.dump_delays(out
);
353 out
<< " " << get_name() << "(";
359 void PGAssign::dump(ostream
&out
, unsigned ind
) const
361 out
<< setw(ind
) << "";
362 out
<< "assign (" << strength0() << "0 " << strength1() << "1) ";
364 out
<< " " << *pin(0) << " = " << *pin(1) << ";" << endl
;
367 void PGBuiltin::dump(ostream
&out
, unsigned ind
) const
369 out
<< setw(ind
) << "";
371 case PGBuiltin::BUFIF0
:
374 case PGBuiltin::BUFIF1
:
377 case PGBuiltin::NOTIF0
:
380 case PGBuiltin::NOTIF1
:
383 case PGBuiltin::NAND
:
386 case PGBuiltin::NMOS
:
389 case PGBuiltin::RNMOS
:
392 case PGBuiltin::RPMOS
:
395 case PGBuiltin::PMOS
:
398 case PGBuiltin::RCMOS
:
401 case PGBuiltin::CMOS
:
405 out
<< "builtin gate ";
408 out
<< "(" << strength0() << "0 " << strength1() << "1) ";
410 out
<< " " << get_name();
413 out
<< " [" << *msb_
<< ":" << *lsb_
<< "]";
421 void PGModule::dump(ostream
&out
, unsigned ind
) const
423 out
<< setw(ind
) << "" << type_
<< " ";
425 // If parameters are overridden by order, dump them.
426 if (overrides_
&& overrides_
->count() > 0) {
430 if ((*overrides_
)[0] == 0)
433 out
<< *((*overrides_
)[0]);
434 for (unsigned idx
= 1 ; idx
< overrides_
->count() ; idx
+= 1) {
435 out
<< "," << *((*overrides_
)[idx
]);
440 // If parameters are overridden by name, dump them.
442 assert(overrides_
== 0);
444 out
<< "." << parms_
[0].name
<< "(" << *parms_
[0].parm
<< ")";
445 for (unsigned idx
= 1 ; idx
< nparms_
; idx
+= 1) {
446 out
<< ", ." << parms_
[idx
].name
<< "(" <<
447 *parms_
[idx
].parm
<< ")";
454 // If the module is arrayed, print the index expressions.
457 if (msb_
) out
<< *msb_
;
459 if (lsb_
) out
<< *lsb_
;
465 out
<< "." << pins_
[0].name
<< "(";
466 if (pins_
[0].parm
) out
<< *pins_
[0].parm
;
468 for (unsigned idx
= 1 ; idx
< npins_
; idx
+= 1) {
469 out
<< ", ." << pins_
[idx
].name
<< "(";
471 out
<< *pins_
[idx
].parm
;
480 void Statement::dump(ostream
&out
, unsigned ind
) const
482 /* I give up. I don't know what type this statement is,
483 so just print the C++ typeid and let the user figure
485 out
<< setw(ind
) << "";
486 out
<< "/* " << get_line() << ": " << typeid(*this).name()
490 void PAssign::dump(ostream
&out
, unsigned ind
) const
492 out
<< setw(ind
) << "";
493 out
<< *lval() << " = " << delay_
<< " " << *rval() << ";";
494 out
<< " /* " << get_line() << " */" << endl
;
497 void PAssignNB::dump(ostream
&out
, unsigned ind
) const
499 out
<< setw(ind
) << "";
500 out
<< *lval() << " <= " << delay_
<< " " << *rval() << ";";
501 out
<< " /* " << get_line() << " */" << endl
;
504 void PBlock::dump(ostream
&out
, unsigned ind
) const
506 out
<< setw(ind
) << "" << "begin";
508 out
<< " : " << name_
;
511 for (unsigned idx
= 0 ; idx
< list_
.count() ; idx
+= 1) {
513 list_
[idx
]->dump(out
, ind
+2);
515 out
<< setw(ind
+2) << "" << "/* NOOP */ ;" << endl
;
518 out
<< setw(ind
) << "" << "end" << endl
;
521 void PCallTask::dump(ostream
&out
, unsigned ind
) const
523 out
<< setw(ind
) << "" << path_
;
525 if (parms_
.count() > 0) {
530 for (unsigned idx
= 1 ; idx
< parms_
.count() ; idx
+= 1) {
538 out
<< "; /* " << get_line() << " */" << endl
;
541 void PCase::dump(ostream
&out
, unsigned ind
) const
543 out
<< setw(ind
) << "";
555 out
<< " (" << *expr_
<< ") /* " << get_line() << " */" << endl
;
557 for (unsigned idx
= 0 ; idx
< items_
->count() ; idx
+= 1) {
558 PCase::Item
*cur
= (*items_
)[idx
];
560 if (cur
->expr
.count() == 0) {
561 out
<< setw(ind
+2) << "" << "default:";
564 out
<< setw(ind
+2) << "" << *cur
->expr
[0];
566 for(unsigned e
= 1 ; e
< cur
->expr
.count() ; e
+= 1)
567 out
<< ", " << *cur
->expr
[e
];
574 cur
->stat
->dump(out
, ind
+6);
580 out
<< setw(ind
) << "" << "endcase" << endl
;
583 void PCondit::dump(ostream
&out
, unsigned ind
) const
585 out
<< setw(ind
) << "" << "if (" << *expr_
<< ")" << endl
;
587 if_
->dump(out
, ind
+3);
589 out
<< setw(ind
) << ";" << endl
;
591 out
<< setw(ind
) << "" << "else" << endl
;
592 else_
->dump(out
, ind
+3);
596 void PCAssign::dump(ostream
&out
, unsigned ind
) const
598 out
<< setw(ind
) << "" << "assign " << *lval_
<< " = " << *expr_
599 << "; /* " << get_line() << " */" << endl
;
602 void PDeassign::dump(ostream
&out
, unsigned ind
) const
604 out
<< setw(ind
) << "" << "deassign " << *lval_
<< "; /* "
605 << get_line() << " */" << endl
;
608 void PDelayStatement::dump(ostream
&out
, unsigned ind
) const
610 out
<< setw(ind
) << "" << "#" << *delay_
<< " /* " <<
614 statement_
->dump(out
, ind
+2);
616 out
<< " /* noop */;" << endl
;
620 void PDisable::dump(ostream
&out
, unsigned ind
) const
622 out
<< setw(ind
) << "" << "disable " << scope_
<< "; /* "
623 << get_line() << " */" << endl
;
626 void PEventStatement::dump(ostream
&out
, unsigned ind
) const
628 if (expr_
.count() == 0) {
629 out
<< setw(ind
) << "" << "@* ";
632 out
<< setw(ind
) << "" << "@(" << *(expr_
[0]);
633 if (expr_
.count() > 1)
634 for (unsigned idx
= 1 ; idx
< expr_
.count() ; idx
+= 1)
635 out
<< " or " << *(expr_
[idx
]);
642 statement_
->dump(out
, ind
+2);
648 void PForce::dump(ostream
&out
, unsigned ind
) const
650 out
<< setw(ind
) << "" << "force " << *lval_
<< " = " << *expr_
651 << "; /* " << get_line() << " */" << endl
;
654 void PForever::dump(ostream
&out
, unsigned ind
) const
656 out
<< setw(ind
) << "" << "forever /* " << get_line() << " */" << endl
;
657 statement_
->dump(out
, ind
+3);
660 void PForStatement::dump(ostream
&out
, unsigned ind
) const
662 out
<< setw(ind
) << "" << "for (" << *name1_
<< " = " << *expr1_
663 << "; " << *cond_
<< "; " << *name2_
<< " = " << *expr2_
<<
665 statement_
->dump(out
, ind
+3);
668 void PFunction::dump(ostream
&out
, unsigned ind
) const
670 out
<< setw(ind
) << "" << "function ";
671 switch (return_type_
.type
) {
695 if (return_type_
.range
) {
700 out
<< name_
<< ";" << endl
;
703 for (unsigned idx
= 0 ; idx
< ports_
->count() ; idx
+= 1) {
704 out
<< setw(ind
) << "";
706 out
<< (*ports_
)[idx
]->path() << ";" << endl
;
710 statement_
->dump(out
, ind
);
712 out
<< setw(ind
) << "" << "/* NOOP */" << endl
;
715 void PRelease::dump(ostream
&out
, unsigned ind
) const
717 out
<< setw(ind
) << "" << "release " << *lval_
<< "; /* "
718 << get_line() << " */" << endl
;
721 void PRepeat::dump(ostream
&out
, unsigned ind
) const
723 out
<< setw(ind
) << "" << "repeat (" << *expr_
<< ")" << endl
;
724 statement_
->dump(out
, ind
+3);
727 void PTask::dump(ostream
&out
, unsigned ind
) const
730 for (unsigned idx
= 0 ; idx
< ports_
->count() ; idx
+= 1) {
731 out
<< setw(ind
) << "";
732 switch ((*ports_
)[idx
]->get_port_type()) {
736 case NetNet::POUTPUT
:
746 out
<< (*ports_
)[idx
]->path() << ";" << endl
;
750 statement_
->dump(out
, ind
);
752 out
<< setw(ind
) << "" << "/* NOOP */" << endl
;
755 void PTrigger::dump(ostream
&out
, unsigned ind
) const
757 out
<< setw(ind
) << "" << "-> " << event_
<< ";" << endl
;
760 void PWhile::dump(ostream
&out
, unsigned ind
) const
762 out
<< setw(ind
) << "" << "while (" << *cond_
<< ")" << endl
;
763 statement_
->dump(out
, ind
+3);
766 void PProcess::dump(ostream
&out
, unsigned ind
) const
769 case PProcess::PR_INITIAL
:
770 out
<< setw(ind
) << "" << "initial";
772 case PProcess::PR_ALWAYS
:
773 out
<< setw(ind
) << "" << "always";
777 out
<< " /* " << get_line() << " */" << endl
;
779 for (map
<perm_string
,PExpr
*>::const_iterator idx
= attributes
.begin()
780 ; idx
!= attributes
.end() ; idx
++ ) {
782 out
<< setw(ind
+2) << "" << "(* " << (*idx
).first
;
784 out
<< " = " << *(*idx
).second
;
786 out
<< " *)" << endl
;
789 statement_
->dump(out
, ind
+2);
792 void PSpecPath::dump(std::ostream
&out
, unsigned ind
) const
794 out
<< setw(ind
) << "" << "specify path ";
797 out
<< "if (" << *condition
<< ") ";
807 for (unsigned idx
= 0 ; idx
< src
.size() ; idx
+= 1) {
808 if (idx
> 0) out
<< ", ";
815 if (data_source_expression
)
818 for (unsigned idx
= 0 ; idx
< dst
.size() ; idx
+= 1) {
819 if (idx
> 0) out
<< ", ";
824 if (data_source_expression
)
825 out
<< " : " << *data_source_expression
<< ")";
828 for (unsigned idx
= 0 ; idx
< delays
.size() ; idx
+= 1) {
829 if (idx
> 0) out
<< ", ";
836 void PGenerate::dump(ostream
&out
, unsigned indent
) const
838 out
<< setw(indent
) << "" << "generate(" << id_number
<< ")";
840 switch (scheme_type
) {
847 << "; " << *loop_test
848 << "; " << loop_index
849 << "=" << *loop_step
<< ")";
852 out
<< " if (" << *loop_test
<< ")";
855 out
<< " else !(" << *loop_test
<< ")";
860 out
<< " : " << scope_name
;
864 for (map
<pform_name_t
,PWire
*>::const_iterator idx
= wires
.begin()
865 ; idx
!= wires
.end() ; idx
++) {
867 (*idx
).second
->dump(out
, indent
+2);
870 for (list
<PGate
*>::const_iterator idx
= gates
.begin()
871 ; idx
!= gates
.end() ; idx
++) {
872 (*idx
)->dump(out
, indent
+2);
875 for (list
<PProcess
*>::const_iterator idx
= behaviors
.begin()
876 ; idx
!= behaviors
.end() ; idx
++) {
877 (*idx
)->dump(out
, indent
+2);
880 for (list
<PGenerate
*>::const_iterator idx
= generates
.begin()
881 ; idx
!= generates
.end() ; idx
++) {
882 (*idx
)->dump(out
, indent
+2);
885 out
<< " endgenerate" << endl
;
888 void Module::dump(ostream
&out
) const
890 if (attributes
.begin() != attributes
.end()) {
892 for (map
<perm_string
,PExpr
*>::const_iterator idx
= attributes
.begin()
893 ; idx
!= attributes
.end() ; idx
++ ) {
894 if (idx
!= attributes
.begin()) {
899 out
<< " = " << *(*idx
).second
;
905 out
<< "module " << name_
<< ";" << endl
;
907 for (unsigned idx
= 0 ; idx
< ports
.count() ; idx
+= 1) {
908 port_t
*cur
= ports
[idx
];
911 out
<< " unconnected" << endl
;
915 out
<< " ." << cur
->name
<< "(" << *cur
->expr
[0];
916 for (unsigned wdx
= 1 ; wdx
< cur
->expr
.count() ; wdx
+= 1) {
917 out
<< ", " << *cur
->expr
[wdx
];
923 typedef map
<perm_string
,param_expr_t
>::const_iterator parm_iter_t
;
924 typedef map
<pform_name_t
,PExpr
*>::const_iterator parm_hiter_t
;
925 for (parm_iter_t cur
= parameters
.begin()
926 ; cur
!= parameters
.end() ; cur
++) {
927 out
<< " parameter ";
928 if ((*cur
).second
.signed_flag
)
930 if ((*cur
).second
.msb
)
931 out
<< "[" << *(*cur
).second
.msb
<< ":"
932 << *(*cur
).second
.lsb
<< "] ";
933 out
<< (*cur
).first
<< " = ";
934 if ((*cur
).second
.expr
)
935 out
<< *(*cur
).second
.expr
<< ";" << endl
;
937 out
<< "/* ERROR */;" << endl
;
940 for (parm_iter_t cur
= localparams
.begin()
941 ; cur
!= localparams
.end() ; cur
++) {
942 out
<< " localparam ";
943 if ((*cur
).second
.msb
)
944 out
<< "[" << *(*cur
).second
.msb
<< ":"
945 << *(*cur
).second
.lsb
<< "] ";
946 out
<< (*cur
).first
<< " = ";
947 if ((*cur
).second
.expr
)
948 out
<< *(*cur
).second
.expr
<< ";" << endl
;
950 out
<< "/* ERROR */;" << endl
;
953 typedef list
<perm_string
>::const_iterator genvar_iter_t
;
954 for (genvar_iter_t cur
= genvars
.begin()
955 ; cur
!= genvars
.end() ; cur
++) {
956 out
<< " genvar " << (*cur
) << ";" << endl
;
959 typedef list
<PGenerate
*>::const_iterator genscheme_iter_t
;
960 for (genscheme_iter_t cur
= generate_schemes
.begin()
961 ; cur
!= generate_schemes
.end() ; cur
++) {
962 (*cur
)->dump(out
, 4);
965 typedef map
<perm_string
,PExpr
*>::const_iterator specparm_iter_t
;
966 for (specparm_iter_t cur
= specparams
.begin()
967 ; cur
!= specparams
.end() ; cur
++) {
968 out
<< " specparam " << (*cur
).first
<< " = "
969 << *(*cur
).second
<< ";" << endl
;
972 for (parm_hiter_t cur
= defparms
.begin()
973 ; cur
!= defparms
.end() ; cur
++) {
974 out
<< " defparam " << (*cur
).first
<< " = ";
976 out
<< *(*cur
).second
<< ";" << endl
;
978 out
<< "/* ERROR */;" << endl
;
981 for (map
<perm_string
,PEvent
*>::const_iterator cur
= events
.begin()
982 ; cur
!= events
.end() ; cur
++ ) {
983 PEvent
*ev
= (*cur
).second
;
984 out
<< " event " << ev
->name() << "; // "
985 << ev
->get_line() << endl
;
988 // Iterate through and display all the wires.
989 for (map
<pform_name_t
,PWire
*>::const_iterator wire
= wires_
.begin()
990 ; wire
!= wires_
.end()
993 (*wire
).second
->dump(out
);
996 // Dump the task definitions.
997 typedef map
<perm_string
,PTask
*>::const_iterator task_iter_t
;
998 for (task_iter_t cur
= tasks_
.begin()
999 ; cur
!= tasks_
.end() ; cur
++) {
1000 out
<< " task " << (*cur
).first
<< ";" << endl
;
1001 (*cur
).second
->dump(out
, 6);
1002 out
<< " endtask;" << endl
;
1005 // Dump the function definitions.
1006 typedef map
<perm_string
,PFunction
*>::const_iterator func_iter_t
;
1007 for (func_iter_t cur
= funcs_
.begin()
1008 ; cur
!= funcs_
.end() ; cur
++) {
1009 out
<< " function " << (*cur
).first
<< ";" << endl
;
1010 (*cur
).second
->dump(out
, 6);
1011 out
<< " endfunction;" << endl
;
1015 // Iterate through and display all the gates
1016 for (list
<PGate
*>::const_iterator gate
= gates_
.begin()
1017 ; gate
!= gates_
.end()
1024 for (list
<PProcess
*>::const_iterator behav
= behaviors_
.begin()
1025 ; behav
!= behaviors_
.end()
1028 (*behav
)->dump(out
, 4);
1031 for (list
<PSpecPath
*>::const_iterator spec
= specify_paths
.begin()
1032 ; spec
!= specify_paths
.end()
1035 (*spec
)->dump(out
, 4);
1038 out
<< "endmodule" << endl
;
1041 void pform_dump(ostream
&out
, Module
*mod
)
1046 void PUdp::dump(ostream
&out
) const
1048 out
<< "primitive " << name_
<< "(" << ports
[0];
1049 for (unsigned idx
= 1 ; idx
< ports
.count() ; idx
+= 1)
1050 out
<< ", " << ports
[idx
];
1051 out
<< ");" << endl
;
1054 out
<< " reg " << ports
[0] << ";" << endl
;
1056 out
<< " table" << endl
;
1057 for (unsigned idx
= 0 ; idx
< tinput
.count() ; idx
+= 1) {
1059 for (unsigned chr
= 0 ; chr
< tinput
[idx
].length() ; chr
+= 1)
1060 out
<< " " << tinput
[idx
][chr
];
1063 out
<< " : " << tcurrent
[idx
];
1065 out
<< " : " << toutput
[idx
] << " ;" << endl
;
1067 out
<< " endtable" << endl
;
1070 out
<< " initial " << ports
[0] << " = 1'b" << initial
1073 // Dump the attributes for the primitive as attribute
1075 for (map
<string
,PExpr
*>::const_iterator idx
= attributes
.begin()
1076 ; idx
!= attributes
.end()
1078 out
<< " attribute " << (*idx
).first
;
1080 out
<< " = " << *(*idx
).second
;
1084 out
<< "endprimitive" << endl
;