├── .gitignore
├── COPYING
├── ISSUES.txt
├── README.md
├── build
├── build.bat
├── cCfgSLICE.cpp
├── cCfgSLICE.h
├── cCollection.cpp
├── cCollection.h
├── cDatum.cpp
├── cDatum.h
├── cDevice.cpp
├── cDevice.h
├── cDyn.cpp
├── cDyn.h
├── cDynXdl.cpp
├── cModule.cpp
├── cModule.h
├── cMultiWire.cpp
├── cMultiWire.h
├── cMultiWireBuilder.cpp
├── cMultiWireBuilder.h
├── cMultiWireWalker.cpp
├── cMultiWireWalker.h
├── cParse.cpp
├── cParse.h
├── cParseStream.cpp
├── cParseStream.h
├── cPrim.cpp
├── cPrim.h
├── cProto.cpp
├── cProto.h
├── cQuark.cpp
├── cQuark.h
├── cSub.cpp
├── cSub.h
├── fpgasm.cpp
├── global.cpp
└── global.h
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 |
6 | # Compiled Dynamic libraries
7 | *.so
8 |
9 | # Compiled Static libraries
10 | *.lai
11 | *.la
12 | *.a
13 |
14 | #backup
15 | *.~
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/ISSUES.txt:
--------------------------------------------------------------------------------
1 | Overall
2 | -------
3 |
4 | -Must verify wiring more. All inputs and outputs should be connected.
5 | -Must verify placement overlaps. Right now, par outputs "error 30", which is pretty confusing.
6 |
7 | Specific
8 | --------
9 |
10 | -cCollection. Check the 'realization' of cfg pairs - data may contain CR's... Also, note:
11 | loc:SLICE_X0Y0 other stuff fails. CR is a menace here.
12 |
13 | Syntax changes
14 | --------------
15 | Quark experiment not worth it. To be deprecated.
16 | DONE Accomodate initalization file for RAMs
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #THIS PROJECT HAS BEEN MOVED!
2 |
3 | https://github.com/FPGAsm/FPGAsm
4 |
5 | See [the wiki](https://github.com/stacksmith/fpgasm/wiki) for more information.
6 |
7 | See other repos for tools and code
8 | * [fpgasm-test](https://github.com/stacksmith/fpgasm-test) test code
9 | * [fpgasm-xcfg](https://github.com/stacksmith/fpgasm-xcfg) visual configuration string tool
10 |
11 | Crap. I wish I'd learned Common Lisp a couple of years ago!
12 |
--------------------------------------------------------------------------------
/build:
--------------------------------------------------------------------------------
1 | #/******************************************************************************
2 | # Copyright 2012 Victor Yurkovsky
3 | #
4 | # This file is part of FPGAsm
5 | #
6 | # FPGAsm 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 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # FPGAsm 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.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with FPGAsm. If not, see .
18 | #******************************************************************************/
19 | g++ fpgasm.cpp cDatum.cpp cCollection.cpp cProto.cpp cPrim.cpp cDevice.cpp \
20 | cModule.cpp cSub.cpp cDyn.cpp cParseStream.cpp cParse.cpp \
21 | cMultiWire.cpp cMultiWireBuilder.cpp cMultiWireWalker.cpp \
22 | cQuark.cpp\
23 | -Wall -fpack-struct -o fpgasm
24 | #CHANGE THIS LINE to your preferred PATH-visible directory
25 | cp fpgasm ~/bin
26 |
--------------------------------------------------------------------------------
/build.bat:
--------------------------------------------------------------------------------
1 | REM ******************************************************************************
2 | REM Copyright 2012 Victor Yurkovsky
3 | REM
4 | REM This file is part of FPGAsm
5 | REM
6 | REM FPGAsm is free software: you can redistribute it and/or modify
7 | REM it under the terms of the GNU General Public License as published by
8 | REM the Free Software Foundation, either version 3 of the License, or
9 | REM (at your option) any later version.
10 | REM
11 | REM FPGAsm is distributed in the hope that it will be useful,
12 | REM but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | REM GNU General Public License for more details.
15 | REM
16 | REM You should have received a copy of the GNU General Public License
17 | REM along with FPGAsm. If not, see .
18 | REM ******************************************************************************/
19 | g++ fpgasm.cpp cDatum.cpp cCollection.cpp cProto.cpp cPrim.cpp cDevice.cpp ^
20 | cModule.cpp cSub.cpp cDyn.cpp cParseStream.cpp cParse.cpp cWires.cpp ^
21 | cWireList.cpp cQuark.cpp ^
22 | -Wall -fpack-struct -o fpgasm
23 | REM CHANGE THIS LINE to your preferred PATH-visible directory
24 | copy fpgasm.exe C:\WINDOWS\fpgasm.exe
25 |
--------------------------------------------------------------------------------
/cCfgSLICE.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #include "global.h"
20 | #include "cCfgSLICE.h"
21 | #include "cDyn.h"
22 | #define CLASS cCfgSLICE
23 | void CLASS::verilogLoc(FILE* fout,cDatum* loc){
24 | fputs("(*LOC=\"",fout);
25 | loc->outputLoc(fout);
26 | fputs("\" *)",fout);
27 | }
28 | void CLASS::verilog(FILE* fout,cDyn* dyn){
29 | // is there a G BEL?
30 | int i = find("G");
31 | if(-1!=i){
32 | verilogLoc(fout,dyn->loc);
33 | fputs("(* BEL=\"G\"*) //",fout);
34 | dyn->hierName(fout);
35 | fputs("\n",fout);
36 | char* gstring=data[i]->valStr;
37 | fputs(gstring,stderr);
38 | if(0==strncmp(gstring,"#LUT:D=0x",9)) {
39 | //processing a lut. 0x????, means use all 4 inputs.
40 | fprintf(fout,"LUT4 #(.INIT(16'h%s)) ",gstring+9);
41 | dyn->hierName(fout);
42 | }
43 | } else {
44 | fprintf(stderr,"not yet finished\n");
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/cCfgSLICE.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #pragma once
20 | /******************************************************************************
21 |
22 | cCfgSLICE is a cCollection, a special one containing cfgs of a SLICEL or
23 | a SLICEM. cDynVerilog uses it to create the verilog BELs. We are not creating
24 | this, just casting an existing collection in cDyn
25 | ******************************************************************************/
26 | //class cDatum; //global.h always includes cDatumc & Collection.h
27 | class cDyn;
28 | class cCfgSLICE:public cCollection{
29 | private:
30 | cCfgSLICE(){};
31 | ~cCfgSLICE(){};
32 | public:
33 | void verilogLoc(FILE*fout,cDatum*loc);
34 | void verilog(FILE*fout,cDyn* dyn);
35 | };
36 |
--------------------------------------------------------------------------------
/cCollection.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 |
20 | #include "global.h"
21 | #include "cSub.h"
22 | #include "cProto.h"
23 | #define CLASS cCollection
24 |
25 | CLASS::CLASS(int max){
26 | // chunk = g_string_chunk_new(32);
27 | name = (char**)malloc(max*sizeof(char*));
28 | data = (cDatum**)malloc(max*sizeof(cDatum*));
29 | size=0;
30 | #ifdef DEBUG
31 | debugmax=max;
32 | #endif
33 | }
34 | CLASS::CLASS(){
35 | name = (char**)malloc(256*sizeof(char*));
36 | data = (cDatum**)malloc(256*sizeof(cDatum*));
37 | size=0;
38 | #ifdef DEBUG
39 | debugmax=256;
40 | #endif
41 | }
42 | CLASS::CLASS(const CLASS& src){
43 | //fprintf(stderr,"COPY CONSTRUCTOR %d\n",src.size);
44 | name=src.name; //reuse name array
45 | //data array will be copied. That way data can be replaced
46 | //without affecting the src.
47 | data=(cDatum**)malloc(src.size*sizeof(cDatum*));
48 | memcpy(data,src.data,src.size*sizeof(cDatum*));
49 | size=src.size;
50 | }
51 | CLASS::~CLASS(){
52 | free(name); //name array
53 | int i;
54 | for(i=0;i=debugmax){
67 | fprintf(stderr,"cCollection:%s add RANGE ERROR - overwriting RAM\n",debugname?debugname:"unnamed");
68 | fprintf(stderr,"max is %d, writing at %d\n",debugmax,size);
69 | fprintf(stderr,"len %d str %s\n",len,str);
70 | this->dump(stderr,"DUMPING");
71 |
72 | throw(1);
73 | }
74 | #endif
75 | //printf("ADDING %s \n",str);
76 | char*p = (char*)malloc(len+1);
77 | memcpy(p,str,len);
78 | p[len]=0;
79 | name[size]=p;
80 | data[size]=dat;
81 | return size++;
82 | }
83 | /******************************************************************************
84 | clone
85 | Occasionally we need an item that is just a reference to an existing
86 | name:value pair. Clone does just that.
87 | ******************************************************************************/
88 | //TODO: rename to addRef
89 | int CLASS::addClone(const char* str,cDatum* dat){
90 | name[size]=(char*)str;
91 | data[size]=dat;
92 | return size++;
93 |
94 | }
95 | void CLASS::solidify(){
96 | //replace builder with properly sized copy of the array
97 | name= (char**)realloc(name,size*sizeof(char*));
98 | data= (cDatum**)realloc(data,size*sizeof(cDatum*));
99 | #ifdef DEBUG
100 | debugmax=size;
101 | //fprintf(stderr,"Solidified %s to %d elements",debugname?debugname:"unknown",size);
102 | #endif
103 | //fprintf(stderr,"PRE-SOLIDIFIED. \n");
104 | //dump(stderr);
105 | //fprintf(stderr,"SOLIDIFIED. \n");
106 | //dump(stderr);
107 | }
108 |
109 | int CLASS::find(const char* str){
110 | return find(str,strlen(str));
111 | }
112 | int CLASS::find(const char* str,int len){
113 | //fprintf(stderr,"cCollection:find(%s,%d)\n",str,len);
114 | int j;
115 | for(j=size-1;j>-1;j--){
116 | if(0==strncmp(str,name[j],len))
117 | if(0==name[j][len])
118 | break;
119 | }
120 | //if(-1==j)
121 | // fprintf(stderr,"find %s %d failed\n",str,len);
122 | //if(-1!=j)fprintf(stderr,"found:%d %s\n",j,name[j]);
123 | return j;
124 | }
125 | char* CLASS::getName(int i){
126 | if(i>=0)
127 | return name[i];
128 | else {
129 | #ifdef DEBUG
130 | fprintf(stderr,"cCollection %s attempted to getName(%d)\n",debugname,i);
131 | #else
132 | fprintf(stderr,"cCollection attempted to getName(%d)\n",i);
133 | #endif
134 | throw(0);
135 | }
136 | }
137 | cDatum* CLASS::getDatum(int i){
138 | if(i>=0)
139 | return data[i];
140 | else {
141 | #ifdef DEBUG
142 | fprintf(stderr,"cCollection %s attempted to getData(%d)\n",debugname,i);
143 | #else
144 | fprintf(stderr,"cCollection attempted to getData(%d)\n",i);
145 | #endif
146 | throw(0);
147 | }
148 | }
149 | int CLASS::indent=0;
150 | void CLASS::dump(FILE*f,const char* title){
151 | if(!size) return;
152 | indent+=2;
153 | if(title)
154 | fprintf(f,"%s",title);
155 | else
156 | fprintf(f,"collection with %d items:\n",size);
157 | int i;
158 | for(i=0;idump(f);
164 | else {
165 | fprintf(f,"DATA IS NULL!!!\n");
166 | }
167 | fprintf(f,"\n");
168 | }
169 | indent-=2;
170 | }
171 | #ifdef DEBUG
172 | void CLASS::setdebugname(char*name,int len){
173 | debugname = (char*)malloc(len+1);
174 | memcpy(debugname,name,len);
175 | debugname[len]=0;
176 | }
177 | #endif
178 | /******************************************************************************
179 | vlogWireDefs
180 | create wire defintions from pins.
181 | ******************************************************************************/
182 | void CLASS::vlogWireDefs(FILE*f,const char*prefix){
183 | int i; for(i=0;ipinBusWidth;
186 | if(buswidth>1)
187 | fprintf(f,"[%d:0] ",buswidth-1);
188 | fprintf(f,"%s_%s;\n",prefix,name[i]);
189 | }
190 | }
191 | /******************************************************************************
192 | vlogPinDefs
193 | create wire defintions from pins.
194 | input a,
195 | output b
196 | ******************************************************************************/
197 | void CLASS::vlogPinDefs(FILE*f){
198 | int i; for(i=0;ipinDir)
201 | fputs(" output ",f);
202 | else
203 | fputs(" input ",f);
204 | if(pin->pinBusWidth>1)
205 | fprintf(f,"[%d:0] ",pin->pinBusWidth-1);
206 | fputs(name[i],f);
207 | if(i!=size-1)
208 | fputs(",\n",f);
209 | else
210 | fputs("\n",f);
211 | }
212 |
213 | }
214 | /******************************************************************************
215 | vlogPins
216 | just list the pins for an inst,comma-sep
217 | a,b,c
218 | ******************************************************************************/
219 | void CLASS::vlogPins(FILE*f,const char*prefix){
220 | int i; for(i=0;ipinBusWidth;
222 | fprintf(f,"%s_%s",prefix,name[i]);
223 | if(buswidth>1)
224 | fprintf(f,"[%d:0]",buswidth-1);
225 | if(i!=size-1)
226 | fputs(",",f);
227 | }
228 | }
229 |
--------------------------------------------------------------------------------
/cCollection.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #pragma once
20 | /******************************************************************************
21 |
22 | cCollection
23 |
24 | This class is roughly an array of named objects.
25 | -The array starts in 'builder' mode. When the count of objects
26 | is nailed down, the array compacts itself.
27 |
28 | Index access is used to traverse wiring, so we have to use a
29 | fixed array. If searching becomes too slow we could hashtable
30 | in addition instead of a stringchunk.
31 | ******************************************************************************/
32 | //class cDatum; //global.h always includes cDatumc & Collection.h
33 | class cCollection{
34 | public:
35 | cCollection(); //for debugging only
36 | cCollection(int max);
37 | cCollection(const cCollection&src); //reuse names, point at same data
38 | ~cCollection();
39 | void resize(int max);
40 | int add(const char*str,int len,cDatum* dat);
41 | int addClone(const char*str,cDatum*dat);
42 | void solidify();
43 | int find(const char*str); //Neg means not found
44 | int find(const char*str,int len);
45 | char* getName(int i);
46 | cDatum* getDatum(int i);
47 | void dump(FILE*f,const char*name);
48 | void vlogWireDefs(FILE*f,const char*prefix);
49 | void vlogPinDefs(FILE*f);
50 | void vlogPins(FILE*f,const char*prefix);
51 |
52 | //DATA:
53 | char** name;
54 | cDatum** data;
55 | int size;
56 | #ifdef DEBUG
57 | int debugmax;
58 | char* debugname;
59 | void setdebugname(char*name,int len);
60 | #endif
61 | private:
62 | static int indent;
63 | };
64 |
--------------------------------------------------------------------------------
/cDatum.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #include "global.h"
20 | #include "cSub.h"
21 | #include "cProto.h"
22 | #include "cDatum.h"
23 |
24 | #define CLASS cDatum
25 |
26 | char *CLASS::buf=(char*)malloc(32); //- SLICE_X...Y...\0
27 |
28 | CLASS::CLASS(eDatumType typ){
29 | type=typ;
30 | }
31 | CLASS::~CLASS(){
32 | switch(type){
33 | case TYPE_UNREALIZED:
34 | case TYPE_STR:
35 | free(valStr); break;
36 | default:
37 | //TODO: comprehensive destructor
38 | break;
39 | }
40 | }
41 | cDatum* CLASS::newStr(const char* str,int len){
42 | cDatum* ret = new cDatum(TYPE_STR);
43 |
44 | ret->valStr = (char*)malloc(len+1);
45 | strncpy(ret->valStr,str,len);
46 | ret->valStr[len]=0;
47 | return ret;
48 | }
49 | cDatum* CLASS::newInt(int val){
50 | cDatum* ret = new cDatum(TYPE_INT);
51 |
52 | ret->valInt=val;
53 | return ret;
54 | }
55 | cDatum* CLASS::newPin(int dir,int bwidth){
56 | cDatum* ret = new cDatum(TYPE_PIN);
57 | ret->pinDir=dir&1;
58 | ret->pinBusWidth=bwidth&0xFF;
59 | return ret;
60 | }
61 | cDatum* CLASS::newSub(cSub* val){
62 | cDatum* ret = new cDatum(TYPE_SUB);
63 |
64 | ret->valSub=val;
65 | return ret;
66 | }
67 | cDatum* CLASS::newLocXY(int x,int y){
68 | cDatum* ret = new cDatum(TYPE_LOCXY);
69 |
70 | ret->valX=x;
71 | ret->valY=y;
72 | return ret;
73 | }
74 | cDatum* CLASS::newLocAbs(const char* str,int len){
75 | cDatum* ret = new cDatum(TYPE_LOCABS);
76 |
77 | ret->valStr = (char*)malloc(len+1);
78 | strncpy(ret->valStr,str,len);
79 | ret->valStr[len]=0;
80 | return ret;
81 | }
82 | cDatum* CLASS::newGoodCfgs(const char* str,int len){
83 | cDatum* ret = new cDatum(TYPE_GOODCFGS);
84 |
85 | ret->valStr = (char*)malloc(len+1);
86 | strncpy(ret->valStr,str,len);
87 | ret->valStr[len]=0;
88 | return ret;
89 | }
90 | cDatum* CLASS::newProto(cProto* val){
91 | //proto reference
92 | cDatum* ret = new cDatum(TYPE_PROTO);
93 |
94 | ret->valProto=val;
95 | return ret;
96 | }
97 |
98 | cDatum* CLASS::newTile(const char*str,int len){
99 | cDatum* ret = new cDatum(TYPE_TILE);
100 |
101 | ret->valStr = (char*)malloc(len+1);
102 | strncpy(ret->valStr,str,len);
103 | ret->valStr[len]=0;
104 | return ret;
105 | }
106 | cDatum* CLASS::newParSub(const char*str,int len){
107 | cDatum* ret = new cDatum(TYPE_PARSUB);
108 |
109 | ret->valStr = (char*)malloc(len+1);
110 | strncpy(ret->valStr,str,len);
111 | ret->valStr[len]=0;
112 | return ret;
113 | }
114 | cDatum* CLASS::newUnrealized(const char* str,int len){
115 | cDatum* ret=CLASS::newStr(str,len);
116 | ret->type=TYPE_UNREALIZED;
117 | return ret;
118 |
119 | }
120 | /******************************************************************************
121 | parseLiteral
122 |
123 | ******************************************************************************/
124 | char* CLASS::parseLiteral(char*start,S32*presult){
125 | char*ptr=start;
126 | int radix=10;
127 | long accum=0;
128 | bool neg=false;
129 | char c=*ptr; //check the initial character...
130 | switch(c){
131 | case '$':
132 | radix=16;
133 | ptr++;
134 | break;
135 | case '%':
136 | radix=2;
137 | ptr++;
138 | break;
139 | case '-':
140 | neg=true;
141 | ptr++;
142 | break;
143 | default:
144 | radix=10;
145 | break;
146 | }
147 | while(true){
148 | c=*ptr++;
149 | if('_'==c) continue;
150 | c-='0';
151 | if(c<0) break;
152 | if(c>9) {
153 | c-=7;
154 | if(c<0) break;
155 | }
156 | if(c>radix) {
157 | fprintf(stderr,"invalid digit in '%s'",start);
158 | throw(1);
159 | }
160 | accum = (accum*radix)+c;
161 | }
162 | ptr--;
163 | if(neg) accum = 0-accum;
164 | *presult=accum;
165 | return ptr;
166 | }
167 |
168 |
169 | /*=====================================================================
170 | Convert an unrealized datum to a realized type
171 | ======================================================================*/
172 | void CLASS::realize(){
173 | if(type==TYPE_UNREALIZED){
174 | //let's check for xy()
175 | if(0==strncmp("xy(",valStr,3)){
176 | int x,y;
177 | char*p=parseLiteral(valStr+3,&x);
178 | //TODO: check for , and ) properly.
179 | //fprintf(stderr,"cDatum::realize() after x,'%s'\n",p);
180 | p=parseLiteral(p+1,&y);
181 | //fprintf(stderr,"cDatum::realize() after y,'%s'\n",p);
182 | free(valStr);
183 | type=TYPE_LOCXY;
184 | valX=x;
185 | valY=y;
186 | return;
187 | }
188 | if(0==strncmp("cfg:",valStr,4)){
189 | //cfg contains many name:val pairs...
190 | char* p = strtok(valStr," \n");
191 | int maxcfgs=256;
192 | cCollection* cfgs = new cCollection(maxcfgs);
193 | int counter=0;
194 | while(true){
195 | p=strtok(NULL," :\n");
196 | if(!p) break;
197 | counter++;
198 | if(counter>=maxcfgs){
199 | fprintf(stderr,"Error: Maximum of %d cfgs allowed; exceeded\n",maxcfgs);
200 | throw(-1);
201 | }
202 | char* name=p;
203 | //An empty cfg has a " " here... strtok(NULL," " will just eat the
204 | //next name, so check explicitly. TODO: this sucks, and should
205 | //be replaced by a stream parsing class...
206 | char* val=(char*)""; //for empty cfg
207 | if(' '!=*(name+strlen(name)+1)) {
208 | //fprintf(stderr,"xxx[%s]\n",name+strlen(name)+1);
209 | p=strtok(NULL," \n");
210 | if(!p) {
211 | fprintf(stderr,"Error realizing %d-long cfg string [%s] %d\n",(int)strlen(name),name,*name);
212 | throw(1);
213 | }
214 | val=p;
215 | }
216 | //fprintf(stderr,"REALIZED #%d [%s:%s]\n",counter,name,val);
217 | cfgs->add(name,strlen(name),cDatum::newStr(val,strlen(val)));
218 | //fprintf(stderr,"[[%s:%s]]\n",name,val);
219 | }
220 | cfgs->solidify();
221 | delete valStr;
222 | valCfgs=cfgs;
223 | type=TYPE_CFGS;
224 | }
225 | else
226 | type=TYPE_STR;
227 | }
228 | }
229 |
230 |
231 | void CLASS::realize1(){
232 | if(type==TYPE_UNREALIZED){
233 | //let's check for xy()
234 | if(0==strncmp("xy(",valStr,3)){
235 | int x,y;
236 | char*p=parseLiteral(valStr+3,&x);
237 | //TODO: check for , and ) properly.
238 | //fprintf(stderr,"cDatum::realize() after x,'%s'\n",p);
239 | p=parseLiteral(p+1,&y);
240 | //fprintf(stderr,"cDatum::realize() after y,'%s'\n",p);
241 | free(valStr);
242 | type=TYPE_LOCXY;
243 | valX=x;
244 | valY=y;
245 | return;
246 | }
247 | if(0==strncmp("cfg:",valStr,4)){
248 | //cfg contains many name:val pairs...
249 | char* p = strtok(valStr," ");
250 | int maxcfgs=256;
251 | cCollection* cfgs = new cCollection(maxcfgs);
252 | int counter=0;
253 | while(true){
254 | p=strtok(NULL," :");
255 | if(!p) break;
256 | counter++;
257 | if(counter>=maxcfgs){
258 | fprintf(stderr,"Error: Maximum of %d cfgs allowed; exceeded\n",maxcfgs);
259 | throw(-1);
260 | }
261 | char* name=p;
262 | //An empty cfg has a " " here... strtok(NULL," " will just eat the
263 | //next name, so check explicitly. TODO: this sucks, and should
264 | //be replaced by a stream parsing class...
265 | char* val=(char*)""; //for empty cfg
266 | if(' '!=*(name+strlen(name)+1)) {
267 | //fprintf(stderr,"xxx[%s]\n",name+strlen(name)+1);
268 | p=strtok(NULL," ");
269 | if(!p) {
270 | fprintf(stderr,"Error realizing cfg string\n");
271 | throw(1);
272 | }
273 | val=p;
274 | }
275 | //fprintf(stderr,"REALIZED #%d [%s:%s]\n",counter,name,val);
276 | cfgs->add(name,strlen(name),cDatum::newStr(val,strlen(val)));
277 | //fprintf(stderr,"[[%s:%s]]\n",name,val);
278 | }
279 | cfgs->solidify();
280 | delete valStr;
281 | valCfgs=cfgs;
282 | type=TYPE_CFGS;
283 | }
284 | else
285 | type=TYPE_STR;
286 | }
287 | }
288 | /*=====================================================================
289 | outputLoc - used by xdl output
290 | ======================================================================*/
291 | char* CLASS::outputLoc(){
292 | switch(type){
293 | case TYPE_STR:
294 | strcpy(buf,valStr);
295 | break;
296 | case TYPE_LOCXY:
297 | sprintf(buf,"SLICE_X%dY%d",valX,valY);
298 | break;
299 | default:
300 | fprintf(stderr,"cCollection:outputLoc - Not a location!\n");
301 | throw(1);
302 | }
303 | return buf;
304 | }
305 | char* CLASS::outputLoc(FILE*f){
306 | switch(type){
307 | case TYPE_STR:
308 | fputs(valStr,f);
309 | break;
310 | case TYPE_LOCXY:
311 | fprintf(f,"SLICE_X%dY%d",valX,valY);
312 | break;
313 | default:
314 | fprintf(stderr,"cCollection:outputLoc - Not a location!\n");
315 | throw(1);
316 | }
317 | return buf;
318 | }
319 | void CLASS::dump(FILE*f){
320 | switch(type){
321 | case TYPE_INT: fprintf(f,"int:%d ",valInt);break;
322 | case TYPE_STR: fprintf(f,"str:\"%s\" ",valStr);break;
323 | case TYPE_PIN: fprintf(f,"pin: ");break;
324 | case TYPE_SUB: valSub->dump(f); break;
325 | case TYPE_LOCXY:
326 | fprintf(f,"(%d,%d) ",valX,valY); break;
327 | case TYPE_LOCABS:
328 | fprintf(f,"abs:%s ",valStr); break;
329 | case TYPE_GOODCFGS:
330 | fprintf(f,"good cfgs:%s ",valStr); break;
331 | case TYPE_PROTO: valProto->dump(f); break;
332 | case TYPE_TILE: fprintf(f,"tile:\"%s\" ",valStr);break;
333 | case TYPE_PARSUB: fprintf(f,"parsub:<%s> ",valStr);break;
334 | case TYPE_UNREALIZED: fprintf(f,"unr:\"%s\" ",valStr);break;
335 | case TYPE_CFGS:
336 | valCfgs->dump(f,"cfgs:"); break;
337 |
338 | default: fprintf(f,"cCollection::dump - unknown type %d\n",type);
339 | }
340 | }
341 |
342 |
343 |
344 |
345 |
--------------------------------------------------------------------------------
/cDatum.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANonTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #pragma once
20 | /******************************************************************************
21 |
22 | cDatum
23 |
24 | This class is represents a data item stored in a cCollection.
25 | ******************************************************************************/
26 | enum eDatumType {
27 | TYPE_INT=0,
28 | TYPE_STR, //1
29 | TYPE_PIN, //2 direction,buswidth
30 | TYPE_SUB, //3 instances declared in a module
31 | TYPE_LOCXY, //4
32 | TYPE_LOCABS, //5
33 | TYPE_GOODCFGS,//6
34 | TYPE_PROTO, //7
35 | TYPE_TILE, //8 used by device to track tiles
36 | TYPE_PARSUB, //9 parameter substitution TODO:deprecated??
37 | TYPE_CFGS, //10 ???
38 | TYPE_UNREALIZED=255
39 | };
40 | class cSub;
41 | class cProto;
42 | class cCollection;
43 |
44 | class cDatum{
45 | public:
46 | eDatumType type:8;
47 | union {
48 | unsigned int valInt;
49 | char* valStr;
50 | cSub* valSub;
51 | cProto* valProto;
52 | cCollection* valCfgs;
53 | struct {
54 | U16 valX;
55 | U16 valY;
56 | };
57 | struct {
58 | U8 pinDir;
59 | U8 pinBusWidth;
60 | } ;
61 | };
62 | // give factories access to data
63 | //friend cDatum* newStr(const char* str,int len);
64 | //friend cDatum* newInt(const char* str,int len);
65 | public:
66 | cDatum(eDatumType type);
67 | ~cDatum();
68 | void dump(FILE*f);
69 | static cDatum* newStr(const char* str,int len);
70 | static cDatum* newInt(int val);
71 | static cDatum* newPin(int dir,int bwidth);
72 | static cDatum* newSub(cSub* val);
73 | static cDatum* newLocXY(int x,int y);
74 | static cDatum* newLocAbs(const char* str,int len);
75 | static cDatum* newGoodCfgs(const char* str,int len);
76 | static cDatum* newProto(cProto* val);
77 | static cDatum* newTile(const char* val,int len);
78 | static cDatum* newParSub(const char* val,int len);
79 | static cDatum* newUnrealized(const char* str,int len);
80 |
81 | char* outputLoc(); //TODO: get rid of this
82 | char* outputLoc(FILE*f); //proper SLICE_X..Y.. or abs
83 | void realize();
84 | void realize1();
85 |
86 | private:
87 | static char*buf; //a buffer for outputting location strings
88 | char* parseLiteral(char*start,S32*presult);
89 |
90 | };
91 |
--------------------------------------------------------------------------------
/cDevice.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #include "global.h"
20 | #include "cDevice.h"
21 | #include "cPrim.h"
22 | #define CLASS cDevice
23 |
24 | CLASS::CLASS()
25 | :sites(1000000) //TODO: should dynamically resize maybe?
26 | {
27 | #ifdef DEBUG
28 | sites.setdebugname((char*)"sites",5);
29 | #endif
30 |
31 | //htPlace=g_hash_table_new(g_str_hash,g_str_equal);
32 | //htPrims =g_hash_table_new(g_str_hash,g_str_equal);
33 | }
34 | CLASS::~CLASS(){
35 | //g_hash_table_destroy(htPlace);
36 | //g_hash_table_destroy(htPrims);
37 |
38 | }
39 |
40 | void CLASS::initialize(){
41 | // initialize device stuff
42 | }
43 | #include
44 |
45 | /******************************************************************************/
46 | void CLASS::parse_defs( char*buf){
47 | //printf("-- %s\n",buf);
48 | if(0==strncmp(buf,"(primitive_defs ",16)){
49 | // primitive_defs COUNT
50 | int pdcount;
51 | sscanf(buf,"(primitive_defs %d",&pdcount);
52 | //fprintf(stderr,"Will parse %d primitive_defs\n",pdcount);
53 |
54 | int i;
55 | for(i=0;iparamnames->add("loc",3,cDatum::newInt(0));
67 | prim->paramnames->add("cfg",3,cDatum::newInt(0)); //TODO: null is OK now
68 | prim->paramnames->add("cfgfile",7,NULL); //TODO: awkward
69 | //------------------------------------------------------------------
70 | // Primitive's pins are parsed.
71 | //\t\t(pin RESET RESET output)
72 | int i;
73 | for(i=0;ipins->add(name,strlen(name),cDatum::newPin(0,0));
81 | else if(0==strncmp(dir,"output",6))
82 | prim->pins->add(name,strlen(name),cDatum::newPin(1,0) );
83 | else {
84 | printf("ERROR: pin direction\n");
85 | }
86 | }
87 | // Now commit the pins
88 | prim->pins->solidify();
89 | //------------------------------------------------------------------
90 | // Element name pins
91 | // Elements are interesting only if there is a 'cfg' line...
92 | for(i=0;icfgval->add(elname,strlen(elname),
109 | cDatum::newGoodCfgs(p,strlen(p))
110 | );
111 | //add to paramname so we can verify name:val pairs
112 | //prim->paramnames->add(elname,strlen(elname),cDatum::newInt(0));
113 |
114 | //fprintf(stderr,"added element %s goodcfgs %s\n",elname,p);
115 | }
116 | // now skip the conn lines...
117 | while(true){
118 | if(0==strncmp(buf,"\t\t)\n",4))
119 | break;
120 | fgets(buf,1024,f);
121 | }
122 | } else {
123 | printf("ERROR: expected (element, got [%s]. index %d out of %d\n",buf,i,elements);
124 | }
125 | }
126 | prim->paramnames->solidify();
127 | prim->cfgval->solidify();
128 | fgets(buf,1024,f); //eat the \t\t(
129 | }
130 | //THIS KILL RAM! should resize somehow...TODO:protos.solidify();
131 | }
132 | }
133 |
134 | /******************************************************************************/
135 | void CLASS::addProto(char*name,int len,cProto* proto) {
136 | //fprintf(stderr,"addProto %d %s\n",len,name);
137 | //make sure there are no duplicates
138 | if(-1==protos.find(name,len)){
139 | protos.add(name,len,cDatum::newProto(proto));
140 | } else {
141 | fprintf(stderr,"cDevice::addProto Module %s already exists\n",name);
142 | throw(1);
143 | }
144 | }
145 | /******************************************************************************/
146 |
147 | int CLASS::idxFindProto(char*name,int len){
148 | return protos.find(name,len);
149 | }
150 | cProto* CLASS::findProto(char*name,int len) {
151 | //protos.dump(stderr);
152 | int i=protos.find(name,len);
153 | if(-1==i) return 0;
154 | cDatum*p = protos.getDatum(i);
155 | if(p->type!=TYPE_PROTO){
156 | fprintf(stderr,"findProto: type mismatch\n");
157 | throw(1);
158 | }
159 | return p->valProto;
160 | }
161 | /******************************************************************************/
162 | //used by hash table iterator...
163 | void CLASS::listProtos() {
164 | protos.dump(stderr,"protos:\n");
165 | }
166 |
167 | const char* CLASS::tileFor( char* primsite){
168 | int i;
169 | i=sites.find(primsite);
170 | if(-1==i){
171 | fprintf(stderr,"cDevice::tileFor(\"%s\") is impossible\n",primsite);
172 | throw(1);
173 |
174 | }
175 | cDatum* dat = sites.getDatum(i);
176 | if(TYPE_TILE != dat->type){
177 | fprintf(stderr,"cDevice::tileFor %s NOT A TILE\n",primsite);
178 | throw(1);
179 | }
180 | return dat->valStr;
181 |
182 | }
183 |
184 | /******************************************************************************/
185 | void CLASS::parse_tile( char*buf){
186 | if(0==strncmp(buf,"\t(tile ",7)){
187 | // Appears to be a valid tile description...
188 | int x;
189 | int y;
190 | char tilename[32]; //placed tilename sitename
191 | char whatever[32];
192 | int count;
193 | sscanf(buf," (tile %d %d %s %s %d ",&x,&y,(char*)&tilename,(char*)&whatever,&count);
194 | //printf("read: %d %d %s %d\n",x,y,whatever,count);
195 | int i;
196 | for(i=0;i.
18 | ******************************************************************************/
19 | /******************************************************************************
20 | A device contains
21 | - a database of named cPrimDefs
22 | ******************************************************************************/
23 | class cProto;
24 | class cDevice{
25 | //DATA
26 | private:
27 | cCollection protos;
28 | int lineno;
29 | char* buf;
30 | FILE* f;
31 | char* designator; //device name and speed
32 | //CODE
33 | public:
34 | cDevice();
35 | ~cDevice();
36 | void initialize();
37 | void parse_xdlrc(const char* fname);
38 |
39 | char* place(const char* key);
40 |
41 | void addProto(char* key,int len,cProto* proto); //add a prim or module
42 | cProto* findProto(char*str,int len); //find a prim or module
43 | int idxFindProto(char*str,int len); //find index or -1
44 |
45 | void listProtos();
46 | const char* tileFor( char* primsite); //like SLICE_XY or IOB
47 | const char* getDesignator(); //device name and speed grade for output
48 | private:
49 | bool readline();
50 | void parse_tile(char* buf);
51 | void parse_defs(char* buf);
52 | cCollection sites; //map sitename like SLICE_X?Y? to tilename R?C?
53 | //GHashTable *htPrims; // map primnames like IOB to cPrim objects
54 | void errorIn(const char* function);
55 | void error(U32 xerrno);
56 |
57 | };
58 |
--------------------------------------------------------------------------------
/cDyn.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #include "global.h"
20 | #include "cDyn.h"
21 | #include "cModule.h"
22 | #include "cSub.h"
23 | #include "cPrim.h"
24 | #include "cDevice.h"
25 | extern cDevice* pDevice;
26 | #define CLASS cDyn
27 | //char* CLASS::namebuf=(char*)malloc(256);
28 | FILE* CLASS::fout; //static
29 | /*
30 | Note: net names are hier followed by seq number. This allows duplication
31 | in net sources. Otherwise, we would need to build a wire sorter.
32 | =====================================================================
33 | ======================================================================*/
34 | CLASS::CLASS(cSub* ero, cDyn* const pop){
35 | hero=ero;
36 | dad=pop;
37 | }
38 | CLASS::~CLASS(){};
39 |
40 |
41 | /*=====================================================================
42 | ======================================================================*/
43 | int CLASS::banglen(char* str,char*fullstr){ //just past the bang
44 | char* nextbang=strchr(str,'!');
45 | if(!nextbang) {
46 | errorIn("banglen()");
47 | fprintf(stderr,"Argument value '%s' is missing the closing !",
48 | fullstr);
49 | error(1);
50 | }
51 | return nextbang-str;
52 | }
53 | /*=====================================================================
54 | expandFile
55 | called by expand for cfgfile parameters
56 | ======================================================================*/
57 | #include
58 | #include
59 | #include
60 | #include
61 | char* CLASS::expandFile(const char* filename){
62 | int f = open(filename,O_RDONLY);
63 | if(-1==f){
64 | errorIn("expandFile");
65 | fprintf(stderr,"Trying to open cfgfile \"%s\"\n",filename);
66 | error(-1);
67 | }
68 | char* data = (char*)malloc(0x10000);
69 | strcpy(data,"cfg: ");
70 | read(f,data+5,0x10000-5);
71 | //TODO: clean up
72 | //fprintf(stderr,"EXPANDED\n----------------\n%s\n-------------------\n",data);
73 | //fprintf(stderr,"EXPANDED length %d\n",strlen(data));
74 | return data;
75 |
76 | }
77 | /*------------------------------------------------------------------
78 | expand
79 | All data is in unrealized form; now is the time to realize it.
80 | !..! substitution takes place here.
81 | *-----------------------------------------------------------------*/
82 | /*=====================================================================
83 | ======================================================================*/
84 | void CLASS::expand(){
85 | char expandbuf[8192]; //TODO: BUFSIZEwill be expanding to here
86 | char* dest;
87 | char* src;
88 | char c;
89 | //hierName(stderr);fprintf(stderr,"\n");
90 | //fprintf(stderr," being expanded %p\n",this);
91 | //--------------------------
92 | // expand parameters. Start by copying hero's
93 | if(hero->pparams){
94 | pparams = new cCollection(*hero->pparams);
95 | //pparams->dump(stderr,"expanding");
96 | // hero->pparams->dump(stderr,"expanding");
97 | // now step through and fix the parsub values
98 | int i;
99 | for(i=0;isize;i++){
100 | // If cfgfile parameter is encountered, substitute
101 | // the value of the file for val.
102 | // if(0==strcmp("cfgfile",pparams->name[i])){
103 | // //(pparams->name[i])=(char*)"cfg"; //convert cfgfile into cfg
104 | // char*filedata=expandFile(pparams->data[i]->valStr);
105 | // //now replace the cDatum's string with expanded
106 | // free(pparams->data[i]->valStr); //don't need the filename
107 | // pparams->data[i]->valStr=filedata; //replace with data
108 | // }
109 | cDatum* val=pparams->data[i];
110 | src=val->valStr;
111 | dest=expandbuf; *dest=0;
112 | //copy characters unless a special one is encountered...
113 | bool done=false;
114 | while(!done){
115 | c=*src++;
116 | switch(c){
117 | case '!':
118 | // Substitution!
119 | {
120 | int blen = banglen(src,val->valStr);
121 | //fprintf(stderr,"substitution of %.*s\n",blen,src);
122 | //Dad should have a named parameter like this
123 | int idx=dad->pparams->find(src,blen);
124 | if(-1==idx) {
125 | // char pname[64];
126 | // strncpy(pname,src,blen);
127 | errorIn("expand()");
128 | fprintf(stderr,"While expanding argument '%s',",val->valStr);
129 | fprintf(stderr,"noticed that:\n containing module %s has no parameter ",dad->hero->type->name);
130 | fprintf(stderr,"named '%.*s'",blen,src);
131 | //Argument value !%.*s! requires module %s to have such a parameter named %s"
132 | // ,blen,val->valStr,hero->type->name,pname);
133 | error(1);
134 | }
135 | src+=blen; //In source string !xxx!, skip it
136 | src++; //skip the ! too
137 | //now copy dad's value
138 | //fprintf(stderr,"will copy %s\n",dad->pparams->data[idx]->valStr);
139 | //fprintf(stderr,"dest %s\n",dest);
140 | strcpy(dest,dad->pparams->data[idx]->valStr);
141 | dest+=strlen(dad->pparams->data[idx]->valStr);
142 | //fprintf(stderr,"final answer: %s\n",expandbuf);
143 | }
144 | break;
145 | // case ' ':
146 | case 0:
147 | done=true;
148 | default:
149 | *dest++=c;
150 | break;
151 | }
152 | }
153 | // Now replace parameter data with our string.
154 | // fprintf(stderr,"REPLACING %s's parameter '%s' was {%s} now {%s}\n",//
155 | // hero->name,pparams->name[i],pparams->data[i]->valStr,expandbuf);
156 | //Do not delete - it is a shallow copy...
157 | pparams->data[i]=cDatum::newUnrealized(expandbuf,strlen(expandbuf));
158 | //Now realize...
159 | //fprintf(stderr,"Realizing parameter %d [%s]\n",(int)strlen(pparams->data[i]->valStr),pparams->data[i]->valStr);
160 | pparams->data[i]->realize();
161 | //fprintf(stderr,"Done realizing \n");
162 | }
163 | } else {
164 | pparams = new cCollection();
165 | pparams->solidify();
166 | }
167 | //pparams->dump(stderr,"params");
168 | //if(hero->pparams)
169 | // hero->pparams->dump(stderr,"hero");
170 |
171 | //--------------------------
172 | // children.
173 | psubs=0;
174 | psubcnt=0;
175 | if(hero->type->psubs){
176 | psubcnt=hero->type->psubs->size;
177 | //fprintf(stderr,"SUB COUNT at %p %d\n",&psubcnt,psubcnt);
178 | if(psubcnt){
179 | // Now go through the children. Inside dyn, create an array
180 | //pointing to each of the children, as we create them.
181 | psubs = (cDyn**)malloc(psubcnt*sizeof(cDyn*));
182 | int i;
183 | for(i=0;itype->psubs->data[i];
185 | if(TYPE_SUB != dat->type) {
186 | errorIn("expand()");
187 | fprintf(stderr,"Module '%s' stores an invalid inst (seq %d)\n",
188 | hero->type->name,i);
189 | error(1);
190 | }
191 | cSub* sub = dat->valSub;
192 | //do whatever expansion here
193 | psubs[i]=new cDyn(sub,this);
194 | psubs[i]->expand();
195 | }
196 | }
197 | }
198 |
199 | }
200 | /*=====================================================================
201 | ======================================================================*/
202 | void CLASS::place(){
203 | //fprintf(stderr,"1. Start placing %s %p\n",hero->name,this);
204 | //hierName(stderr);
205 | //fprintf(stderr,"\n");
206 | //fprintf(stderr," subcnt at %p %d \n",&psubcnt,psubcnt);
207 | //first place ourselves...Simple if we are absolut
208 | cDatum* hloc = getLocation();
209 | //fprintf(stderr,"2. Got location %p\n",hloc);
210 | if(!hloc) {
211 | /* No location specified in the hero. This means use dad's loc,
212 | unless we are top. In this case, just set 0,0. */
213 | //fprintf(stderr,"No loc specified\n");
214 | if(dad)
215 | loc = dad->loc;
216 | else
217 | loc=cDatum::newLocXY(0,0);
218 | } else {
219 | //fprintf(stderr," loc:%p \n",hloc);
220 | //fprintf(stderr," loc:%s \n",hloc->valStr);
221 |
222 | //fprintf(stderr,"2.location found: %d\n",hloc->type);
223 | switch (hloc->type){
224 | case TYPE_STR:
225 | //fprintf(stderr,"5. hloc->type is STR %s\n",hloc->valStr);
226 | loc = hloc; //just use our hero's location!
227 | break;
228 | case TYPE_LOCXY: //our hero is xy..
229 | //fprintf(stderr,"6. hloc->type is XY (%d,%d)\n",hloc->valX,hloc->valY);
230 | loc = cDatum::newLocXY(hloc->valX,hloc->valY);//copy constructor...
231 | if(dad){ //TODO: what if no dad
232 | switch(dad->loc->type){
233 | case TYPE_LOCABS:
234 | errorIn("place()");
235 | fprintf(stderr,"cDyn::place(): %s has an absolute location; %s cannot be relative\n",dad->hero->name,hero->name);
236 | error(1);
237 | break;
238 | case TYPE_LOCXY: //dad is xy, so adjust...
239 | loc->valX += dad->loc->valX;
240 | loc->valY += dad->loc->valY;
241 | //fprintf(stderr,"61. dad's location is xy(%d,%d). offsetting to (%d,%d)\n",
242 | // dad->loc->valX,dad->loc->valY,
243 | // loc->valX,loc->valY);
244 | break;
245 | default:
246 | errorIn("place()");
247 | fprintf(stderr,"cDyn:place %s invalid loc type %d\n",hero->name,dad->loc->type);
248 | error(1);
249 | }
250 | } else {
251 | errorIn("place()");
252 | fprintf(stderr,"cDyn:place %s has no parent and cannot be placed\n",hero->name);
253 | error(1);
254 | }
255 | break;
256 | default:
257 | errorIn("place()");
258 | fprintf(stderr,"loc type of %s not ABS or XY, it is %d\n",hero->name,hloc->type);
259 | error(1);
260 | break;
261 | }
262 | }
263 | // now place children
264 | int i;
265 | for(i=0;iplace();
267 | }
268 | //fprintf(stderr,"99.done placing %s\n",hero->name);
269 | //fprintf(stderr,"loc is %p\n",loc);
270 | }
271 |
272 | U32 CLASS::seq=0;
273 |
274 | /*=====================================================================
275 | ======================================================================*/
276 | int CLASS::childIndex(cDyn*p){
277 | int i;
278 | for(i=0;ihierName();
286 | strcat(namebuf,"/");
287 | strcat(namebuf,hero->name);
288 | } else {
289 | strcpy(namebuf,hero->name);
290 | }
291 | }*/
292 | /*=====================================================================
293 | ======================================================================*/
294 | void CLASS::hierName(FILE*f){
295 | if(dad){
296 | dad->hierName(f);
297 | fprintf(f,"/%s",hero->name);
298 | }
299 | else
300 | fprintf(f,"%s",hero->name);
301 | }
302 |
303 | /*=====================================================================
304 | ======================================================================*/
305 | cDatum* CLASS::getLocation(){
306 | if(pparams){
307 | int iloc = pparams->find("loc",3);
308 | if(-1==iloc) return 0; //0 means no set location
309 | return pparams->data[iloc];
310 | } else {
311 | return 0; //no parameters at all
312 | }
313 | }
314 |
315 | /*=====================================================================
316 | error
317 | First, fprintf an error message to stderr.
318 | Then, call error - it outputs the position.
319 | ======================================================================*/
320 | void CLASS::errorIn(const char* from){
321 | fprintf(stderr,"----------------------------------------------------------------------\n");
322 | fprintf(stderr,"Error in function cDyn::%s\n",from);
323 | }
324 | void CLASS::error(int errnox){
325 | fprintf(stderr,"\nError occured in definition of module '%s' instance '%s'\n",
326 | dad->hero->type->name, hero->name);
327 | fputs("while processing '",stderr);
328 | hierName(stderr);
329 | fputs("' \n",stderr);
330 | fprintf(stderr,"----------------------------------------------------------------------\n");
331 | throw(errnox);
332 | }
333 | /*=====================================================================
334 | top module not connected
335 | While generating xdl, we found that the top module is not connected.
336 | TODO:This is normally an error, but what about macros?
337 | ======================================================================*/
338 | void CLASS::errTopModuleNotConnected(const char* from,const char* pin){
339 | errorIn(from);
340 | fprintf(stderr,"Top module's pin %s is not connected\n",pin);
341 | error(-1);
342 | }
343 | /******************************************************************************
344 | isPrimitive
345 | Originally I thought that having no subs makes it a root node, and a primitive.
346 | But for verilog output it is useful to put in LUT/MUXCY etc. subs that do
347 | not get xdl'd but do get verilog'd. So how do we know if we are a primitive
348 | or not? Simple - if we have a cfg we are a primitive!
349 | ******************************************************************************/
350 | bool CLASS::isPrimitive(){
351 | //
352 | // if(psubs) //primitives have psubs=NULL. modules create a collection.
353 | // return false;
354 | // return true;
355 | int iCfg = pparams->find("cfg",3);
356 | return (-1 != iCfg);
357 | }
358 | #include "cDynXdl.cpp"
359 | //#include "cDynVerilog.cpp"
360 |
--------------------------------------------------------------------------------
/cDyn.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #pragma once
20 | #include "cMultiWireWalker.h"
21 | /******************************************************************************
22 | cDyn
23 |
24 | A dynamic instance created during expansion.
25 | ******************************************************************************/
26 | class cProto;
27 | class cSub;
28 | class cWires;
29 | class cDyn {
30 | // data
31 | public:
32 | static FILE* fout;
33 |
34 | cSub *hero; //reference type of this dyn;
35 | cDyn *dad;
36 | cDyn** psubs; //tree
37 | int psubcnt; //number of children
38 |
39 | cDatum* loc; //final location
40 | cCollection* pparams; //actual parameters...
41 | private:
42 | static U32 seq; //wire sequence number
43 |
44 | public:
45 | cDyn(cSub* hero, cDyn* const dad);
46 | ~cDyn();
47 | void expand();
48 | void dump(FILE*f);
49 | // void hierName();
50 | void hierName(FILE*f);
51 | void place();
52 | //xdl-specific, see cDynXdl.cpp
53 | void xdlWires1();
54 | void xdlDefs(); //output definitions to xdl...
55 | void xdlHeader();
56 | //verilog-specific see cDynVlog.cpp
57 | void verilog();
58 | protected:
59 | char* expandFile(const char* filename);
60 | void errorIn(const char* from);
61 | void error(int errnox);
62 | void errTopModuleNotConnected(const char* from, const char*pin);
63 |
64 | int banglen(char* str,char*fullstr);//length of !...! parameter, str is past !
65 | cDatum* getLocation();
66 | int childIndex(cDyn*p);
67 | //xdl-specific, see cDynXdl.cpp
68 | void xdlNetHeader(cCollection* pins,int pindex);
69 | void xdlNetInpin(cCollection* pins,int pindex);
70 | void xdlStartWires1(cDyn* prim);
71 | void xdlContinueWire1(cDyn* prim,int pindex,int busid);
72 | void xdlWireUpOrDown1(int pindex,int busid);
73 | void xdlWirePower1();
74 | void xdlWireInner1(int pinst,int pindex,int busid,cMultiWireWalker& walker);
75 | //verilog-specific, see cDynVerilog.cpp
76 | void verilogDefs();
77 | bool isPrimitive();
78 | };
79 | // deprecated old-style wiring
80 | // void xdlContinueWire(cDyn* prim,int pindex,int busid);
81 | // void xdlStartWires1(cDyn* prim);
82 | // void xdlWirePower1();
83 | // void xdlWireInner1(int pinst,int pindex,int busid,cMultiWireWalker& walker);
84 |
85 |
--------------------------------------------------------------------------------
/cDynXdl.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | // This file is included from cDyn.cpp. It was separated purely for
20 | // convenience as cDyn got too long, but it made no sense (as usual) to
21 | // break it out into a class hierarchy (I really don't want to introduce
22 | // templates here).
23 |
24 | /*=====================================================================
25 | ======================================================================*/
26 | /* Ok, here we go. To output the definitions to XDL we need to walk the tree
27 | */
28 | #include "cMultiWireWalker.h"
29 | void CLASS::xdlDefs(){
30 | if(isPrimitive()){
31 | //fprintf(stderr," xdlDefs %p \n",loc);
32 | //loc->dump(stderr);
33 | char* primsite = loc->outputLoc();
34 |
35 | const char* tile = pDevice->tileFor(primsite);
36 | //leaf node (primitive). Output it.
37 | fputs("inst \"",fout);
38 | hierName(fout);
39 | fprintf(fout,"\" \"%s\", placed %s %s,\n",
40 | hero->type->name,
41 | tile,
42 | primsite //name like SLICE_XY
43 | );
44 | // now output the cfgs. They are in a TYPE_CFG collection datatype.
45 | //pparams->dump(stderr,"PARAMETERS:");
46 | fprintf(fout," cfg \"" );
47 | if(pparams){
48 | int i;
49 | for(i=0;isize;i++){
50 | // if(0==strncmp("loc",pparams->name[i],3)) continue; //do not output loc as cfg
51 | //else
52 | if(0==strcmp("cfg",pparams->name[i])){
53 | cCollection* cfgs = pparams->data[i]->valCfgs;
54 | int j; for(j=0;jsize;j++){
55 | fprintf(fout,"%s::%s ",cfgs->name[j],cfgs->data[j]->valStr);
56 | }
57 | } else {
58 | // loc is not interesting to us.
59 | if(0==strncmp("loc",pparams->name[i],3))
60 | continue;
61 |
62 | // cfgfile is of interest here
63 | if(0==strncmp("cfgfile",pparams->name[i],7)){
64 | FILE*f=fopen(pparams->data[i]->valStr,"r");
65 | if(!f){
66 | errorIn("expandFile");
67 | fprintf(stderr,"Trying to open cfgfile \"%s\"\n",pparams->data[i]->valStr);
68 | error(-1);
69 | }
70 | char buf[256];
71 | while(fgets(buf,256,f)){
72 | fputs(buf,fout);
73 | }
74 | fclose(f);
75 | continue;
76 | }
77 | errorIn("xdlDefs()");
78 | fprintf(stderr,"encountered parameter named '%s' in primitive '%s'\n",
79 | pparams->name[i], hero->name);
80 | //fprintf(stderr,"dumping parameters:\n");
81 | //pparams->dump(stderr,"xxx");
82 | throw(1);
83 | }
84 | }
85 | }
86 | fprintf(fout,"\";\n");
87 | //
88 | } else {
89 | int i;
90 | for(i=0;ixdlDefs();
92 | }
93 | }
94 | }
95 | /*=====================================================================
96 | Top-level entry to the wiring part of the process..
97 | ======================================================================*/
98 | /*=====================================================================
99 | Top-level entry to the wiring part of the process..
100 | ======================================================================*/
101 | void CLASS::xdlWires1(){
102 | //fprintf(stderr,"%s\n",__func__);
103 | //check for power wires originating here...
104 | if(psubcnt){
105 | xdlWirePower1(); //vcc/gnd only for non-prims.
106 | int i; for(i=0;ixdlWires1();
108 | }
109 | } else {
110 | //Aha-a primitive...Ask the parent to send work on just us,
111 | //otherwise we will never know who did what.
112 | if(dad)
113 | dad->xdlStartWires1(this);
114 | else{
115 | errorIn(__func__);
116 | fprintf(stderr,"dyn instance %s has no parent\n",hero->name);
117 | }
118 | }
119 | }
120 | /*=====================================================================
121 | ======================================================================*/
122 | void CLASS::xdlStartWires1(cDyn* prim){
123 | //fprintf(stderr,"%s\n",__func__);
124 | int refinst=childIndex(prim); //index of child primitive we love...
125 | cCollection* pins = prim->hero->pins;
126 | cMultiWireWalker walker(*hero->type->xwire);
127 | while(!walker.isEnd()){
128 | sWireEnd source=walker.getInc();
129 | if(refinst==source.inst) {//source is our child primitive?
130 | prim->xdlNetHeader(pins,source.pindex); //go in one
131 | xdlWireInner1(source.inst,source.pindex,source.busid,walker);
132 | fprintf(fout,";\n");
133 | }
134 | walker.seekNext();
135 | }
136 | }
137 |
138 | /*=====================================================================
139 | ======================================================================*/
140 | //searches up and down!
141 | /*=====================================================================
142 | ======================================================================*/
143 | //searches up and down!
144 | void CLASS::xdlWireUpOrDown1(int refindex,int busId){
145 | //fprintf(stderr,"shit %s psubs: %p\n",__func__,psubs==0?NULL:psubs);
146 | if(!psubs){
147 | //PRIMITIVE/leaf node... terminate net
148 | cCollection* pins = hero->pins;
149 | xdlNetInpin(pins,refindex);
150 | } else {
151 | //try to go back down
152 | // for wires starting with FF,pindex,busid
153 | cMultiWireWalker walker(*hero->type->xwire);
154 | while(!walker.isEnd()){
155 | int pinst; int pindex;int busid;
156 | walker.getInc(pinst,pindex,busid);
157 | if((pinst==INST_MY)&&(pindex==refindex)&&(busid==busId)){
158 | xdlWireInner1(pinst,pindex,busid,walker);
159 | }
160 |
161 | walker.seekNext();
162 |
163 | } //after, try up as well.
164 | if(dad)
165 | dad->xdlContinueWire1(this,refindex,busId);
166 | // else top module not connected...
167 | else
168 | //we are top...
169 | errTopModuleNotConnected(__func__,hero->pins->name[refindex]);
170 | }
171 | }
172 | //From just above, looks for wires reaching up to us.
173 | /*=====================================================================
174 | ======================================================================*/
175 | /*=====================================================================
176 | ======================================================================*/
177 | void CLASS::xdlContinueWire1(cDyn* prim,int refindex,int busId){
178 | //fprintf(stderr,"%s\n",__func__);
179 | //fprintf(stderr,"xdlContinueWire(%s,%d,%d)\n",prim->hero->name,refindex,busId);
180 | //using our wires, find the wire from pindex of prim..
181 | int refinst=childIndex(prim); //index of child primitive we love...
182 | cMultiWireWalker walker(*hero->type->xwire);
183 | while(!walker.isEnd()){
184 | int pinst; int pindex;int busid;
185 | walker.getInc(pinst,pindex,busid);
186 | if((pinst==refinst)&&(pindex==refindex)&&(busid==busId)){
187 | xdlWireInner1(pinst,pindex,busid,walker);
188 | }
189 | walker.seekNext();
190 | }
191 | }
192 | /*=====================================================================
193 | Wire the vcc net. VCCs originate from non-prims only.
194 | ======================================================================*/
195 | /*=====================================================================
196 | Wire the vcc net. VCCs originate from non-prims only.
197 | ======================================================================*/
198 | void CLASS::xdlWirePower1(){
199 | //fprintf(stderr,"%s\n",__func__);
200 | cMultiWireWalker walker(*hero->type->xwire);
201 | while(!walker.isEnd()){
202 | int pinst;int pindex;int busid;
203 | walker.getInc(pinst,pindex,busid);
204 | if(pinst==INST_MY){
205 | switch(pindex){
206 | case 0xFF: //vcc
207 | case 0xFE: //gnd
208 | xdlNetHeader(0,pindex);
209 | xdlWireInner1(pinst,pindex,0,walker); //ground and vcc are scalars
210 | fprintf(fout,";\n");
211 | }
212 | }
213 | walker.seekNext();
214 | }
215 | }
216 | /*=====================================================================
217 | ======================================================================*/
218 | /*=====================================================================
219 | * TODO: does not seem to use the parameters passed to it... check.
220 | ======================================================================*/
221 | void CLASS::xdlWireInner1(int pinst,int pindex,int busid,cMultiWireWalker& walker){
222 | //fprintf(stderr,"%s\n",__func__);
223 | //we should follow all destinations...
224 | //fprintf(stderr,"xdlWireInner(%d,%d,%d,%p)\n",pinst,pindex,busid,wl.wp);
225 | while(!walker.isStop()){
226 | walker.getInc(pinst,pindex,busid);
227 | cDyn* dyn;
228 | if(pinst==INST_MY){
229 | dyn=this;
230 | } else {
231 | dyn=psubs[pinst];
232 | }
233 | //end wire in wherever
234 | dyn->xdlWireUpOrDown1(pindex,busid);
235 | }
236 | }
237 | /*=====================================================================
238 | ======================================================================*/
239 | void CLASS::xdlHeader(){
240 | fprintf(fout,"# =======================================================\n");
241 | fprintf(fout,"# top FPGA Hammer tools 0.1.0\n");
242 | fprintf(fout,"# =======================================================\n");
243 | fprintf(fout,"design \"top\" %s v3.2 ,\n",pDevice->getDesignator() );
244 | fprintf(fout," cfg \" \" ;\n") ;
245 | }
246 |
247 | /*=====================================================================
248 | Called to start a net output XDL-style.
249 | Note: primitives have no buses, all pins are scalars.
250 | ======================================================================*/
251 | void CLASS::xdlNetHeader(cCollection*pins,int pindex){
252 | fputs(" net \"",fout);
253 | hierName(fout);
254 | switch(pindex){
255 | case 255:
256 | fprintf(fout,"/vcc/%.5d\" vcc,\n",seq++);//attach sequence number
257 | break;
258 | case 254:
259 | fprintf(fout,"/gnd/%.5d\" gnd,\n",seq++);//attach sequence number
260 | break;
261 | default:
262 | fprintf(fout,"/%s",pins->name[pindex]); //attach outpin name
263 | fprintf(fout,"/%.5d\" ,\n outpin \"",seq++);//attach sequence number
264 | hierName(fout);
265 | fprintf(fout,"\" %s ,\n",pins->name[pindex]);
266 | break;
267 | }
268 | }
269 | /*=====================================================================
270 | ======================================================================*/
271 | void CLASS::xdlNetInpin(cCollection*pins,int pindex){
272 | fputs(" inpin \"",fout);
273 | hierName(fout);
274 | fputs("\" ",fout);
275 | fputs(pins->name[pindex],fout);
276 | fputs(" ,\n",fout);
277 | }
278 | /* DEPRECATED */
279 | /*=====================================================================
280 | ======================================================================*/
281 | /*void CLASS::xdlStartWires(cDyn* prim){
282 | int refinst=childIndex(prim); //index of child primitive we love...
283 | cWires* wires = hero->type->pwires;
284 | cCollection* pins = prim->hero->pins;
285 | cWireList wl=wires->seekFirst();
286 |
287 | while(wl.exists()){
288 | int pinst; int pindex;int busid;
289 | wl.getInc(pinst,pindex,busid);
290 | if(refinst==pinst){ //sourced refinst?
291 | // fprintf(stderr,"B. xdlStartWires: doing it\n");
292 | prim->xdlNetHeader(pins,pindex); //go in one
293 | xdlWireInner(pinst,pindex,busid,wl);
294 | fprintf(fout,";\n");
295 | };
296 | wl.seekNext();
297 | }
298 | }
299 | void CLASS::xdlWireInner(int pinst,int pindex,int busid,cWireList wl){
300 | fprintf(stderr,"%s\n",__func__);
301 | //we should follow all destinations...
302 | //fprintf(stderr,"xdlWireInner(%d,%d,%d,%p)\n",pinst,pindex,busid,wl.wp);
303 | while(!wl.isLast()){
304 | wl.getInc(pinst,pindex,busid);
305 | cDyn* dyn;
306 | if(pinst==0xFF){
307 | fprintf(stderr,"dyn=this\n");
308 | dyn=this;
309 | } else {
310 | fprintf(stderr,"dyn=%p\n",psubs[pinst]);
311 | dyn=psubs[pinst];
312 | }
313 | //end wire in wherever
314 | dyn->xdlWireUpOrDown(pindex,busid);
315 | }
316 | }
317 | void CLASS::xdlWirePower(){
318 | cWires* wires = hero->type->pwires;
319 | cWireList wl=wires->seekFirst();
320 | while(wl.exists()){
321 | int pinst;int pindex;int busid;
322 | wl.getInc(pinst,pindex,busid);
323 | if(pinst==0xFF){
324 | switch(pindex){
325 | case 0xFF: //vcc
326 | case 0xFE: //gnd
327 | xdlNetHeader(0,pindex);
328 | xdlWireInner(pinst,pindex,0,wl); //ground and vcc are scalars
329 | fprintf(fout,";\n");
330 | }
331 | }
332 | wl.seekNext();
333 | }
334 | }
335 | void CLASS::xdlContinueWire(cDyn* prim,int refindex,int busId){
336 | //fprintf(stderr,"xdlContinueWire(%s,%d,%d)\n",prim->hero->name,refindex,busId);
337 | //using our wires, find the wire from pindex of prim..
338 | int refinst=childIndex(prim); //index of child primitive we love...
339 | cWires* wires = hero->type->pwires;
340 | //we need to seek out one at refinst:pindex start...
341 | cWireList wl=wires->seekFirst();
342 | while(wl.exists()){
343 | int pinst; int pindex;int busid;
344 | wl.getInc(pinst,pindex,busid);
345 | if((pinst==refinst)&&(pindex==refindex)&&(busid==busId)){
346 | xdlWireInner(pinst,pindex,busid,wl);
347 | }
348 | wl.seekNext();
349 | }
350 | }
351 | void CLASS::xdlWireUpOrDown(int refindex,int busId){
352 | fprintf(stderr,"shit %s psubs: %p\n",__func__,psubs==0?NULL:psubs);
353 | //fprintf(stderr,"xdlWireUpOrDown(%d,%d)\n",refindex,busId);
354 | if(!psubs){
355 | //PRIMITIVE/leaf node... terminate net
356 | cCollection* pins = hero->pins;
357 | xdlNetInpin(pins,refindex);
358 | } else {
359 | //try to go back down
360 | // for wires starting with FF,pindex,busid
361 | cWires* wires = hero->type->pwires;
362 | cWireList wl=wires->seekFirst();
363 | while(wl.exists()){
364 | int pinst; int pindex;int busid;
365 | wl.getInc(pinst,pindex,busid);
366 | if((pinst==0xFF)&&(pindex==refindex)&&(busid==busId)){
367 | xdlWireInner(pinst,pindex,busid,wl);
368 | }
369 | wl.seekNext();
370 | } //after, try up as well.
371 | if(dad)
372 | dad->xdlContinueWire(this,refindex,busId);
373 | // else top module not connected...
374 | else
375 | //we are top...
376 | errTopModuleNotConnected(__func__,hero->pins->name[refindex]);
377 | }
378 | }
379 | void CLASS::xdlWires(){
380 | fprintf(stderr,"%s\n",__func__);
381 | //check for power wires originating here...
382 | if(psubcnt){
383 | xdlWirePower(); //vcc/gnd only for non-prims.
384 | int i; for(i=0;ixdlWires();
386 | }
387 | } else {
388 | //Aha-a primitive...Ask the parent to send work on just us,
389 | //otherwise we will never know who did what.
390 | if(dad)
391 | dad->xdlStartWires(this);
392 | else{
393 | errorIn(__func__);
394 | fprintf(stderr,"dyn instance %s has no parent\n",hero->name);
395 | }
396 | }
397 | }
398 |
399 | */
--------------------------------------------------------------------------------
/cModule.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #include "global.h"
20 | #include "cModule.h"
21 | #include "cDevice.h"
22 | #include "cDyn.h"
23 | #include "cSub.h"
24 | #define CLASS cModule
25 |
26 | extern cDevice* pDevice;
27 |
28 | CLASS::CLASS(char* name,int size)
29 | : cProto(name,size)
30 | {
31 | //printf("MODULE %s %d\n",name,size);
32 | psubs=new cCollection(4096); //TODO: make collection expand
33 | pDevice->addProto(name,size,this); //will check for dups
34 | }
35 | CLASS::~CLASS(){
36 | // g_hash_table_destroy(subs);
37 | }
38 |
39 |
40 | cSub* CLASS::getSub(char*name){
41 | int i = psubs->find(name);
42 | if(-1==i)
43 | return NULL;
44 | cDatum* r = psubs->getDatum(i);
45 | if(TYPE_SUB!=r->type)
46 | return r->valSub;
47 | return 0;
48 | }
49 |
50 | /******************************************************************************
51 | * D U M P
52 | *******************************************************************************/
53 | void CLASS::dump(FILE*f){
54 | ((cProto*)this)->dump(f);
55 | // fprintf(f,"%d parameter names:\n",paramnames.size);
56 | // int i;
57 | // for(i=0;idump(f,"subs:\n");
61 | }
62 | /******************************************************************************
63 | * Verilog
64 | * Output this module as a verilog module.
65 | *******************************************************************************/
66 | void CLASS::verilog(FILE*fout){
67 | // first, check the module's instances and make sure their types are known.
68 | int iVlog = paramnames->find("Verilog",7);
69 | if(-1==iVlog){
70 | if(psubs){
71 | int i; for(i=0;isize;i++){
72 | cSub* sub=psubs->data[i]->valSub;
73 | if(!sub->type->converted)
74 | sub->type->verilog(fout);
75 | }
76 | }
77 | // Now output the module verilog style
78 | fprintf(fout,"module %s(\n",name);
79 | // pins
80 | pins->vlogPinDefs(fout); //see cCollection.cpp
81 | fputs(");\n",fout);
82 |
83 | // output the module's instances
84 | if(psubs){
85 | int i; for(i=0;isize;i++){
86 | cSub* sub=psubs->data[i]->valSub;
87 | //Create a wire for every pin of this sub, before the sub...
88 | sub->pins->vlogWireDefs(fout,sub->name);
89 | //first, the loc
90 | //fprintf(fout,"(*RLOC="
91 | fprintf(fout," %s ",sub->type->name);
92 | fprintf(fout," %s(",sub->name);
93 | sub->pins->vlogPins(fout,sub->name); //output the pins in parens
94 | fputs(");\n",fout);
95 | }
96 | }
97 | // wire up our module
98 | vlogWiring(fout);
99 | fputs("\n",fout);
100 | fputs("endmodule\n",fout);
101 | } else {
102 | fputs(paramnames->data[iVlog]->valStr, fout);
103 | }
104 | }
105 | /******************************************************************************
106 | At this point we defined the module's instances, and declared all inst inputs
107 | and outputs as verilog wires. Now the module wiring can connect them all!
108 | ******************************************************************************/
109 | void CLASS::vlogWiring(FILE*fout){
110 | //TODO: reimplement vlog wiring!
111 | fprintf(stderr,"Verilog needs re-implementation with new wiring format\n");
112 | exit(-1);
113 | /*
114 | cWireList wl = pwires->seekFirst();
115 | while(wl.exists()){
116 | //more wires exist.
117 | //source
118 | int sInst; int sIndex;int sBusid;
119 | wl.getInc(sInst,sIndex,sBusid);
120 | //fprintf(fout,"from %d %d %d\n",sInst,sIndex,sBusid);
121 | while(!wl.isLast()){
122 | int dInst; int dIndex;int dBusid;
123 | wl.getInc(dInst,dIndex,dBusid);
124 | //fprintf(fout,"to %d %d %d\n",dInst,dIndex,dBusid);
125 | //Now, verilog-style assigns. Destination cannot be a power net.
126 | fputs(" assign ",fout);
127 | cModule* modDest = (0xFF==dInst)?this:(cModule*)psubs->data[dInst]->valSub->type;
128 | modDest->vlogAssignDest(fout,dIndex,dBusid);
129 | fputs(" = ",fout);
130 | if(0xFF==sInst){
131 | //source is "MY" pin. The pin can also be a power net
132 | switch(sIndex){
133 | case 0xFF: fputs("vcc",fout); break;
134 | case 0xFE: fputs("gnd",fout); break;
135 | default:
136 | fprintf(fout,"%s_%s",name,pins->name[sIndex]);
137 | break;
138 | }
139 | }else{
140 | fprintf(fout,"%s_%s",psubs->name[sInst],psubs->data[sInst]->valSub->pins->name[sIndex]);
141 | }
142 | fputs(";\n",fout);
143 | }
144 | wl.seekNext(); //next wire
145 | }
146 | */
147 | }
148 | /******************************************************************************
149 | Verilog output of a pin name for ASSIGNMENTS!
150 |
151 | ******************************************************************************/
152 | void CLASS::vlogAssignDest(FILE* fout,U32 pindex,U32 busid){
153 | fprintf(fout,"%s_%s",name,pins->name[pindex]);
154 | //final issue - is it a scalar or a bus?
155 | if(pins->data[pindex]->pinBusWidth > 1){
156 | //yes,a bus
157 | fprintf(fout,"[%d]",busid);
158 | }
159 | }
160 | void CLASS::vlogAssignSrc(FILE* fout,U32 pindex,U32 busid){
161 | }
--------------------------------------------------------------------------------
/cModule.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | /******************************************************************************
20 | A user-defined module
21 |
22 | PrimDef is the low-level building block of the FPGA. It exports names of pins
23 | ******************************************************************************/
24 | #include "cProto.h"
25 | class cModule;
26 | // The proto has pins and parameter names! also * psubs
27 | class cModule : public cProto{
28 | public:
29 | cModule( char*name,int size);
30 | ~cModule();
31 | cSub* getSub(char*name);
32 | // virtual cProto** subs(); //return count of subs, see cDyn expansion
33 | void dump(FILE*f);
34 | //cCollection pins; //from cProto
35 | virtual void verilog(FILE*f);
36 | void vlogWiring(FILE*f);
37 | void vlogAssignDest(FILE*fout,U32 pindex,U32 busid);
38 | void vlogAssignSrc(FILE*fout,U32 pindex,U32 busid);
39 | // Data
40 | };
41 |
--------------------------------------------------------------------------------
/cMultiWire.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #include "global.h"
20 | #include "cMultiWire.h"
21 |
22 | //sWireEnd dump
23 | void sWireEnd::dump(FILE*f){
24 | switch(inst){
25 | case INST_STOP:
26 | fprintf(f,"-----\n");
27 | break;
28 | case INST_END:
29 | fprintf(f,"-fini-\n");
30 | break;
31 | default:
32 | fprintf(f,"-%d-%d-%d-\n",inst,pindex,busid);
33 | break;
34 | }
35 | }
36 |
37 |
38 | #define CLASS cMultiWire
39 | CLASS::CLASS(const cMultiWire& orig){
40 | buf=((cMultiWire&)orig).getBuf();
41 | }
42 |
43 | CLASS::CLASS(){
44 | buf=0;
45 | }
46 |
47 | CLASS::~CLASS(){
48 | free(buf);
49 | }
50 |
51 | #include "cMultiWireWalker.h"
52 | void CLASS::dump(FILE*f){
53 | cMultiWireWalker* walker = new cMultiWireWalker(*this);
54 | while(!walker->isEnd()){
55 | while(!walker->isStop()){
56 | fprintf(f," %p ",this);
57 | walker->getInc().dump(f);
58 | }
59 | fprintf(f," %p ",this);
60 | walker->getInc().dump(f); //dump the stop
61 | }
62 | fprintf(f," %p ",this);
63 | walker->getInc().dump(f); //dump the end, parse too far but who cares...
64 | fprintf(f,"DONE\n");
65 |
66 | }
--------------------------------------------------------------------------------
/cMultiWire.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #pragma once
20 | /******************************************************************************
21 | Cleaning up the wiring.
22 | Each endpoint consists of a 4-byte structure:
23 | ******************************************************************************/
24 | struct sWireEnd {
25 | U16 inst; //index of the instance
26 | U8 pindex; //index of the pin
27 | U8 busid; //start bus index
28 |
29 | void dump(FILE*f);
30 | };
31 | //special cases:
32 | #define INST_MY 0xFFFF
33 | #define INST_STOP 0xFFFE //end of wire
34 | #define INST_END 0xFFFD //end of wire list
35 |
36 | class cModule;
37 | class cMultiWireWalker;
38 | class cMultiWire {
39 | public:
40 | cMultiWire(const cMultiWire& orig);
41 | ~cMultiWire();
42 | sWireEnd* getBuf(){return buf;} //for derived constructor use
43 | void dump(FILE*f);
44 | protected:
45 | cMultiWire(); //only called by builder
46 | //DATA
47 | sWireEnd* buf; //buffer of sWireEnds
48 |
49 | };
50 |
--------------------------------------------------------------------------------
/cMultiWireBuilder.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #include "global.h"
20 | #include "cMultiWireBuilder.h"
21 | #define CLASS cMultiWireBuilder
22 | CLASS::CLASS(){
23 | max = CMULTIWIRE_CAP_INIT; //initial limit, in wireends.
24 | buf = (sWireEnd*)malloc(max*sizeof(sWireEnd));
25 | index=0;
26 | }
27 |
28 | CLASS::~CLASS(){
29 | //we never free the buffer - it is used by consumers.
30 | }
31 |
32 | void CLASS::add(int inst,int port,int busid){
33 | //is there room
34 | if(index>=max) {
35 | // reallocate, double size
36 | //fprintf(stderr,"cMultiWireBuilder: reallocating from %d to %d\n",max,max*2);
37 | max = max*2;
38 | buf = (sWireEnd*)realloc(buf,max*sizeof(sWireEnd));
39 | }
40 | buf[index].inst=inst;
41 | buf[index].pindex=port;
42 | buf[index].busid=busid;
43 | index++;
44 | //fprintf(stderr,"cMultiWireBuilder: added %d %d %d, total %d\n",inst,port,busid,index);
45 | }
46 | void CLASS::stop(){
47 | add(INST_STOP, 0, 0);
48 | }
49 | void CLASS::end(){
50 | add(INST_END, 0, 0);
51 | }
52 | cMultiWire* CLASS::solidify(){
53 | end();
54 | buf = (sWireEnd*)realloc(buf,index*sizeof(sWireEnd));
55 | //fprintf(stderr,"cMultiWireBuilder: final size %d units\n",index);
56 | cMultiWire* ret = new cMultiWire(*this);
57 | buf=0; //this way it will not be free'd
58 | return ret;
59 | }
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/cMultiWireBuilder.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #pragma once
20 | #include "cMultiWire.h"
21 | #define CMULTIWIRE_CAP_INIT 16
22 | class cMultiWireBuilder : public cMultiWire {
23 | public:
24 | cMultiWireBuilder();
25 | ~cMultiWireBuilder();
26 | void add(int inst,int port,int busid);
27 | cMultiWire* solidify();
28 | void stop();
29 | void end();
30 | private:
31 | U32 max;
32 | U32 index;
33 | };
34 |
--------------------------------------------------------------------------------
/cMultiWireWalker.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #include "global.h"
20 | #include "cMultiWireWalker.h"
21 | #define CLASS cMultiWireWalker
22 |
23 | CLASS::CLASS(cMultiWire& it){
24 | buf=it.getBuf();
25 | index=0;
26 | }
27 | CLASS::~CLASS(){
28 | buf=0;
29 | //do not free - we don't own the wire, just walk it
30 |
31 | }
32 |
33 |
34 | void CLASS::getInc(int& inst,int& pindex,int& busid){
35 | inst = buf[index].inst;
36 | pindex = buf[index].pindex;
37 | busid = buf[index].busid;
38 | index++;
39 | }
40 | sWireEnd& CLASS::getInc(){
41 | return buf[index++];
42 | }
43 | bool CLASS::isStop(void){
44 | return(INST_STOP==buf[index].inst);
45 | }
46 | bool CLASS::isEnd(void){
47 | return(INST_END==buf[index].inst);
48 | }
49 | // Seek next wire. If end, leave at end.
50 | bool CLASS::seekNext(){
51 | while(true){
52 | switch(buf[index].inst){
53 | case INST_STOP:
54 | index++;
55 | return true;
56 | case INST_END:
57 | return false;
58 | default:
59 | index++;
60 | break;
61 | }
62 | }
63 | }
64 | //seek a particular instance
65 | bool CLASS::seekInst(int inst){
66 | if(isEnd())
67 | return false; //at end!
68 | //starting at outgoing instance pointer...
69 | while(seekNext()){
70 | if(inst==buf[index].inst)
71 | return true;
72 | }
73 | return false;
74 | }
--------------------------------------------------------------------------------
/cMultiWireWalker.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | /******************************************************************************
20 | This class starts out by referencing an existing cMultiWire. It keeps an
21 | index and walks the wire structure.
22 | ******************************************************************************/
23 | #pragma once
24 | #include "cMultiWire.h"
25 | class cMultiWireWalker : public cMultiWire {
26 | public:
27 | cMultiWireWalker(cMultiWire& it);
28 | ~cMultiWireWalker();
29 | void getInc(int& inst,int& index,int& busid);
30 | sWireEnd& getInc();
31 | bool isStop();
32 | bool isEnd();
33 | bool seekNext(); //true=next false=end.
34 | bool seekInst(int inst);
35 |
36 | private:
37 | U32 index;
38 | };
39 |
--------------------------------------------------------------------------------
/cParse.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #include "global.h"
20 | #include "cParse.h"
21 | #include
22 | #include "cModule.h"
23 | #include "cQuark.h"
24 | #include "cSub.h"
25 | #define CLASS cParse
26 | #include "cDevice.h"
27 | extern cDevice* pDevice;
28 |
29 | #include "cMultiWireBuilder.h"
30 | CLASS::CLASS(){
31 | topModule = NULL;
32 | }
33 | CLASS::~CLASS(){
34 | }
35 | /******************************************************************************
36 | handleInclude
37 |
38 |
39 | ******************************************************************************/
40 | bool CLASS::handleInclude(int len){
41 | static const char* funcname="handleInclude()";
42 | if(tokAnything("#include",len)){
43 | ws(true);
44 | if('"'==*ptr){
45 | cDatum* d = parseQuotedString();
46 | /* and the type of the file included is... */
47 | char* xdlrc = strstr(d->valStr,".xdlrc");
48 | if(xdlrc){
49 | if(pDevice){
50 | errorIn(funcname);
51 | fprintf(stderr,"Device is already included");
52 | error(1);
53 | }
54 | pDevice = new cDevice();
55 | pDevice->initialize();
56 | pDevice->parse_xdlrc(d->valStr);
57 |
58 | } else {
59 | FILE* f = fopen(d->valStr,"r");
60 | if(!f) {
61 | errorIn(funcname);
62 | fprintf(stderr,"Unable to open file '%s'\n",d->valStr);
63 | error(1);
64 | }
65 | /* to handle reentrant includes, preserve old state */
66 | FILE* fold = file;
67 | int linenoOld=lineno;
68 | lineno=0;
69 | parse(f);
70 | file=fold;
71 | lineno=linenoOld;
72 | }
73 | } else {
74 | errorIn(funcname);
75 | fprintf(stderr,"filename must be in quotes");
76 | error(1);
77 | }
78 | return true; //included.
79 | } else return false; //not an include...
80 | }
81 | /******************************************************************************
82 | parsePins
83 |
84 | parse a declaration of pins in the module.
85 |
86 | name scalar pin
87 | name[3] a bus. Width must be a literal integer 1-255
88 |
89 |
90 | ******************************************************************************/
91 | void CLASS::parsePins(cCollection* pins,int dir){
92 | // if(dir>1)
93 | // fprintf(stderr,"WTF\n");
94 | ws(true);
95 | int len=requireWord("(",1);
96 | ws(true);
97 | if(')'==*ptr) //in case it's a ()
98 | ptr++;
99 | else do {
100 | int i= pins->add(ptr,len,cDatum::newPin(dir,1)); //for now, scalar pin.
101 | ptr+=len; //skip pin name
102 | //showtok();
103 | if('['==*ptr){ //defining a pin bus
104 | ptr++;
105 | ws(true);
106 | int width = parseLiteral();
107 | if((width<1)||(width>255)) {
108 | errorIn("parsePins");
109 | fprintf(stderr,"A bus must have at least 1 and at most 255 pins\n");
110 | error(1);
111 | }
112 | pins->data[i]->pinBusWidth=width;
113 | len=requireWord("]",1);
114 | }
115 | char sep;
116 | len=requireSeparator("parsePins",",; \t\n)",&sep); //ws with comma allowed here...
117 | if(')'==sep) break;
118 | } while(true);
119 | }
120 | /******************************************************************************
121 | parseParamNames
122 |
123 | In the declaration of parameters ( NAME (ins)(outs)(params)) parameters names
124 | are declared as a list. In addition, default values may be declared as
125 | name:default value.
126 |
127 | ******************************************************************************/
128 | void CLASS::parseParamNames(cModule* module){
129 | //fprintf(stderr,"PARAM [%s]\n",ptr);
130 | requireSeparator("parseParamNames","("); //we need a (
131 | bool doit=true;
132 | while(doit){
133 | ws(true);
134 | int len = cnt();
135 | if((1==len)&&(')'==*ptr)){
136 | ptr++;
137 | break;
138 | }
139 | //start by creating a named parameter with NULL data
140 | int index=module->paramnames->add(ptr,len,0);
141 | ptr+=len;
142 | ws(true);
143 | char c = *ptr;
144 | cDatum* pdatum;
145 | switch(c){
146 | case ':' :
147 | //Default value provided.
148 | ptr++;
149 | ws(true);
150 | if('{'==*ptr){
151 | pdatum = parseBracedString();
152 | } else {
153 | len=cnt();
154 | pdatum=cDatum::newStr(ptr,len);
155 | ptr+=len;
156 | }
157 | module->paramnames->data[index]= pdatum;
158 | ws(true);
159 | // now either , or ). Set c and fallthrough! WATCH OUT FOR ORDER HERE
160 | c=*ptr;
161 | switch(c){
162 | case ',': ptr++; break;
163 | case ')': ptr++; doit=false; break;
164 | }
165 | //fprintf(stderr,"post-default parameter parser at [%s]\n",ptr);
166 | //fprintf(stderr,"DEFAULT PARAMETER %s:%s\n",module->paramnames->name[index],module->paramnames->data[index]->valStr );
167 | break;
168 | case ',':
169 | ptr++;
170 | break;
171 | case ')':
172 | ptr++;
173 | doit=false;
174 | break;
175 | }
176 | }
177 | module->paramnames->solidify();
178 | }
179 | int i=0;
180 | bool BUGGER ;//DEBUGGING-REMOVE ME
181 | /******************************************************************************
182 | parseWireEndpoint
183 |
184 | Parse a unit of wire declaration.
185 |
186 | ******************************************************************************/
187 | sWireEndpoint CLASS::parseWireEndpoint(cModule* module,int idxInst,cSub* pinst){
188 | cCollection*ppins;
189 | sWireEndpoint ep;
190 | ep.busid1=ep.busid2=0; //for simple scalar wires.
191 | // cProto *proto;
192 | ws(true); int len=cnt(" '");
193 | //if(BUGGER)
194 | // fprintf(stderr,"STARTING %d[%.*s]\n",i++,len,ptr);
195 | //if(i>590)
196 | // fprintf(stderr,"endpoint %d[%.*s]\n",i++,len,ptr);
197 | cProto* pinowner; //for error reporting mainly...
198 | if(tokAnything("my",len)){
199 | ep.inst=INST_MY;
200 | ppins=module->pins;
201 | pinowner=module;
202 | /*proto=module;*/
203 | } else {
204 | if((tokAnything("his",len)) && (-1 != idxInst)){
205 | ep.inst=idxInst;
206 | ppins=pinst->pins;
207 | } else {
208 | /* find the inst by name
209 | */
210 | //if(i>=580)
211 | // fprintf(stderr,"A\n");
212 | cParseStream::validateName(__func__,len); //WTF - it did not see it?f
213 | //if(i>=580){
214 | // fprintf(stderr,"trying to find %.*s %d\n",len,ptr,len);
215 | // fprintf(stderr,"modules->psubs is %p\n",module->psubs);
216 | // module->psubs->dump(stderr,"collection");
217 | //}
218 | int inst =module->psubs->find(ptr,len);
219 | //if(i>=580)
220 | // fprintf(stderr,"C\n");
221 |
222 | //fprintf(stderr,"FOUND inst %s at %d [%s]\n",module->psubs->name[ep.inst],ep.inst,ptr);
223 | if(-1==inst){
224 | errorIn("parseWireEndpoint()");
225 | fprintf(stderr,"Instance '%.*s' has not been declared in module '%s'\n",
226 | len,ptr,module->name);
227 | error(1);
228 | }
229 | ep.inst=inst;
230 | ppins =module->psubs->data[ep.inst]->valSub->pins;
231 | ptr+=len;
232 | //if(i>580)
233 | // fprintf(stderr,"D\n");
234 | }
235 | pinowner = module->psubs->data[ep.inst]->valSub->type;
236 | }
237 | // handle 's neatly
238 | if(('\''==*ptr)&&('s'==*(ptr+1))) ptr+=2;
239 |
240 | ws(true); len=cnt();
241 | if(tokAnything("vcc",len)){
242 | ep.pindex=0xFF;
243 | } else if(tokAnything("gnd",len)){
244 | ep.pindex=0xFE;
245 | } else {
246 | int pindex = ppins->find(ptr,len);
247 | //fprintf(stderr,"FOUND PIN %d %s at %d \n",len,ptr,pindex);
248 | if(-1==pindex){
249 | errorIn("parseWireEndpoint()");
250 | fprintf(stderr,"Pin '%.*s' has not been declared in module '%s' \n",
251 | len,ptr,
252 | // module->psubs->data[ep.inst]->valSub->name, //wire's owner sub
253 | pinowner->name //and its type
254 | );
255 | error(-1);
256 | }
257 | ep.pindex= pindex; //don't forget it's a byte!
258 | ptr+=len;
259 | /* could be a [busid] or range [busid1:busid2] */
260 | if('['==*ptr){
261 | //fprintf(stderr,"BUS %s\n",ptr);
262 | ptr++;
263 | ws(true); ep.busid2=ep.busid1=parseLiteral();
264 | if((ep.busid1<0)||(ep.busid1>=(ppins->data[ep.pindex]->pinBusWidth))) {
265 | errorIn("parseWireEndpoint");
266 | fprintf(stderr,"Pin %s[%d] has an invalid index; should be between %d and %d\n",
267 | ppins->name[ep.pindex],
268 | ep.busid1,
269 | ep.busid1+1,
270 | ppins->data[ep.pindex]->pinBusWidth-1);
271 | error(1);
272 | }
273 | // is it a range?
274 | //fprintf(stderr,"XXX ..%s..\n",ptr);
275 | if(':'==*ptr){
276 | ptr++;
277 | ws(true); ep.busid2=parseLiteral();
278 | if((ep.busid2<=ep.busid1)||(ep.busid2>=(ppins->data[ep.pindex]->pinBusWidth))) {
279 | errorIn("parseWireEndpoint");
280 | fprintf(stderr,"Pin %s[%d:%d] has an invalid index; should be between %d and %d\n",
281 | ppins->name[ep.pindex],ep.busid1,
282 | ep.busid2,
283 | ep.busid1+1,
284 | ppins->data[ep.pindex]->pinBusWidth-1);
285 | error(1);
286 | }
287 | }
288 | ws(true);requireWord("]",1);
289 | }
290 | }
291 | // fprintf(stderr,"PARSED: %s inst %d index %d from %d to %d\n",
292 | // ppins->name[ep.pindex], ep.inst,ep.pindex,ep.busid1,ep.busid2);
293 | //fprintf(stderr,"AT {%s}\n",ptr);
294 | return ep;
295 | }
296 | /******************************************************************************
297 | wire
298 |
299 | Wires are stored in the module. At wiring time, the names of
300 | relevant insts are in the inst array,and the names of pins are
301 | solidly in the proto's arrays. We are free to use the bytecode
302 | encoding scheme as follows (each item is a byte index)
303 | ...
304 | $FF inst means us, the module.
305 |
306 | ******************************************************************************/
307 |
308 | void CLASS::parseWire(cModule* module,int idxInst,cSub* pinst,cMultiWireBuilder* xwire){
309 | //fprintf(stderr,"wire ");
310 | // First collect endpoints, which may be buses.
311 | #define MAX_ENDPOINTS 4096
312 | sWireEndpoint ep[MAX_ENDPOINTS];
313 | //parse all the endpoints. ep[0] is the source endpoint.
314 | //BUGGER=true;
315 | ep[0]=parseWireEndpoint(module,idxInst,pinst);
316 | //BUGGER=false;
317 | int srcBusWidth= ep[0].busid2 - ep[0].busid1; //width-1; 0 means scalar...
318 | //fprintf(stderr,"module '%s'; width %d\n",module->name,buswidth);
319 | int i=1; //index of endpoint being processed
320 | int len;
321 | while(true){
322 | ws(true); len=cnt();
323 | if(tokAnything(",",len)) //just skip it
324 | len=cnt();
325 | if(tokAnything("to",len))
326 | len=cnt(); //just skip it
327 | ep[i]=parseWireEndpoint(module,idxInst,pinst);
328 | /* if source is a scalar, we can connect it to all destination bus widths.
329 | if it's a bus, it has to match the destination endpoint buswidths. */
330 | if(srcBusWidth) { //a scalar can go to a bus..
331 | if(srcBusWidth != (ep[i].busid2-ep[i].busid1)){
332 | errorIn("parseWire");
333 | fprintf(stderr,"bus width mismatch. Expected %d, found %d\n",srcBusWidth+1,ep[i].busid2-ep[i].busid1+1);
334 | error(1);
335 | }
336 | }
337 | i++;
338 | if(i>(MAX_ENDPOINTS-1)){
339 | errorIn("parseWire");
340 | fprintf(stderr,"Wire chain too long; maximum %d exceeded\n",MAX_ENDPOINTS);
341 | error(1);
342 | }
343 | ws(true); len=cnt();
344 | if(tokAnything(";",len)) break;
345 | }
346 | // Now add wires to the module. The reason for all this is that buses
347 | // must be looped through wire by wire. So now, loop on first one's
348 | // bus width.
349 | //fprintf(stderr,"WILL ADD BUS OF %d WIRES\n",buswidth+1);
350 | if(srcBusWidth){
351 | //fprintf(stderr,"bus wire in module '%s'; width %d\n",module->name,srcBusWidth);
352 | int j;
353 | for(j=0;jpwires->add(
358 | // ep[k].inst,
359 | // ep[k].pindex,
360 | // ep[k].busid1+j);
361 | xwire->add(
362 | ep[k].inst,
363 | ep[k].pindex,
364 | ep[k].busid1+j);
365 |
366 | }
367 | // module->pwires->close(); //and end the wire
368 | xwire->stop();
369 | }
370 | } else{ //source is a scalar; connect it to all destinations
371 | //source wire is a scalar...
372 | // module->pwires->add( ep[0].inst,ep[0].pindex,ep[0].busid1);
373 | xwire->add( ep[0].inst,ep[0].pindex,ep[0].busid1);
374 | int ei; //endpoint index
375 | for(ei=1;einame,j);
379 | // module->pwires->add(ep[ei].inst, ep[ei].pindex,j);
380 | xwire->add(ep[ei].inst, ep[ei].pindex,j);
381 | }
382 | }
383 | // module->pwires->close(); //one wire from source, closed.
384 | xwire->stop();
385 | }
386 | }
387 |
388 | /******************************************************************************
389 | parseParamData - TRICKY! We will create 'unrealized' strings to be
390 | expanded during dynamic expansion phase.
391 | Right now it's only cfgs...
392 | ******************************************************************************/
393 | cDatum* CLASS::parseParamData(cModule*module,const char* prepend){
394 | cDatum*ret;
395 | int len;
396 | if('{'==*ptr){
397 | /* cfg-style list. Parse it as a long string, a pair at a time
398 | separated by spaces. It's a little messy as we need to do multi-line */
399 | ptr++;
400 | int total=0;
401 | int max = 8192; //TODO:bufsize
402 | char*bu=(char*)malloc(max);
403 | bu[0]=0;
404 | if(prepend){
405 | strcpy(bu,prepend);
406 | }
407 | while(true){
408 | ws(true); len=cnt(" }\0");
409 | //fprintf(stderr,"parseParamData at: %d [%s]\n",len,ptr);
410 | if((len==0)&&('}'==*ptr)) { break;}
411 | total+=len;
412 | if(max<=total){
413 | errorIn("parseParamData()");
414 | fprintf(stderr,"out of space parsing a cfg string\n");
415 | error(1);
416 | }
417 | strncat(bu,ptr,len);
418 | strcat(bu," ");
419 | ptr+=len;
420 | //If we bounced on ' )', the ) will stump us...
421 | ws(true); //after there may be a ws
422 | }
423 | //strcat(bu,";");
424 | ptr++;
425 | ret=cDatum::newUnrealized(bu,strlen(bu));
426 | //fprintf(stderr,"unrealized buffer is %d\n",strlen(bu));
427 | free(bu);
428 | //done
429 | } else {
430 | len=cnt(" ;");
431 | //fprintf(stderr,"QQQ %d, [%.*s]\n",len,len,ptr);
432 | ret = cDatum::newUnrealized(ptr,len);
433 | ptr+=len;
434 | }
435 | return ret;
436 | }
437 | /******************************************************************************
438 | parsePairs.
439 | Our sub started exactly like its type paramnames, with defaults.
440 | scan the pairs and fix the data
441 | ******************************************************************************/
442 | void CLASS::parsePairs(cModule* module,cSub* sub){
443 | char sep;
444 | while(true){
445 | ws(true);
446 | if(';'==*ptr){
447 | ptr++;
448 | //fprintf(stderr,"ending parsing of inst %s in module %s\n",sub->name,module->name);
449 | break;
450 | }
451 | // cDatum *val;
452 | //-------------------------------------------------------------------------
453 | // parse a name:value pair. Note: the entire cfg string is a single pair,
454 | // and is parsed out in cDyn during expansion. The value may span multiple
455 | // lines, rendering pname invalid ...
456 | //fprintf(stderr,"PARSING PAIR {%s}\n",ptr);
457 | char*pname;
458 | int pnamelen;
459 | pnamelen=cnt();
460 | pname = (char*)malloc(pnamelen+1);
461 | strncpy(pname,ptr,pnamelen);
462 | pname[pnamelen]=0;
463 | // First of all, our parameter name must match the type's paramname. Note:
464 | // the type's index is not important - our order may be different.
465 | //if module declares this parameter name, we are good.
466 | int i = sub->type->paramnames->find(pname,pnamelen);
467 | if(-1==i){
468 | errorIn("parsePairs()");
469 | fprintf(stderr,"Argument named '%.*s' is not a part of the parameter list of module '%s'\n",
470 | pnamelen,pname,sub->type->name);
471 | error(1);
472 | }
473 | ptr+=pnamelen;
474 | requireSeparator("parsePairs()",":",&sep);
475 | // To facilitate cfg merging, we should see if the name has occurred and
476 | // if it has, reuse the index.
477 | //fprintf(stderr,"ParsePairs - value to be parsed from{%s}\n", ptr);
478 | // fprintf(stderr,"ParsePairs - value parsed is{%s}\n", val->valStr);
479 | int q = sub->pparams->find(pname,pnamelen);
480 | if(-1==q) {
481 | // first time parameter is created
482 | cDatum* val = parseParamData(module,"cfg: "); //as unrealized string...
483 | q=sub->pparams->add(pname,pnamelen,val);
484 | //fprintf(stderr,"in sub %s, added new parameter %.*s, [%s]\n",sub->name,
485 | // pnamelen,pname,val->valStr);
486 | } else {
487 | // an existing parameter must be merged
488 | cDatum* val = parseParamData(module,0);
489 | cDatum* oldparm = sub->pparams->data[q];
490 | //fprintf(stderr,"Expanding old parameter [%s]\n", oldparm->valStr);
491 | //fprintf(stderr,"Will append [%s]\n", val->valStr);
492 | int newlen =strlen(oldparm->valStr) + strlen(val->valStr) +1;
493 | oldparm->valStr = (char*)realloc(oldparm->valStr,newlen);
494 | strcat(oldparm->valStr,val->valStr);
495 | delete val;
496 | }
497 | free(pname);
498 | // TODO: fix this later. for parameters like xy(1,2 ), the space bounces
499 | // us out, and the ) is looming ahead...
500 | ws(true);
501 | if(')'==*ptr) ptr++;// for .. )
502 | //fprintf(stderr,"ADDING PARAMETER %s %d %d\n",sub->pparams->name[i],i,q);
503 | }
504 | //-----------------------------------------------------------------
505 | // Now walk through our sub's type's parameter names to make sure
506 | // all were declared here in the sub. This only applies to modules
507 | // insts are allowed to carry cfg parameters that are just not used.
508 | if(sub->type->psubs){
509 | //fprintf(stderr,"type is %s\n",sub->type->name);
510 | //sub->type->paramnames->dump(stderr,"PARAMNAMES");
511 | int tsize = sub->type->paramnames->size;
512 | int i;
513 | for(i=0;itype->paramnames->name[i]; // pull a parameter name
515 | int idx=sub->pparams->find(pname); //find by name in subs
516 | if(-1==idx){
517 | // Type declares a parameter, but we did not fill it. Hopefully there
518 | // is a default value!
519 | if(sub->type->paramnames->data[i]){
520 | //Bingo! a default value. So create a parameter
521 | sub->pparams->addClone(sub->type->paramnames->name[i],sub->type->paramnames->data[i]);
522 | } else {
523 | errorIn("parsePairs()");
524 | fprintf(stderr,"Module '%s' declares parameter '%s' that is never set in inst '%s'. Check the ;\n",
525 | sub->type->name,
526 | pname,
527 | sub->name);
528 | error(1);
529 | }
530 | }
531 | }
532 | }
533 | sub->pparams->solidify();
534 | //fprintf(stderr,"After all pairs, the pparams is %d \n",sub->pparams->debugmax);
535 |
536 | }
537 | /******************************************************************************
538 | parseSub
539 |
540 | parse an instance declaration.
541 |
542 | ******************************************************************************/
543 | cSub* CLASS::parseSub(cModule* module,int len){
544 | // NAME
545 | //fprintf(stderr,"sub %.*s %d\n",len,ptr,len);
546 | validateName(__func__,len,module);
547 | cSub* sub = new cSub(ptr,len);
548 | module->psubs->add(ptr,len,cDatum::newSub(sub)); //add to the collection...
549 | ptr+=len;
550 | // TYPE
551 | ws(true);
552 | int size=cnt();
553 | cProto* proto = pDevice->findProto(ptr,size); //find prototype by name
554 | if(!proto) {
555 | errorIn("parseSub");
556 | // A common error mode is a word taken for the name and : for type.
557 | if((1==size)&&(':'==*ptr)) {
558 | fprintf(stderr,"Run-on parameter. The previous ; probably should not be there\n");
559 | } else {
560 | fprintf(stderr,"instance %s is of an invalid type '%.*s'\n",sub->name,size,ptr);
561 | }
562 | error(1);
563 | }
564 | sub->type=proto;
565 | sub->pins=proto->pins;
566 |
567 | ptr+=size;
568 | // LOCATION. This should be (x,y) or name
569 | //sub->setLocation(parseLocation());
570 | //Start with an empty, expandable parameter collection
571 | sub->pparams = new cCollection();
572 | /* pparams will have name:value pairs. A notable one is cfg:xxx
573 | because it contains a whole collection inside. */
574 |
575 | // any variable pairs
576 | parsePairs(module,sub);
577 | // fprintf(stderr,"------------------\n");
578 | //sub->pparams->dump(stderr,sub->name);
579 | // fprintf(stderr,"------------------\n");
580 | //DONE
581 | return sub;
582 | }
583 | /******************************************************************************
584 | parseMerge
585 | following an inst declaration,
586 | ******************************************************************************/
587 | void CLASS::parseMerge(cModule*module,cSub* inst){
588 | fprintf(stderr,"merging inst %s\n",inst->name);
589 | static const char* funcname="parseMerge";
590 | if(!inst){
591 | errorIn("parseMerge()");
592 | fprintf(stderr,"No module declared to merge configurations into\n");
593 | error(1);
594 | }
595 | //merge can extend inst's pins. Since inst started out with a reference
596 | //to type module's pins, let's make a copy. Now we will be appending and
597 | //never removing items, so we can reference individual pins in module.
598 | cCollection *pins = new cCollection();
599 | int i; for(i=0;ipins->size;i++){
600 | pins->name[i] = inst->pins->name[i]; //reference to type's pin's name
601 | pins->data[i] = inst->pins->data[i]; //reference to type's pin's data
602 | }
603 | pins->size=inst->pins->size;
604 | ws(true);int len=cnt();
605 | while(!tokAnything(";",len)){
606 | if(tokAnything("input",len)){
607 | optionalColon();
608 | parsePins(pins,0); //inputs
609 | }else if(tokAnything("output",len)){
610 | optionalColon();
611 | parsePins(pins,1); //outputs
612 | } else if(tokAnything("cfg",len)){
613 | requireSeparator(funcname,":");
614 | cDatum* mergeparm = parseParamData(module,NULL/*no prepend*/);
615 | //now rewrite the cfg by merging them
616 | int ioldcfg = inst->pparams->find("cfg");
617 | if(-1==ioldcfg){
618 | errorIn(funcname);
619 | fprintf(stderr,"Instance %s has no cfg parameter\n",inst->name);
620 | error(1);
621 | }
622 | cDatum* pOldCfg = inst->pparams->data[ioldcfg];
623 | //fprintf(stderr,"old cfg [%s]\n",pOldCfg->valStr);
624 | //the length is both strings. Since only one will start with cfg: -5.
625 | int newlen = strlen(mergeparm->valStr) + strlen(pOldCfg->valStr);
626 | char* newCfgStr = (char*)malloc(newlen+1);
627 | strcpy(newCfgStr,pOldCfg->valStr); //start with old string
628 | strcat(newCfgStr,mergeparm->valStr); //append new
629 | //fprintf(stderr,"merge parsed cfg[%s]\n",newCfgStr);
630 | // Now delete old data
631 | delete mergeparm;
632 | free(pOldCfg->valStr);
633 | //and replace it
634 | pOldCfg->valStr=newCfgStr;
635 | //fprintf(stderr,"merged inst %s\n",inst->name);
636 | //inst->pparams->dump(stderr,"XXX");
637 |
638 |
639 | }
640 | else {
641 | errorIn("parseMerge()");
642 | fprintf(stderr,"merge must contain only input:() output:() or ;\n");
643 | error(1);
644 | }
645 | ws(true );len=cnt();
646 | }
647 | //now replace our inst's pins with the new version. Do not delete old-
648 | //it was just a pointer to type's
649 | pins->solidify();
650 | inst->pins=pins;
651 | }
652 |
653 | /******************************************************************************
654 | parsemergeQuark - merge the quark with the module itself!
655 |
656 | ******************************************************************************/
657 | void CLASS::parseMergeQuark(cModule*module){
658 | ws(true);
659 | int size=cnt();
660 | //find the quark name
661 | cProto* proto = pDevice->findProto(ptr,size); //find prototype by name
662 | if(!proto){
663 | errorIn(__func__);
664 | fprintf(stderr,"Quark %.*s has not been defined\n",size,ptr);
665 | error(1);
666 | }
667 | ptr+=size;
668 | //TODO:merge parameter names, without duplication...
669 | //merge pins TODO: if dup, check direction and keep old one.
670 | int i; for(i=0;ipins->size;i++){
671 | module->pins->addClone(proto->pins->name[i],proto->pins->data[i]);
672 | }
673 | //merge instances TODO: must be a dup! just add params
674 | for(i=0;ipsubs->size;i++){
675 | cSub* oldsub = module->getSub(proto->psubs->name[i]);
676 | if(!oldsub){
677 | //reference the merging sub TODO: is this really OK?
678 | module->psubs->add(proto->psubs->name[i],
679 | strlen(proto->psubs->name[i]),
680 | proto->psubs->data[i]);
681 | } else {
682 | //it exists, so merge parameters
683 | int j;
684 | cSub* srcSub = proto->psubs->data[i]->valSub;
685 | for(j=0;jpparams->size;j++){
686 | //TODO: check parameters for duplication - not allowed.
687 | oldsub->pparams->add(srcSub->pparams->name[j],
688 | strlen(srcSub->pparams->name[j]),
689 | srcSub->pparams->data[j]);
690 | }
691 | }
692 | }
693 |
694 | fprintf(stderr,"merging quark type %s\n",proto->name);
695 | }
696 | /******************************************************************************
697 | parseModule
698 |
699 | ******************************************************************************/
700 | cModule* CLASS::parseModule(){
701 | static const char*funcname="parseModule()";
702 | // if(!ws(/*required*/false)) return 0; //done!
703 | ws(true);
704 | int size=cnt();
705 | cParseStream::validateName(__func__,size);
706 | //first check for duplications
707 | if(-1 != pDevice->idxFindProto(ptr,size)){
708 | errorIn(funcname);
709 | fprintf(stderr,"Module '%.*s' already exists\n",size,ptr);
710 | error(1);
711 | }
712 | cModule* module = new cModule(ptr,size); //it will check for dups
713 | ptr+=size;
714 | //---------------------factor---
715 | // parameter names
716 | parseParamNames(module);
717 | //Now inputs and outputs
718 | ws(true); size=cnt();
719 | while(!tokAnything("{",size)){
720 | if(tokAnything("input",size)){
721 | optionalColon();
722 | parsePins(module->pins,0); //inputs
723 | }else if(tokAnything("output",size)){
724 | optionalColon();
725 | parsePins(module->pins,1); //outputs
726 | }
727 | else {
728 | errorIn("parseModule()");
729 | fprintf(stderr,"module header must contain only input:() output:() or ;\n");
730 | error(1);
731 | }
732 | ws(true );size=cnt();
733 | }
734 | // now parse insts and wiring...
735 | cMultiWireBuilder* xwire = new cMultiWireBuilder(); //***
736 | //---------------------factor---
737 | //----------------------------------------------------------------
738 |
739 | int idxInst=-1; //keep track of most recent instance index for 'his'
740 | cSub* pinst=0;
741 | ws(true);size=cnt(" \n\r\t"); //10.02.2012 - names can be anything, require space
742 | while(!tokAnything("}",size)){
743 | if(tokAnything("wire",size)){
744 | //if(tokWire(size)){
745 | parseWire(module,idxInst,pinst,xwire);
746 | } else if(tokAnything("merge",size)){
747 | parseMerge(module,pinst);
748 | } else {
749 | if(tokAnything("quark",size)){
750 | //merge quark into the module definition!
751 | parseMergeQuark(module);
752 |
753 | } else {
754 | pinst=parseSub(module,size);
755 | idxInst++;
756 | }
757 | }
758 | ws(true );size=cnt(" \n\r\t");
759 |
760 | }
761 | module->pins->solidify();
762 | // char*p=(char*)module->pwires->buf;
763 | //q(module->pwires->buf);
764 | // module->pwires->dump(stderr);
765 | //module->pwires->dump(stderr);
766 | //printf("ptr[%s]\n",ptr);
767 | module->psubs->solidify();
768 | // module->pwires->solidify();
769 | module->xwire = xwire->solidify();
770 | delete xwire;
771 |
772 |
773 | //q(module->pwires->buf);
774 | // module->pwires->dump(stderr);
775 |
776 | // module->dump(stderr);
777 | //fprintf(stderr,"DONE module %s\n",module->name);
778 | topModule=module;
779 | return module;
780 | }
781 | /******************************************************************************
782 | parseQuark
783 |
784 | ******************************************************************************/
785 | bool CLASS::parseQuark(){
786 | ws(true);
787 | int size=cnt();
788 | cParseStream::validateName(__func__,size);
789 | //TODO: check for duplicates
790 | cQuark* quark = new cQuark(ptr,size);
791 | ptr+=size;
792 | //---------------------factor---
793 |
794 | //Now inputs and outputs
795 | ws(true); size=cnt();
796 | while(!tokAnything("{",size)){
797 | if(tokAnything("input",size)){
798 | optionalColon();
799 | parsePins(quark->pins,0); //inputs
800 | }else if(tokAnything("output",size)){
801 | optionalColon();
802 | parsePins(quark->pins,1); //outputs
803 | }
804 | else {
805 | errorIn("parseQuark()");
806 | fprintf(stderr,"Quark header must contain only input:() output:() or ;\n");
807 | error(1);
808 | }
809 | ws(true );size=cnt();
810 | }
811 | //Let's use paramnames as actual merge parameters here...
812 | // pparamnames = new cCollection();
813 | //---------------------factor---
814 | quark->pins->solidify();
815 | // psubs are not used and are nil.
816 | // wires are not used and are nil.
817 | return 1;
818 | }
819 | /******************************************************************************
820 | In between modules, #includes may occur.
821 | Sept 19 - added quarks
822 |
823 | ******************************************************************************/
824 | void CLASS::parseModules(){
825 | bool iterate=true;
826 | int len;
827 | do{
828 | //fprintf(stderr,"OK [%s]\n",ptr);
829 | /* In between modules it's possible that we run off the EOF. Normally this
830 | means that we are done with an included file, or everything. */
831 | if(!ws(false))/*EOF*/ return;
832 | len=cnt();
833 | /* In between modules, #INCLUDE is allowed */
834 | if(handleInclude(len)) continue;
835 | if(pDevice){
836 | /* If device is parsed, a quark or module is expected. */
837 | // if(tokAnything("quark",5))
838 | // iterate = parseQuark();
839 | // else
840 | iterate=parseModule();
841 | } else {
842 | errorIn("parseModules()");
843 | fprintf(stderr,"expecting an include of an .xdlrc file\n");
844 | error(1);
845 | }
846 | } while(iterate);
847 |
848 | }
849 | /******************************************************************************
850 | parse
851 | called by include as well...
852 | ******************************************************************************/
853 | void CLASS::parse(FILE*f){
854 | setFile(f);
855 | parseModules();
856 | //Make sure we did anything
857 | if(!topModule){
858 | errorIn("parse");
859 | fprintf(stderr,"No modules defined\n");
860 | error(-1);
861 | }
862 | }
863 |
864 | void CLASS::validateName(const char* func,int len,cModule* module){
865 | cParseStream::validateName(func,len);
866 | //if another sub exists with this name, error...
867 | int i = module->psubs->find(ptr,len);
868 | if(-1 != i) {
869 | errorIn("validateName()");
870 | fprintf(stderr,"Module '%s' already has an inst named '%.*s'",
871 | module->name,len,ptr);
872 | error(1);
873 | }
874 | }
--------------------------------------------------------------------------------
/cParse.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #pragma once
20 | #include "cParseStream.h"
21 | class cModule;
22 | class cMultiWireBuilder;
23 | class cSub;
24 | /* While parsing wiring, we generate endpoints. */
25 | struct sWireEndpoint {
26 | U16 inst; //index of the instance
27 | U8 pindex; //index of the pin
28 | U8 busid1; //start bus index
29 | U8 busid2; //end bus index
30 | };
31 |
32 |
33 | class cParse: public cParseStream {
34 | public:
35 | cParse();
36 | ~cParse();
37 | void parse(FILE*f);
38 | //data
39 | cModule* topModule; //keep track of the last module - it is top.
40 |
41 | protected:
42 | void parseModules();
43 | bool handleInclude(int len);
44 | void validateName(const char* func,int len,cModule* module);
45 |
46 |
47 |
48 | void parsePins(cCollection*pins,int dir);
49 | void parseParamNames(cModule* module);
50 | cDatum* parseParamData(cModule*module,const char* prepend);
51 | sWireEndpoint parseWireEndpoint(cModule* module,int idxInst,cSub*pinst);
52 | void parseWire(cModule* module,int idxInst,cSub*pinst,cMultiWireBuilder* xwire);
53 | void parseMergeQuark(cModule* module);
54 |
55 | cSub* parseSub(cModule* module,int len);
56 | void parseMerge(cModule* module,cSub* pinst);
57 | void parsePairs(cModule* module,cSub* sub);
58 | cModule* parseModule();
59 | bool parseQuark();
60 | //data
61 | };
--------------------------------------------------------------------------------
/cParseStream.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #include "global.h"
20 | #include "cParseStream.h"
21 | #define CLASS cParseStream
22 | #include
23 | CLASS::CLASS(){
24 | file=0;
25 | buf=(char*)malloc(1024);
26 | ptr=buf;
27 | *ptr=0; //will force a reload.
28 | lineno=0;
29 | }
30 | CLASS::~CLASS(){
31 | if(file)
32 | fclose(file);
33 | free(buf);
34 | }
35 | void CLASS::setFile(FILE*f){
36 | file=f;
37 | }
38 |
39 | /******************************************************************************
40 | parseQuotedString.
41 | Enter with ptr at "; return with ptr past ".
42 |
43 | ******************************************************************************/
44 | cDatum* CLASS::parseQuotedString(){
45 | ptr++; //ptr is past "
46 | int len=0;
47 | char c;
48 | char* buf=(char*)malloc(0x10000);
49 | char*dest=buf;
50 | // Now count the characters until "
51 | while('"' != (c=*ptr++)){
52 | len++;
53 | *dest++=c;
54 | switch(c){
55 | case 0x0A:
56 | case 0x0D: reload(); break;
57 | }
58 | }
59 | *dest++=0;len++;
60 | cDatum* ret = cDatum::newStr(buf,len);
61 | free(buf);
62 | return ret;
63 | }
64 | cDatum* CLASS::parseBracedString(){
65 | ptr++; //ptr is past {
66 | int len=0;
67 | char c;
68 | char* buf=(char*)malloc(0x10000);
69 | char*dest=buf;
70 | // Now count the characters until "
71 | while('}' != (c=*ptr++)){
72 | len++;
73 | *dest++=c;
74 | switch(c){
75 | case 0x0A:
76 | case 0x0D: reload(); break;
77 | }
78 | }
79 | *dest++=0;len++;
80 | cDatum* ret = cDatum::newStr(buf,len);
81 | free(buf);
82 | return ret;
83 | }
84 |
85 | /**************************************************************************
86 | SUBROUTINES
87 | &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
88 |
89 | bool CLASS::reload(){
90 | //fprintf(stderr,"(reloaded)");
91 | ptr=buf;
92 | *ptr=0;
93 | lineno++;
94 | char*ret=fgets(buf,1024,file);
95 | return 0!=ret;
96 | }
97 | /******************************************************************************
98 | wsp is whitespace primitive. It does not handle comments
99 | called by include as well...
100 | ******************************************************************************/
101 | bool CLASS::wsp(){
102 | while(true){
103 | char c=*ptr;
104 | if(!c){
105 | if(!reload()) return false;
106 | c=*ptr;
107 | }
108 | if(!isspace(c)) return true;
109 | ptr++;
110 | }
111 | }
112 | /******************************************************************************
113 | ******************************************************************************/
114 | bool CLASS::enclosedComment(){
115 | //for error reporting, keep track of opening position
116 | int errline=lineno;
117 | char* errsrc = strdup(buf);
118 | char* errptr=ptr;
119 | while(true){
120 | char* p = strstr(ptr,"*/");
121 | if(p) {
122 | ptr= p+2;
123 | return true;
124 | }
125 | if(!reload()){
126 | //even though the error occurs later, the source is here:
127 | memcpy(buf,errsrc,sizeof(buf));
128 | ptr=errptr;
129 | lineno=errline;
130 | errorIn("enclosedComment()");
131 | fprintf(stderr,"where is the closing */\n");
132 | error(1);
133 | }
134 | }
135 | }
136 |
137 | /******************************************************************************
138 | wsComment
139 | process a comment, return isComment
140 | ******************************************************************************/
141 |
142 | bool CLASS::wsComment(){
143 | if(0==strncmp(ptr,"/*",2)) {
144 | enclosedComment(); //it updates ptr to past */
145 | return true;
146 | }
147 | if(0==strncmp(ptr,"//",2)) {
148 | /* handle // comment to eol by reloading */
149 | if(!reload()){
150 | errorIn("wsComment()");
151 | fprintf(stderr,"Out of source in // comment");
152 | error(1);
153 | }
154 | //reload succeeded.
155 | return true;
156 | }
157 | // not a comment.
158 | return false;
159 | }
160 | /******************************************************************************
161 | ws and comments...
162 | return true if source ok, false if ran out.
163 |
164 | Note: calling ws(FALSE) and checking for false is a way to see if we ran out
165 | of soruce in an include file, for instance.
166 | ******************************************************************************/
167 | bool CLASS::ws(bool required){
168 | do{
169 | if(!wsp()) {
170 | if(required){
171 | errorIn("ws()");
172 | fprintf(stderr,"Out of source");
173 | error(1);
174 | }else
175 | return false; //end at ws
176 | }
177 |
178 | // After skipping space, check for comment. If comment, skip and
179 | // repeat.
180 | } while(wsComment());
181 | return true;
182 | }
183 |
184 | int CLASS::cnt(){
185 | int size=0;
186 | char* p = ptr;
187 | char c=*p;
188 | if(!c) return 0;
189 | switch(c){
190 | case 0:
191 | case '(':
192 | case ')':
193 | case ':':
194 | case ';':
195 | case ',':
196 | case '[':
197 | case ']':
198 | return 1;
199 | }
200 |
201 | while(true){
202 | char c=*p;
203 | if(isspace(c)) break;
204 | if(!c) break;
205 | if('('==c) break;
206 | if(')'==c) break;
207 | if(':'==c) break;
208 | if(';'==c) break;
209 | if(','==c) break;
210 | if('/'==c) break;
211 | if('\''==c) break;
212 | if('['==c) break;
213 | if(']'==c) break;
214 | size++;
215 | p++;
216 | }
217 | return size;
218 |
219 | }
220 | int CLASS::cnt(const char* seps){
221 | int ret=0;
222 | char*p = ptr;
223 | char c;
224 | while((c=*p++)){
225 | if(strchr(seps,c))
226 | return ret;
227 | ret++;
228 | }
229 | return ret;
230 |
231 | }
232 |
233 | void CLASS::showtok(){
234 | int size=cnt();
235 | char word[64];
236 | memcpy(word,ptr,size);
237 | word[size]=0;
238 | fprintf(stderr,"<%s>",word);
239 | }
240 |
241 | // require a word to occur at parseptr
242 | int CLASS::requireWord(const char* str,int len){
243 | ws(true);
244 | int i=cnt();
245 | if(!((i==len) && (0==strncmp(ptr,str,i)))){
246 | errorIn("requireWord()");
247 | fprintf(stderr,"'%.*s' is required\n",len,str);
248 | error(1);
249 | }
250 | ptr+=i;
251 | ws(true);
252 | return cnt();
253 | }
254 | /******************************************************************************
255 | returns cnt()
256 | ******************************************************************************/
257 | int CLASS::requireSeparator (const char*caller,const char* separators,char*actual){
258 | ws(true); //preceding whitespace
259 | //If the next cha acter is a separator in the list...
260 | char c = *ptr;
261 | if((strchr(separators,c))){
262 | ptr++;
263 | ws(true);
264 | if(actual)
265 | *actual=c;
266 | return cnt();
267 | }
268 | errorIn(caller);
269 | fprintf(stderr,"Expected a separator (one of '%s'), not '%c'\n",
270 | separators,c);
271 | error(1);
272 | return 0; //just to stop compiler barksf
273 | }
274 | /******************************************************************************
275 | returns cnt()
276 | ******************************************************************************/
277 | int CLASS::optionalColon(){
278 | ws(true); //preceding whitespace
279 | if(':'==*ptr){
280 | ptr++;ws(true);
281 | }
282 | return cnt();
283 | }
284 | /******************************************************************************
285 |
286 | ******************************************************************************/
287 | int CLASS::notEnd(){
288 | ws(true);
289 | int size=cnt();
290 | if((3==size)&&(0==strncasecmp(ptr,"end",3))){
291 | ptr+=3;
292 | return 0;
293 | }
294 | else
295 | return size;
296 | }
297 |
298 | /******************************************************************************
299 |
300 | ******************************************************************************/
301 | //len is from cnt(), nothing to do with str!
302 | bool CLASS::tokAnything(const char* str,int len){
303 | ws(true);
304 | int sl = strlen(str);
305 | if((len==sl)&&(0==strncasecmp(ptr,str,sl))){
306 | ptr+=sl;
307 | ws(false); //EOF here is not an error.
308 | return true;
309 | }
310 | return false;
311 | }
312 | /******************************************************************************
313 | validateName
314 |
315 | ******************************************************************************/
316 | void CLASS::validateName(const char* func,int len){
317 | // first character must be alpha!
318 | char*p=ptr;
319 | char c=*p++;
320 | if(!isalpha(c)) {
321 | errorIn("cParseStream::validateName()");
322 | fprintf(stderr,"%s Identifier must begin with an alpha character, not %c\n",
323 | func,c);
324 | error(1);
325 | }
326 | /* int i;
327 | for(i=1;i9) {
377 | if(c<11) //take care of : to @
378 | break;
379 | c-=7;
380 | if(c<0) {
381 | break;
382 | }
383 | }
384 | if(c>radix) {
385 | break;
386 | // ptr--;
387 | // errorIn("parseLiteral()");
388 | // fprintf(stderr,"invalid digit\n");
389 | // error(1);
390 | }
391 | accum = (accum*radix)+c;
392 | }
393 | ptr--;
394 | if(neg) accum = 0-accum;
395 | return accum;
396 | }
397 |
398 | /******************************************************************************
399 |
400 | ******************************************************************************/
401 | void CLASS::errorIn(const char* from){
402 | fprintf(stderr,"-------------------------------------------------------\n");
403 | fprintf(stderr,"Error in function cParse::%s\n",from);
404 | fprintf(stderr,"Error occured in line %d:\n",lineno);
405 |
406 | }
407 | void CLASS::warningIn(const char* from){
408 | fprintf(stderr,"-------------------------------------------------------\n");
409 | fprintf(stderr,"Warning in function cParse::%s\n",from);
410 | fprintf(stderr,"Warning occured in line %d:\n",lineno);
411 |
412 | }
413 | void CLASS::error(int xerrno){
414 | int spaces = ptr-buf;
415 | fprintf(stderr,"\n%s",buf); //print line, complete with cr
416 | while(spaces--)
417 | fputc(' ',stderr);
418 | fputc('^',stderr);
419 | fputs("\n",stderr);
420 | fprintf(stderr,"----------------------------------------------------------------------\n");
421 | throw(xerrno);
422 | }
423 | void CLASS::warning(int xerrno){
424 | int spaces = ptr-buf;
425 | fprintf(stderr,"\n%s",buf); //print line, complete with cr
426 | while(spaces--)
427 | fputc(' ',stderr);
428 | fputc('^',stderr);
429 | fputs("\n",stderr);
430 | fprintf(stderr,"----------------------------------------------------------------------\n");
431 | }
432 |
--------------------------------------------------------------------------------
/cParseStream.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | class cParseStream {
20 | public:
21 | cParseStream();
22 | ~cParseStream();
23 |
24 | protected:
25 | bool reload();
26 | //ws-related
27 | bool wsp();
28 | bool ws(bool required);
29 | bool enclosedComment();
30 | bool wsComment();
31 | void setFile(FILE*f);
32 | // bool parseComment();
33 | int cnt();
34 | int cnt(const char* seps);
35 | //these ws,cnt, parse, and return cnt()
36 | int requireWord(const char* str,int len);
37 | int requireSeparator(const char* caller,const char* seps,char*actual=0);
38 | int optionalColon();
39 |
40 | int notEnd();
41 | //these check here for a token. If match, advance.
42 | //bool tokWire(int len);
43 | // bool tokHis(int len);
44 | // bool tokVcc(int len);
45 | bool tokTo(int len);
46 | bool tokAnything(const char* str,int parsecnt);
47 |
48 |
49 | //cDatum* parseLocation();
50 | cDatum* parseQuotedString();
51 | cDatum* parseBracedString();
52 | int banglen(char*str); //length of !paramname!
53 | S32 parseLiteral(); //TODO: duplicated in dyn?
54 | void showtok(); //debugigng
55 | void validateName(const char*func,int len);
56 |
57 | void errorIn(const char* from);
58 | void warningIn(const char* from);
59 | void error(int xerrno);
60 | void warning(int xerrno);
61 |
62 | //and the data
63 | FILE* file;
64 | int lineno;
65 | char* ptr;
66 | char* buf;
67 | };
--------------------------------------------------------------------------------
/cPrim.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #include "global.h"
20 | #include "cPrim.h"
21 | #include "cDevice.h"
22 | #include "cDyn.h"
23 | #define CLASS cPrim
24 | class cModule;
25 | extern cDevice* pDevice;
26 | CLASS::CLASS(char*nam,int len)
27 | : cProto(nam,len)
28 | {
29 | //fprintf(stderr,"cPrim:cPrim %d %s\n",len,nam);
30 | //cfg =g_hash_table_new(g_str_hash,g_str_equal);
31 | pDevice->addProto(name,len,this);
32 | cfgval=new cCollection();
33 | }
34 | CLASS::~CLASS()
35 | {
36 | //g_hash_table_destroy(cfg);
37 | }
38 |
39 | void CLASS::verilog(FILE*f){
40 | fprintf(f,"PRIMITIVE %s NOT YET IMPLEMENTED\n",name);
41 |
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/cPrim.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | /******************************************************************************
20 | Primitive Definition
21 | PrimDef is the low-level building block of the FPGA. It exports names of pins
22 | ******************************************************************************/
23 | #include "cProto.h"
24 | class cModule;
25 | class cPrim : public cProto{
26 | public:
27 | cPrim(char*name,int len);
28 | ~cPrim();
29 | virtual void verilog(FILE*f);
30 |
31 | cCollection* cfgval; //for validation, cfg names and possible values
32 | private:
33 | };
34 |
--------------------------------------------------------------------------------
/cProto.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #include "global.h"
20 | #define CLASS cProto
21 | #include "stdio.h"
22 | #include "cModule.h"
23 | CLASS::CLASS(char* nam,int size)
24 | {
25 | name=(char*)malloc(size+1);
26 | strncpy(name,nam,size);
27 | name[size]=0;
28 | paramnames = new cCollection();
29 | pins = new cCollection();
30 | #ifdef DEBUG
31 | paramnames->setdebugname(nam,size);
32 | #endif
33 | psubs=0;
34 | // pwires=0;
35 | xwire=0;
36 | converted=false; //for the verilog converter
37 | // pins=new cCollection();
38 | }
39 | CLASS::~CLASS(){
40 | free(name);
41 | }
42 |
43 | void CLASS::dump(FILE*f){
44 | fprintf(f,"\nModule/prim %s:\n",name);
45 |
46 | //since pins are typed (see cCollection/cDatum)
47 | pins->dump(f,"pins:\n");
48 | paramnames->dump(f,"paramnames:\n");
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/cProto.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #pragma once
20 | class cDyn;
21 | class cModule;
22 | //class cWires;
23 | class cMultiWire;
24 | class cProto{
25 | public:
26 | cProto(char*name,int size);
27 | ~cProto();
28 | void dump(FILE*f);
29 | virtual void verilog(FILE*f)=0;
30 | // data
31 | bool converted; //verilog sucker marks modules already sucked in as used.
32 | char* name; //name of this module/primitive...
33 | cCollection vars;
34 | //primitives and modules both have a list of valid parameters
35 | cCollection *paramnames;
36 | cCollection *psubs; //names-> submodules...Not relevant to prim.
37 | // cWires* pwires;
38 | cMultiWire* xwire;
39 | cCollection *pins; //pin name->buswidth mapping
40 | private:
41 |
42 | };
43 |
--------------------------------------------------------------------------------
/cQuark.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #include "global.h"
20 | #include "cQuark.h"
21 | #define CLASS cQuark
22 |
23 | CLASS::CLASS(char* name,int size)
24 | : cProto(name,size)
25 | {
26 | //printf("MODULE %s %d\n",name,size);
27 | // pDevice->addProto(name,size,this); //will check for dups
28 | }
29 | CLASS::~CLASS(){
30 | // g_hash_table_destroy(subs);
31 | }
32 |
33 |
34 |
35 | /******************************************************************************
36 | * Verilog
37 | * Output this module as a verilog module.
38 | *******************************************************************************/
39 | void CLASS::verilog(FILE*fout){
40 | fputs("QUARK verilog not implemented\n",fout);
41 | }
--------------------------------------------------------------------------------
/cQuark.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | /******************************************************************************
20 | A quark is a special part of a module. Quarks correspond to Verilog primitive
21 | constructs that may be instantiated in Verilog, and is used in conversion to
22 | verilog. Modules using quarks instead of instantiating primitives can be
23 | converted to verilog.
24 | A quark is instantiated inside a module, and merges its own cfg data and pins
25 | with those of the module.
26 | ******************************************************************************/
27 | #pragma once
28 | #include "cProto.h"
29 | class cQuark: public cProto{
30 | public:
31 | cQuark(char*name,int size);
32 | ~cQuark();
33 | virtual void verilog(FILE*f);
34 | private:
35 | };
36 |
--------------------------------------------------------------------------------
/cSub.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #include "global.h"
20 | #include "cSub.h"
21 | #include "cProto.h"
22 | #define CLASS cSub
23 | /******************************************************************************
24 |
25 | ******************************************************************************/
26 | CLASS::CLASS(char*nam,int len){
27 | name=(char*)malloc(len+1);
28 | strncpy(name,nam,len);
29 | name[len]=0;
30 | //cfg = g_hash_table_new(g_str_hash,g_str_equal);
31 | }
32 | CLASS::~CLASS(){
33 | free(name);
34 | //g_hash_table_destroy(cfg);
35 | //g_hash_table_destroy(var);
36 | }
37 | /******************************************************************************
38 |
39 | ******************************************************************************/
40 | void CLASS::init(cProto* theType){
41 | type=theType;
42 | //Now initialize our pins to be proto's TODO: really?
43 | pins=type->pins;
44 | }
45 | /******************************************************************************
46 |
47 | ******************************************************************************/
48 | void CLASS::setLocation(cDatum* l){
49 | pparams->add("loc",3,l);
50 | }
51 |
52 | cDatum* CLASS::getLocation(){
53 | if(pparams){
54 | int iloc = pparams->find("loc",3);
55 | if(-1==iloc) return 0; //0 means no set location
56 | return pparams->data[iloc];
57 | } else {
58 | return 0; //no parameters at all
59 | }
60 | }
61 | /******************************************************************************
62 |
63 | ******************************************************************************/
64 | void CLASS::dump(FILE*f){
65 | fprintf(f,"sub '%s' ",name);
66 | if(pparams==0)
67 | fprintf(stderr,"NULL params\n");
68 | else
69 | pparams->dump(f,"params:\n");
70 | }
71 |
--------------------------------------------------------------------------------
/cSub.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | /******************************************************************************
20 | cSub
21 |
22 | An embedded instance description. These are used as data for
23 | subs collection.
24 | Describes how a module invokes another module.
25 | pins start out same as the type module, but can be extended with 'merge'
26 | ******************************************************************************/
27 | class cProto;
28 | class cSub {
29 | public:
30 | cSub(char*nam,int len);
31 | ~cSub();
32 | void setLocation(cDatum* loc);
33 | cDatum* getLocation();
34 | void dump(FILE*f);
35 | void init(cProto* type);
36 | // DATA
37 | char*name;
38 | cCollection* pparams;
39 | cProto* type;
40 | cCollection* pins;
41 | };
42 |
--------------------------------------------------------------------------------
/fpgasm.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #include "global.h"
20 | #include "cDevice.h"
21 | #include "cModule.h"
22 | #include "cParse.h"
23 | #include "cDyn.h"
24 | #include "cSub.h"
25 | #include "stdlib.h"
26 |
27 | enum outputType {
28 | verilog, xdl
29 | };
30 | outputType otype; //type of output- verilog or xdl
31 | cDevice *pDevice;
32 | #include "malloc.h"
33 | int main(int argc,char** argv){
34 |
35 | // ;GMainLoop* gmloop;
36 | // gmloop = g_main_loop_new (NULL, TRUE);
37 | //
38 | // g_main_loop_run(gmloop);
39 | fprintf(stderr,"\nFPGAsm 0.11 (c) 2012 Victor Yurkovsky \n");
40 | if(argc!=3){
41 | printf("Usage: fpgasm initialize();
46 | // pDevice->parse_xdlrc("xc3s200ft256.xdlrc");
47 | // pDevice->listProtos();
48 | FILE* fin = (fopen(argv[1],"r"));
49 | if(!fin){
50 | fprintf(stderr,"Error. Unable to open %s for input\n",argv[1]);
51 | exit(1);
52 | }
53 | FILE* fout = stdout;
54 | fout = fopen(argv[2],"w");
55 | if(!fout){
56 | fprintf(stderr,"Error. Unable to open %s for output\n",argv[2]);
57 | exit(1);
58 | }
59 | char* dot = strrchr(argv[2],'.');
60 | if(!dot){
61 | fprintf(stderr,"Error. Output file must have a .v or .xdl suffix\n");
62 | exit(1);
63 | }
64 | if(0==strcmp(dot,".xdl")) otype=xdl;
65 | else if(0==strcmp(dot,".v")) otype=verilog;
66 | else {
67 | fprintf(stderr,"Error. Output file must have a .v or .xdl suffix\n");
68 | exit(1);
69 | }
70 | // DEBUGGING _ REMOVE ME!
71 | //fout=stdout;
72 | pDevice = NULL;
73 | cParse* parser = new cParse();
74 | try {
75 | parser->parse(fin);
76 | //fprintf(stderr,"parse() completed\n");
77 | cModule* root = parser->topModule;
78 | //(cModule*)pDevice->findProto((char*)"top",3);
79 | /* Determine the requested output type */
80 | //fprintf(stderr,argv[2]);
81 | switch(otype){
82 | case xdl: {
83 | //dynamic tree... First create a fake sub for the root
84 |
85 | cSub* subroot = new cSub(root->name,strlen(root->name));
86 | subroot->type=root;
87 | subroot->pparams=0;
88 | subroot->pins=root->pins;
89 | cDyn*dynroot=new cDyn(subroot,0);
90 | dynroot->fout = fout;
91 | dynroot->expand();
92 | dynroot->place();
93 | // now, if the output file is .xdl, output xdl.
94 | dynroot->xdlHeader();
95 | dynroot->xdlDefs();
96 | dynroot->xdlWires1();
97 | fprintf(stderr,"Success! %s generated\n",argv[2]);
98 | }break;
99 | case verilog:
100 | root->verilog(fout);
101 | break;
102 | }
103 | }
104 | catch(int i){
105 | // fprintf(stderr,"CAUGHT %d\n",i);
106 | exit(i);
107 | }
108 |
109 | return 0;
110 | }
111 |
112 | void q(void*ptr){
113 | U8*p=(U8*)ptr;
114 | fprintf(stderr,"%p ",p);
115 | fprintf(stderr,"%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
116 | *p,*(p+1),*(p+2),*(p+3),*(p+4),*(p+5),*(p+6),*(p+7),*(p+8),*(p+9),*(p+10),*(p+11),*(p+12),*(p+13),*(p+14),*(p+15));
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/global.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 | #include "global.h"
20 |
--------------------------------------------------------------------------------
/global.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | Copyright 2012 Victor Yurkovsky
3 |
4 | This file is part of FPGAsm
5 |
6 | FPGAsm 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 3 of the License, or
9 | (at your option) any later version.
10 |
11 | FPGAsm 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.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with FPGAsm. If not, see .
18 | ******************************************************************************/
19 |
20 | //#include
21 | //#include
22 | #include
23 | #include
24 | #include
25 | #include
26 | typedef unsigned char U8;
27 | typedef unsigned short U16;
28 | typedef unsigned int U32;
29 | typedef unsigned long U64;
30 | typedef long S64;
31 | typedef int S32;
32 |
33 | #define DEBUG
34 | #include "cDatum.h"
35 | #include "cCollection.h"
36 |
37 | void q(void*p);
--------------------------------------------------------------------------------