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
:
399 out
<< "builtin gate ";
402 out
<< "(" << strength0() << "0 " << strength1() << "1) ";
404 out
<< " " << get_name();
407 out
<< " [" << *msb_
<< ":" << *lsb_
<< "]";
415 void PGModule::dump(ostream
&out
, unsigned ind
) const
417 out
<< setw(ind
) << "" << type_
<< " ";
419 // If parameters are overridden by order, dump them.
420 if (overrides_
&& overrides_
->count() > 0) {
424 if ((*overrides_
)[0] == 0)
427 out
<< *((*overrides_
)[0]);
428 for (unsigned idx
= 1 ; idx
< overrides_
->count() ; idx
+= 1) {
429 out
<< "," << *((*overrides_
)[idx
]);
434 // If parameters are overridden by name, dump them.
436 assert(overrides_
== 0);
438 out
<< "." << parms_
[0].name
<< "(" << *parms_
[0].parm
<< ")";
439 for (unsigned idx
= 1 ; idx
< nparms_
; idx
+= 1) {
440 out
<< ", ." << parms_
[idx
].name
<< "(" <<
441 *parms_
[idx
].parm
<< ")";
448 // If the module is arrayed, print the index expressions.
451 if (msb_
) out
<< *msb_
;
453 if (lsb_
) out
<< *lsb_
;
459 out
<< "." << pins_
[0].name
<< "(";
460 if (pins_
[0].parm
) out
<< *pins_
[0].parm
;
462 for (unsigned idx
= 1 ; idx
< npins_
; idx
+= 1) {
463 out
<< ", ." << pins_
[idx
].name
<< "(";
465 out
<< *pins_
[idx
].parm
;
474 void Statement::dump(ostream
&out
, unsigned ind
) const
476 /* I give up. I don't know what type this statement is,
477 so just print the C++ typeid and let the user figure
479 out
<< setw(ind
) << "";
480 out
<< "/* " << get_line() << ": " << typeid(*this).name()
484 void PAssign::dump(ostream
&out
, unsigned ind
) const
486 out
<< setw(ind
) << "";
487 out
<< *lval() << " = " << delay_
<< " " << *rval() << ";";
488 out
<< " /* " << get_line() << " */" << endl
;
491 void PAssignNB::dump(ostream
&out
, unsigned ind
) const
493 out
<< setw(ind
) << "";
494 out
<< *lval() << " <= " << delay_
<< " " << *rval() << ";";
495 out
<< " /* " << get_line() << " */" << endl
;
498 void PBlock::dump(ostream
&out
, unsigned ind
) const
500 out
<< setw(ind
) << "" << "begin";
502 out
<< " : " << name_
;
505 for (unsigned idx
= 0 ; idx
< list_
.count() ; idx
+= 1) {
507 list_
[idx
]->dump(out
, ind
+2);
509 out
<< setw(ind
+2) << "" << "/* NOOP */ ;" << endl
;
512 out
<< setw(ind
) << "" << "end" << endl
;
515 void PCallTask::dump(ostream
&out
, unsigned ind
) const
517 out
<< setw(ind
) << "" << path_
;
519 if (parms_
.count() > 0) {
524 for (unsigned idx
= 1 ; idx
< parms_
.count() ; idx
+= 1) {
532 out
<< "; /* " << get_line() << " */" << endl
;
535 void PCase::dump(ostream
&out
, unsigned ind
) const
537 out
<< setw(ind
) << "";
549 out
<< " (" << *expr_
<< ") /* " << get_line() << " */" << endl
;
551 for (unsigned idx
= 0 ; idx
< items_
->count() ; idx
+= 1) {
552 PCase::Item
*cur
= (*items_
)[idx
];
554 if (cur
->expr
.count() == 0) {
555 out
<< setw(ind
+2) << "" << "default:";
558 out
<< setw(ind
+2) << "" << *cur
->expr
[0];
560 for(unsigned e
= 1 ; e
< cur
->expr
.count() ; e
+= 1)
561 out
<< ", " << *cur
->expr
[e
];
568 cur
->stat
->dump(out
, ind
+6);
574 out
<< setw(ind
) << "" << "endcase" << endl
;
577 void PCondit::dump(ostream
&out
, unsigned ind
) const
579 out
<< setw(ind
) << "" << "if (" << *expr_
<< ")" << endl
;
581 if_
->dump(out
, ind
+3);
583 out
<< setw(ind
) << ";" << endl
;
585 out
<< setw(ind
) << "" << "else" << endl
;
586 else_
->dump(out
, ind
+3);
590 void PCAssign::dump(ostream
&out
, unsigned ind
) const
592 out
<< setw(ind
) << "" << "assign " << *lval_
<< " = " << *expr_
593 << "; /* " << get_line() << " */" << endl
;
596 void PDeassign::dump(ostream
&out
, unsigned ind
) const
598 out
<< setw(ind
) << "" << "deassign " << *lval_
<< "; /* "
599 << get_line() << " */" << endl
;
602 void PDelayStatement::dump(ostream
&out
, unsigned ind
) const
604 out
<< setw(ind
) << "" << "#" << *delay_
<< " /* " <<
608 statement_
->dump(out
, ind
+2);
610 out
<< " /* noop */;" << endl
;
614 void PDisable::dump(ostream
&out
, unsigned ind
) const
616 out
<< setw(ind
) << "" << "disable " << scope_
<< "; /* "
617 << get_line() << " */" << endl
;
620 void PEventStatement::dump(ostream
&out
, unsigned ind
) const
622 if (expr_
.count() == 0) {
623 out
<< setw(ind
) << "" << "@* ";
626 out
<< setw(ind
) << "" << "@(" << *(expr_
[0]);
627 if (expr_
.count() > 1)
628 for (unsigned idx
= 1 ; idx
< expr_
.count() ; idx
+= 1)
629 out
<< " or " << *(expr_
[idx
]);
636 statement_
->dump(out
, ind
+2);
642 void PForce::dump(ostream
&out
, unsigned ind
) const
644 out
<< setw(ind
) << "" << "force " << *lval_
<< " = " << *expr_
645 << "; /* " << get_line() << " */" << endl
;
648 void PForever::dump(ostream
&out
, unsigned ind
) const
650 out
<< setw(ind
) << "" << "forever /* " << get_line() << " */" << endl
;
651 statement_
->dump(out
, ind
+3);
654 void PForStatement::dump(ostream
&out
, unsigned ind
) const
656 out
<< setw(ind
) << "" << "for (" << *name1_
<< " = " << *expr1_
657 << "; " << *cond_
<< "; " << *name2_
<< " = " << *expr2_
<<
659 statement_
->dump(out
, ind
+3);
662 void PFunction::dump(ostream
&out
, unsigned ind
) const
664 out
<< setw(ind
) << "" << "function ";
665 switch (return_type_
.type
) {
689 if (return_type_
.range
) {
694 out
<< name_
<< ";" << endl
;
697 for (unsigned idx
= 0 ; idx
< ports_
->count() ; idx
+= 1) {
698 out
<< setw(ind
) << "";
700 out
<< (*ports_
)[idx
]->path() << ";" << endl
;
704 statement_
->dump(out
, ind
);
706 out
<< setw(ind
) << "" << "/* NOOP */" << endl
;
709 void PRelease::dump(ostream
&out
, unsigned ind
) const
711 out
<< setw(ind
) << "" << "release " << *lval_
<< "; /* "
712 << get_line() << " */" << endl
;
715 void PRepeat::dump(ostream
&out
, unsigned ind
) const
717 out
<< setw(ind
) << "" << "repeat (" << *expr_
<< ")" << endl
;
718 statement_
->dump(out
, ind
+3);
721 void PTask::dump(ostream
&out
, unsigned ind
) const
724 for (unsigned idx
= 0 ; idx
< ports_
->count() ; idx
+= 1) {
725 out
<< setw(ind
) << "";
726 switch ((*ports_
)[idx
]->get_port_type()) {
730 case NetNet::POUTPUT
:
740 out
<< (*ports_
)[idx
]->path() << ";" << endl
;
744 statement_
->dump(out
, ind
);
746 out
<< setw(ind
) << "" << "/* NOOP */" << endl
;
749 void PTrigger::dump(ostream
&out
, unsigned ind
) const
751 out
<< setw(ind
) << "" << "-> " << event_
<< ";" << endl
;
754 void PWhile::dump(ostream
&out
, unsigned ind
) const
756 out
<< setw(ind
) << "" << "while (" << *cond_
<< ")" << endl
;
757 statement_
->dump(out
, ind
+3);
760 void PProcess::dump(ostream
&out
, unsigned ind
) const
763 case PProcess::PR_INITIAL
:
764 out
<< setw(ind
) << "" << "initial";
766 case PProcess::PR_ALWAYS
:
767 out
<< setw(ind
) << "" << "always";
771 out
<< " /* " << get_line() << " */" << endl
;
773 for (map
<perm_string
,PExpr
*>::const_iterator idx
= attributes
.begin()
774 ; idx
!= attributes
.end() ; idx
++ ) {
776 out
<< setw(ind
+2) << "" << "(* " << (*idx
).first
;
778 out
<< " = " << *(*idx
).second
;
780 out
<< " *)" << endl
;
783 statement_
->dump(out
, ind
+2);
786 void PSpecPath::dump(std::ostream
&out
, unsigned ind
) const
788 out
<< setw(ind
) << "" << "specify path ";
791 out
<< "if (" << *condition
<< ") ";
801 for (unsigned idx
= 0 ; idx
< src
.size() ; idx
+= 1) {
802 if (idx
> 0) out
<< ", ";
809 if (data_source_expression
)
812 for (unsigned idx
= 0 ; idx
< dst
.size() ; idx
+= 1) {
813 if (idx
> 0) out
<< ", ";
818 if (data_source_expression
)
819 out
<< " : " << *data_source_expression
<< ")";
822 for (unsigned idx
= 0 ; idx
< delays
.size() ; idx
+= 1) {
823 if (idx
> 0) out
<< ", ";
830 void PGenerate::dump(ostream
&out
, unsigned indent
) const
832 out
<< setw(indent
) << "" << "generate(" << id_number
<< ")";
834 switch (scheme_type
) {
841 << "; " << *loop_test
842 << "; " << loop_index
843 << "=" << *loop_step
<< ")";
846 out
<< " if (" << *loop_test
<< ")";
849 out
<< " else !(" << *loop_test
<< ")";
854 out
<< " : " << scope_name
;
858 for (map
<pform_name_t
,PWire
*>::const_iterator idx
= wires
.begin()
859 ; idx
!= wires
.end() ; idx
++) {
861 (*idx
).second
->dump(out
, indent
+2);
864 for (list
<PGate
*>::const_iterator idx
= gates
.begin()
865 ; idx
!= gates
.end() ; idx
++) {
866 (*idx
)->dump(out
, indent
+2);
869 for (list
<PProcess
*>::const_iterator idx
= behaviors
.begin()
870 ; idx
!= behaviors
.end() ; idx
++) {
871 (*idx
)->dump(out
, indent
+2);
874 for (list
<PGenerate
*>::const_iterator idx
= generates
.begin()
875 ; idx
!= generates
.end() ; idx
++) {
876 (*idx
)->dump(out
, indent
+2);
879 out
<< " endgenerate" << endl
;
882 void Module::dump(ostream
&out
) const
884 if (attributes
.begin() != attributes
.end()) {
886 for (map
<perm_string
,PExpr
*>::const_iterator idx
= attributes
.begin()
887 ; idx
!= attributes
.end() ; idx
++ ) {
888 if (idx
!= attributes
.begin()) {
893 out
<< " = " << *(*idx
).second
;
899 out
<< "module " << name_
<< ";" << endl
;
901 for (unsigned idx
= 0 ; idx
< ports
.count() ; idx
+= 1) {
902 port_t
*cur
= ports
[idx
];
905 out
<< " unconnected" << endl
;
909 out
<< " ." << cur
->name
<< "(" << *cur
->expr
[0];
910 for (unsigned wdx
= 1 ; wdx
< cur
->expr
.count() ; wdx
+= 1) {
911 out
<< ", " << *cur
->expr
[wdx
];
917 typedef map
<perm_string
,param_expr_t
>::const_iterator parm_iter_t
;
918 typedef map
<pform_name_t
,PExpr
*>::const_iterator parm_hiter_t
;
919 for (parm_iter_t cur
= parameters
.begin()
920 ; cur
!= parameters
.end() ; cur
++) {
921 out
<< " parameter ";
922 if ((*cur
).second
.signed_flag
)
924 if ((*cur
).second
.msb
)
925 out
<< "[" << *(*cur
).second
.msb
<< ":"
926 << *(*cur
).second
.lsb
<< "] ";
927 out
<< (*cur
).first
<< " = ";
928 if ((*cur
).second
.expr
)
929 out
<< *(*cur
).second
.expr
<< ";" << endl
;
931 out
<< "/* ERROR */;" << endl
;
934 for (parm_iter_t cur
= localparams
.begin()
935 ; cur
!= localparams
.end() ; cur
++) {
936 out
<< " localparam ";
937 if ((*cur
).second
.msb
)
938 out
<< "[" << *(*cur
).second
.msb
<< ":"
939 << *(*cur
).second
.lsb
<< "] ";
940 out
<< (*cur
).first
<< " = ";
941 if ((*cur
).second
.expr
)
942 out
<< *(*cur
).second
.expr
<< ";" << endl
;
944 out
<< "/* ERROR */;" << endl
;
947 typedef list
<perm_string
>::const_iterator genvar_iter_t
;
948 for (genvar_iter_t cur
= genvars
.begin()
949 ; cur
!= genvars
.end() ; cur
++) {
950 out
<< " genvar " << (*cur
) << ";" << endl
;
953 typedef list
<PGenerate
*>::const_iterator genscheme_iter_t
;
954 for (genscheme_iter_t cur
= generate_schemes
.begin()
955 ; cur
!= generate_schemes
.end() ; cur
++) {
956 (*cur
)->dump(out
, 4);
959 typedef map
<perm_string
,PExpr
*>::const_iterator specparm_iter_t
;
960 for (specparm_iter_t cur
= specparams
.begin()
961 ; cur
!= specparams
.end() ; cur
++) {
962 out
<< " specparam " << (*cur
).first
<< " = "
963 << *(*cur
).second
<< ";" << endl
;
966 for (parm_hiter_t cur
= defparms
.begin()
967 ; cur
!= defparms
.end() ; cur
++) {
968 out
<< " defparam " << (*cur
).first
<< " = ";
970 out
<< *(*cur
).second
<< ";" << endl
;
972 out
<< "/* ERROR */;" << endl
;
975 for (map
<perm_string
,PEvent
*>::const_iterator cur
= events
.begin()
976 ; cur
!= events
.end() ; cur
++ ) {
977 PEvent
*ev
= (*cur
).second
;
978 out
<< " event " << ev
->name() << "; // "
979 << ev
->get_line() << endl
;
982 // Iterate through and display all the wires.
983 for (map
<pform_name_t
,PWire
*>::const_iterator wire
= wires_
.begin()
984 ; wire
!= wires_
.end()
987 (*wire
).second
->dump(out
);
990 // Dump the task definitions.
991 typedef map
<perm_string
,PTask
*>::const_iterator task_iter_t
;
992 for (task_iter_t cur
= tasks_
.begin()
993 ; cur
!= tasks_
.end() ; cur
++) {
994 out
<< " task " << (*cur
).first
<< ";" << endl
;
995 (*cur
).second
->dump(out
, 6);
996 out
<< " endtask;" << endl
;
999 // Dump the function definitions.
1000 typedef map
<perm_string
,PFunction
*>::const_iterator func_iter_t
;
1001 for (func_iter_t cur
= funcs_
.begin()
1002 ; cur
!= funcs_
.end() ; cur
++) {
1003 out
<< " function " << (*cur
).first
<< ";" << endl
;
1004 (*cur
).second
->dump(out
, 6);
1005 out
<< " endfunction;" << endl
;
1009 // Iterate through and display all the gates
1010 for (list
<PGate
*>::const_iterator gate
= gates_
.begin()
1011 ; gate
!= gates_
.end()
1018 for (list
<PProcess
*>::const_iterator behav
= behaviors_
.begin()
1019 ; behav
!= behaviors_
.end()
1022 (*behav
)->dump(out
, 4);
1025 for (list
<PSpecPath
*>::const_iterator spec
= specify_paths
.begin()
1026 ; spec
!= specify_paths
.end()
1029 (*spec
)->dump(out
, 4);
1032 out
<< "endmodule" << endl
;
1035 void pform_dump(ostream
&out
, Module
*mod
)
1040 void PUdp::dump(ostream
&out
) const
1042 out
<< "primitive " << name_
<< "(" << ports
[0];
1043 for (unsigned idx
= 1 ; idx
< ports
.count() ; idx
+= 1)
1044 out
<< ", " << ports
[idx
];
1045 out
<< ");" << endl
;
1048 out
<< " reg " << ports
[0] << ";" << endl
;
1050 out
<< " table" << endl
;
1051 for (unsigned idx
= 0 ; idx
< tinput
.count() ; idx
+= 1) {
1053 for (unsigned chr
= 0 ; chr
< tinput
[idx
].length() ; chr
+= 1)
1054 out
<< " " << tinput
[idx
][chr
];
1057 out
<< " : " << tcurrent
[idx
];
1059 out
<< " : " << toutput
[idx
] << " ;" << endl
;
1061 out
<< " endtable" << endl
;
1064 out
<< " initial " << ports
[0] << " = 1'b" << initial
1067 // Dump the attributes for the primitive as attribute
1069 for (map
<string
,PExpr
*>::const_iterator idx
= attributes
.begin()
1070 ; idx
!= attributes
.end()
1072 out
<< " attribute " << (*idx
).first
;
1074 out
<< " = " << *(*idx
).second
;
1078 out
<< "endprimitive" << endl
;