1 /*
2 * Copyright (C) 2010-2020 Cary R. (cygcary@yahoo.com)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 *
19 * This is the vlog95 target module. It generates a 1364-1995 compliant
20 * netlist from the input netlist. The generated netlist is expected to
21 * be simulation equivalent to the original.
22 */
23
24 # include "version_base.h"
25 # include "version_tag.h"
26 # include "config.h"
27 # include "vlog95_priv.h"
28 # include <stdlib.h>
29 # include <string.h>
30
31 static const char*version_string =
32 "Icarus Verilog VLOG95 Code Generator " VERSION " (" VERSION_TAG ")\n\n"
33 "Copyright (C) 2010-2020 Cary R. (cygcary@yahoo.com)\n\n"
34 " This program is free software; you can redistribute it and/or modify\n"
35 " it under the terms of the GNU General Public License as published by\n"
36 " the Free Software Foundation; either version 2 of the License, or\n"
37 " (at your option) any later version.\n\n"
38 " This program is distributed in the hope that it will be useful,\n"
39 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
40 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
41 " GNU General Public License for more details.\n\n"
42 " You should have received a copy of the GNU General Public License along\n"
43 " with this program; if not, write to the Free Software Foundation, Inc.,\n"
44 " 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n"
45 ;
46
47 FILE*vlog_out;
48 int vlog_errors = 0;
49 int sim_precision = 0;
50 unsigned indent = 0;
51 unsigned indent_incr = 2;
52
53 unsigned emit_file_line = 0;
54
55 unsigned allow_signed = 0;
56
57 ivl_design_t design = 0;
58
target_design(ivl_design_t des)59 int target_design(ivl_design_t des)
60 {
61 ivl_scope_t *roots;
62 unsigned nroots, idx;
63 const char*path = ivl_design_flag(des, "-o");
64 /* Set the indent spacing with the -pspacing flag passed to iverilog
65 * (e.g. -pspacing=4). The default is 2 spaces. */
66 const char*spacing_str = ivl_design_flag(des, "spacing");
67 /* Use -pfileline to determine if file and line information is
68 * printed for most lines. (e.g. -pfileline=1). The default is no
69 * file/line information will be printed for individual lines. */
70 const char*fileline_str = ivl_design_flag(des, "fileline");
71 /* Use -pallowsigned to allow signed registers/nets and the
72 * $signed() and $unsigned() system tasks as an extension. */
73 const char*allowsigned_str = ivl_design_flag(des, "allowsigned");
74 assert(path);
75
76 /* Check for and use a provided indent spacing. */
77 if (strcmp(spacing_str, "") != 0) {
78 char *eptr;
79 long value = strtol(spacing_str, &eptr, 0);
80 /* Nothing usable in the spacing string. */
81 if (spacing_str == eptr) {
82 fprintf(stderr, "vlog95 error: Unable to extract spacing "
83 "increment from string: %s\n", spacing_str);
84 return 1;
85 }
86 /* Extra stuff at the end. */
87 if (*eptr != 0) {
88 fprintf(stderr, "vlog95 error: Extra characters '%s' "
89 "included at end of spacing string: %s\n",
90 eptr, spacing_str);
91 return 1;
92 }
93 /* The increment must be greater than zero. */
94 if (value < 1) {
95 fprintf(stderr, "vlog95 error: Spacing increment (%ld) must "
96 "be greater than zero.\n", value);
97 return 1;
98 }
99 /* An increment of more than sixteen is too much. */
100 if (value > 16) {
101 fprintf(stderr, "vlog95 error: Spacing increment (%ld) must "
102 "be sixteen or less.\n", value);
103 return 1;
104 }
105 indent_incr = value;
106 }
107
108 /* Check to see if file/line information should be printed. */
109 if (strcmp(fileline_str, "") != 0) {
110 char *eptr;
111 long value = strtol(fileline_str, &eptr, 0);
112 /* Nothing usable in the file/line string. */
113 if (fileline_str == eptr) {
114 fprintf(stderr, "vlog95 error: Unable to extract file/line "
115 "information from string: %s\n",
116 fileline_str);
117 return 1;
118 }
119 /* Extra stuff at the end. */
120 if (*eptr != 0) {
121 fprintf(stderr, "vlog95 error: Extra characters '%s' "
122 "included at end of file/line string: %s\n",
123 eptr, fileline_str);
124 return 1;
125 }
126 /* The file/line flag must be positive. */
127 if (value < 0) {
128 fprintf(stderr, "vlog95 error: File/line flag (%ld) must "
129 "be positive.\n", value);
130 return 1;
131 }
132 emit_file_line = value > 0;
133 }
134
135 /* Check to see if we should also print signed constructs. */
136 if (strcmp(allowsigned_str, "") != 0) {
137 char *eptr;
138 long value = strtol(allowsigned_str, &eptr, 0);
139 /* Nothing usable in the allow signed string. */
140 if (allowsigned_str == eptr) {
141 fprintf(stderr, "vlog95 error: Unable to extract allow "
142 "signed information from string: %s\n",
143 allowsigned_str);
144 return 1;
145 }
146 /* Extra stuff at the end. */
147 if (*eptr != 0) {
148 fprintf(stderr, "vlog95 error: Extra characters '%s' "
149 "included at end of allow signed string: "
150 "%s\n", eptr, allowsigned_str);
151 return 1;
152 }
153 /* The allow signed flag must be positive. */
154 if (value < 0) {
155 fprintf(stderr, "vlog95 error: Allow signed flag (%ld) must "
156 "be positive.\n", value);
157 return 1;
158 }
159 allow_signed = value > 0;
160 }
161
162 design = des;
163
164 #ifdef HAVE_FOPEN64
165 vlog_out = fopen64(path, "w");
166 #else
167 vlog_out = fopen(path, "w");
168 #endif
169 if (vlog_out == 0) {
170 perror(path);
171 return -1;
172 }
173
174 fprintf(vlog_out, "/*\n");
175 fprintf(vlog_out, " * 1364-1995 Verilog generated by Icarus Verilog "
176 "VLOG95 Code Generator,\n");
177 fprintf(vlog_out, " * Version: " VERSION " (" VERSION_TAG ")\n");
178 fprintf(vlog_out, " * Converted using %s delays and %s signed support.\n",
179 ivl_design_delay_sel(des),
180 allow_signed ? "with" : "without");
181 fprintf(vlog_out, " */\n");
182
183 sim_precision = ivl_design_time_precision(des);
184
185 /* Get all the root modules and then convert each one. */
186 ivl_design_roots(des, &roots, &nroots);
187 /* Emit any root scope tasks or functions first. */
188 for (idx = 0; idx < nroots; idx += 1) {
189 switch(ivl_scope_type(roots[idx])) {
190 case IVL_SCT_FUNCTION:
191 case IVL_SCT_TASK:
192 /* Create a separate module for each task/function.
193 This allows us to handle different timescales. */
194 fprintf(vlog_out, "\n`timescale %s/%s\n",
195 get_time_const(ivl_scope_time_units(roots[idx])),
196 get_time_const(ivl_scope_time_precision(roots[idx])));
197 fprintf(vlog_out, "module ivl_root_scope_%s;\n",
198 ivl_scope_basename(roots[idx]));
199 indent += indent_incr;
200
201 /* Say this task/function has a parent so the
202 * definition is emitted correctly. */
203 emit_scope(roots[idx], roots[idx]);
204
205 indent -= indent_incr;
206 assert(indent == 0);
207 fprintf(vlog_out, "endmodule /* ivl_root_scope_%p */\n",
208 roots[idx]);
209 break;
210 default:
211 break;
212 }
213 }
214 /* Emit the rest of the scope objects. */
215 for (idx = 0; idx < nroots; idx += 1) emit_scope(roots[idx], 0);
216
217 free_emitted_scope_list();
218
219 /* Emit any UDP definitions that the design used. */
220 emit_udp_list();
221
222 /* Emit any UDPs that are Icarus generated (D-FF or latch). */
223 emit_icarus_generated_udps();
224
225 /* Emit the Icarus top module used to trigger translated always_comb/latch processes at T0. */
226 emit_icarus_generated_top_module();
227
228 /* If there were errors then add this information to the output. */
229 if (vlog_errors) {
230 fprintf(vlog_out, "\n");
231 fprintf(vlog_out, "/*\n");
232 if (vlog_errors == 1) {
233 fprintf(vlog_out, " * There was 1 error during "
234 "translation.\n");
235 } else {
236 fprintf(vlog_out, " * There were %d errors during "
237 "translation.\n",
238 vlog_errors);
239 }
240 fprintf(vlog_out, " */\n");
241 /* Add something that makes the file invalid to make sure
242 * the user knows there were errors. */
243 fprintf(vlog_out, "<Add some text to make sure this file is not "
244 "valid Verilog>\n");
245 }
246
247 fclose(vlog_out);
248
249 /* A do nothing call to prevent warnings about this routine not
250 * being used. */
251 dump_nexus_information(0, 0);
252
253 return vlog_errors;
254 }
255
256
target_query(const char * key)257 const char* target_query(const char*key)
258 {
259 if (strcmp(key,"version") == 0) return version_string;
260
261 return 0;
262 }
263