├── .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); --------------------------------------------------------------------------------