NAPA Compiler V4.50
Author: Yves Leduc, yves.leduc.be@gmail.com
Loading...
Searching...
No Matches
C:/Simulate/Napados/Source/sn.c
Go to the documentation of this file.
1/* ** SORT NODES **************************************************************************************************************** */
2
3#undef EXTERN
4#define EXTERN extern
5
6#include "./napa.h"
7#include "./proto.h"
8
9
10/* *** In this file: ************************************************************************************************************ */
11
12/* void build_node_dependencies(void) */
13/* void build_to_be_delayed_node_list(void) */
14/* void sort_nodes(void) */
15
16
17/* ****************************************************************************************************************************** */
18
19/* "sort_nodes" will rearrange the list of nodes to introduce the necessary path from input to output, including a delay when */
20/* explicitely asked. Delays are sorted first. */
21
22/* Nodes are sorted. Checks are done at the end of sorting. Undetermination is caused by faulty loops (no delay, all delays) or */
23/* missing sources. */
24
25/* A node is determined if it is not depending on any other nodes, or if it is depending on determined nodes only. */
26/* It is assumed that no node is determined at the beginning of the process. A pointer is set to the first entry at start. */
27
28/* This process is awfully long as soon as the number of nodes becomes large. */
29/* A thousand of nodes is enough to slow down significantly the sorting process. */
30
31
32/* ****************************************************************************************************************************** */
33
34/* Build the list of node dependencies, smash directives if any. */
35/* Directives are smashed first to detect non obvious dependencies. */
36
37/* List of dependencies is a list of ID corresponding to nodes in the node definition. If a record is detected, check also for */
38/* hidden node dependencies. Records must be expanded before sorting nodes!If inside a drop segment, look after nodes there! */
39
41 long in1, in2, out;
42 char *str1 = (char*) NULL;
43 char *str2 = (char*) NULL;
44 char tok[STRLENGTH] = {'\0'};
45 char sgn[2] = {'\0'};
46 long num;
47 long *p = (long*) NULL;
48 for (out = 0L; out < Num_Nodes; out++) {
49 num = 0L;
50 str1 = Node_List[out].value;
51 for (;;) { /* count number of nodes in the node definition */
52 str1 = get_sign_and_token(str1, sgn, tok);
53 if (ISEMPTY(tok)) {
54 break;
55 }
56 in1 = node_id(tok);
57 if (UNDEFINED != in1) {
58 num++;
59 }
60 in1 = record_id(tok);
61 if (UNDEFINED != in1) {
62 str2 = Record_List[in1].list1;
63 for (;;) { /* count number of nodes in the record definition */
64 str2 = get_sign_and_token(str2, sgn, tok);
65 if (ISEMPTY(tok)) {
66 break;
67 }
68 in2 = node_id(tok);
69 if (UNDEFINED != in2) {
70 num++;
71 }
72 }
73 }
74 } /* 'num' is the number of nodes in netlist */
75 Node_List[out].depend = (long*) malloc((size_t) ((long) (sizeof (long)) * (num+1L)));
76 if ((long*) NULL == Node_List[out].depend) {
77 print_error_location("node dependency", Node_List[out].mline, Node_List[out].mfile);
78 (void) fprintf(STDERR, " dynamic memory allocation error\n");
80 }
81 p = Node_List[out].depend;
82 str1 = Node_List[out].value;
83 for (;;) {
84 str1 = get_sign_and_token(str1, sgn, tok);
85 if (ISEMPTY(tok)) {
86 break;
87 }
88 in1 = node_id(tok);
89 if (UNDEFINED != in1) {
90 *p = Node_List[in1].ID; /* add node ID to dependency list */
91 p++;
92 }
93 in1 = record_id(tok);
94 if (UNDEFINED != in1) {
95 str2 = Record_List[in1].list1;
96 for (;;) {
97 str2 = get_sign_and_token(str2, sgn, tok);
98 if (ISEMPTY(tok)) {
99 break;
100 }
101 in2 = node_id(tok);
102 if (UNDEFINED != in2) {
103 *p = Node_List[in2].ID; /* add node ID to dependency list */
104 p++;
105 }
106 }
107 }
108 }
109 *p = -1L; /* to terminate the array */
110 }
111 return;
112}
113
114
115void sort_nodes(void) {
116 long in;
117 long out, out2;
118 long ndel;
119 long nseg;
120 long determined_ptr;
121 long kd;
122 long i, k;
123 char *str = (char*) NULL;
124 long *p = (long*) NULL;
125 int first, flag, err;
126
127 /* ***** First sort the nodes by segment. Qualifier "with" is messing the node list. */
128 determined_ptr = 0L;
129 for (nseg = 0L; nseg < Num_Segments; nseg++) {
130 for (out = 0L; out < Num_Nodes; out++) {
131 if (nseg == Node_List[out].segment) {
132 swap_nodes(out, determined_ptr);
133 out = determined_ptr;
134 determined_ptr++;
135 }
136 }
137 }
138
139 ndel = Num_Delays;
140 determined_ptr = 0L;
141
142 /* ***** Sort now the nodes output of DELAYS, all segments. */
143 for (out = 0L; out < Num_Nodes; out++) {
144
145 kd = Node_List[out].kind;
146 if ((DELAY1_KIND == kd) || (DELAY2_KIND == kd) || (DELAY3_KIND == kd) || (DELAY_KIND == kd)) {
147 in = UNDEFINED;
148 for (i = 0L; i < ndel; i++) { /* check if input to some other delay */
149 if (Node_List[out].ID == Delay_Input[i]) {
150 in = i;
151 break;
152 }
153 }
154 if (UNDEFINED == in) { /* if not, it can be determined */
155 Node_List[out].determined = true;
156 swap_nodes(out, determined_ptr);
157 out = determined_ptr;
158 determined_ptr++;
159 p = Node_List[out].depend;
160 k = *p;
161 for (i = 0L; i < ndel; i++) {
162 if (Delay_Input[i] == k) {
163 ndel--;
164 swap_delay_inputs(i, ndel);
165 break;
166 }
167 }
168 if (0L == ndel) { /* all delays are processed */
169 break;
170 }
171 }
172 }
173 }
174
175 /* ***** Sort now the other nodes, all segments. Starting from previous location. */
176 for (out = determined_ptr; out < Num_Nodes; out++) {
177
178 flag = true;
179 first = true;
180
181 p = Node_List[out].depend;
182
183 for (;;) { /* check if inputs, one by one, are determined */
184 k = *p;
185 if (-1L >= k) { /* reached end of dependency list */
186 break;
187 }
188 flag = false;
189 for (i = 0L; i < determined_ptr; i++) {
190 if (Node_List[i].ID == k) {
191 flag = true;
192 break;
193 }
194 }
195 if (!flag) { /* at least 1 node of dep. list is not determined */
196 if (!first) { /* move determ. node after undeterm. one (speed up) */
197 *p = *(p-1L);
198 *(p-1L) = k;
199 }
200 break;
201 }
202 p++;
203 first = false;
204 }
205 if (flag) {
206 Node_List[out].determined = true;
207 swap_nodes(out, determined_ptr);
208 out = determined_ptr;
209 determined_ptr++;
210 }
211 }
212
213 /* ***** Verify that all nodes are determined. */
214 if ((Num_Nodes - 1L) > determined_ptr) {
215 Error_Flag++;
216 (void) fprintf(STDERR, "\nNAPA Error: (static loop)\n");
217 (void) fprintf(STDERR, "\n These nodes are involved in one or several static loops:\n");
218
219 for (out = determined_ptr; out < Num_Nodes; out++) { /* review each undetermined node */
220 flag = false;
221 for (out2 = determined_ptr; out2 < Num_Nodes; out2++) { /* check dependency */
222 if (out == out2) {
223 continue;
224 }
225 p = Node_List[out2].depend; /* dependencies of out2 */
226 for (;;) { /* check if node out is in the out2 dependency list */
227 k = *p;
228 if (-1L >= k) { /* reached end of dependency list */
229 break;
230 }
231 if (Node_List[out].ID == k) {
232 flag = true; /* node is part of the dependency list */
233 break;
234 }
235 p++;
236 }
237 if (flag) {
238 break;
239 }
240 }
241 if (!flag) { /* this node does not participate to a loop */
242 swap_nodes(out, determined_ptr);
243 determined_ptr++; /* in this search, we mark it as determined */
244 out = determined_ptr; /* restart the search */
245 }
246 }
247 }
248
249 err = false;
250 for (nseg = 0L; nseg < Num_Segments; nseg++) {
251 flag = true;
252 for (out = determined_ptr; out < Num_Nodes; out++) {
253 if (Node_List[out].segment == nseg) {
254 flag = ((Node_List[out].determined) && (flag)) ? true : false;
255 }
256 }
257 if (!flag) { /* there is a problem in this segment */
258 (void) fprintf(STDERR, "\n");
259 if (1L < Num_Segments) {
260 (void) fprintf(STDERR, " In Segment [%ld]\n", nseg);
261 }
262 for (out = determined_ptr; out < Num_Nodes; out++) {
263 if ((!Node_List[out].determined) && (Node_List[out].segment == nseg)) {
264 if ('_' == Node_List[out].name1[0]) {
265 str = Node_List[out].name1 + 1; /* suppress underscore in void name */
266 } else {
267 str = Node_List[out].name1;
268 }
269 (void) fprintf(STDERR, " -> node %s\n", str);
270 }
271 }
272 err = true;
273 }
274 }
275
276 if (err) {
277 (void) fprintf(STDERR, "\n Your description is not correct. NAPA is not able to sort the nodes of your netlist. \n");
278 (void) fprintf(STDERR, " Check for missing or mispelled nodes or loops of nodes containing no delay or only delays\n\n");
279 if (Stuck_Flag) {
280 (void) fprintf(STDERR, " You are using 'stuck' instructions. This is generally safe, except if you stuck a node \n");
281 (void) fprintf(STDERR, " to another node. In this case, the resulting netlist could be impossible to simulate (loop!).\n");
282 (void) fprintf(STDERR, " You could try to remove these particular instructions.\n\n");
283 }
284 }
285 return;
286}
287
288
289/* ****************************************************************************************************************************** */
290/* end of file */
void print_error_location(const char *type, const unsigned long *mlin, const unsigned long *mfil)
Definition fc.c:1476
void swap_nodes(long i, long j)
Definition id.c:590
long node_id(const char *identifier)
Definition id.c:718
long record_id(const char *identifier)
Definition id.c:796
void swap_delay_inputs(long i, long j)
Definition id.c:581
#define DELAY2_KIND
Definition napa.h:255
EXTERN int Error_Flag
Definition napa.h:853
EXTERN RECORD_TYPE Record_List[127L]
Definition napa.h:965
EXTERN int Stuck_Flag
Definition napa.h:878
#define UNDEFINED
Definition napa.h:331
#define STDERR
Definition napa.h:105
EXTERN NODE_TYPE Node_List[4095L]
Definition napa.h:962
#define DELAY3_KIND
Definition napa.h:256
EXTERN long Num_Nodes
Definition napa.h:824
#define DELAY1_KIND
Definition napa.h:254
EXTERN long Num_Delays
Definition napa.h:811
EXTERN long Num_Segments
Definition napa.h:831
EXTERN long Delay_Input[4095L]
Definition napa.h:984
#define STRLENGTH
Definition napa.h:217
#define ISEMPTY(s)
Definition napa.h:394
#define DELAY_KIND
Definition napa.h:253
void print_error_banner_and_exit(void)
Definition pr.c:5482
char * get_sign_and_token(char *str, char *sgn, char *tok)
Definition tk.c:1188
void sort_nodes(void)
Definition sn.c:115
void build_node_dependencies(void)
Definition sn.c:40