[
  {
    "path": ".gitignore",
    "content": "legal.txt\n.svn\nxilinx\nobj_dir\nobj-pc\nobj-zip\n*.o\n*.a\n*.vcd\n.swp\n.*.swp\n.*.swo\nsvn-commit*\n*_tb\n*_tb.dbl\n*dbg.txt\nautofpga.dbg\n*dump.txt\n*debug.txt\ntags\ncpudefs.h\n20*-autofpga.tjz\ncore\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    {one line to give the program's name and a brief idea of what it does.}\n    Copyright (C) {year}  {name of author}\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    {project}  Copyright (C) {year}  {fullname}\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "Makefile",
    "content": "################################################################################\n##\n## Filename:\tMakefile\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tA master project makefile.  It tries to build all targets\n##\t\twithin the project, mostly by directing subdirectory makes.\n##\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n.PHONY: all\nall:\tsw\nYYMMDD:=`date +%Y%m%d`\n\n.PHONY: archive\n## {{{\narchive:\n\ttar --transform s,^,$(YYMMDD)-video/, -chjf $(YYMMDD)-autofpga.tjz sw/ auto-data/ demo-out/ doc/\n## }}}\n\n.PHONY: autofpga\nautofpga: sw\n\n.PHONY: sw\n## {{{\nsw:\n\t$(MAKE) --no-print-directory --directory=sw\n## }}}\n\n.PHONY: clean\n## {{{\nclean:\n\t$(MAKE) --no-print-directory --directory=sw clean\n## }}}\n"
  },
  {
    "path": "README.md",
    "content": "# AutoFPGA - An FPGA Design Automation routine\n\nAfter now having built several FPGA designs, such as the\n[xulalx25soc](https://github.com/ZipCPU/xulalx25soc),\n[s6soc](https://github.com/ZipCPU/s6soc),\n[openarty](https://github.com/ZipCPU/openarty),\n[zbasic](https://github.com/ZipCPU/zbasic),\n[icozip](https://github.com/ZipCPU/icozip),\nand even a Basys-3 design of my own that hasn't been published, I started\nrecognizing that all of these designs have a lot in common.  In particular,\nthey all have a set of bus masters, such as the\n[UART-to-wishbone](https://github.com/ZipCPU/zbasic/blob/master/rtl/wbubus.v)\nbridge that I use, the [hexbus](https://github.com/ZipCPU/dbgbus) debugging\nbus that offers a simpler version of the same, or even the\n[zipcpu](https://github.com/ZipCPU/zipcpu).\nMany of these designs have also started to use (and reuse) many of the\nperipherals I've developed, such as\nthe generic [UART](https://github.com/ZipCPU/wbuart),\nthe [QSPI flash controller](https://github.com/ZipCPU/qspiflash),\nthe [SD-card controller](https://github.com/ZipCPU/sdspi),\nthe [block RAM controller](https://github.com/ZipCPU/openarty/blob/master/rtl/memdev.v),\nthe [RMII Ethernet Controller](https://github.com/ZipCPU/openarty/blob/master/rtl/enetpackets.v),\nthe [Real-Time Clock](https://github.com/ZipCPU/rtcclock), the [Real-Time\nDate](https://github.com/ZipCPU/rtcclock/blob/master/rtl/rtcdate.v), the\n[Organic LED controller](https://github.com/ZipCPU/openarty/blob/master/rtl/wboled.v),\nXilinx's [Internal Configuration Access\nPort](https://github.com/ZipCPU/wbicapetwo), the [wishbone\nscope](https://github.com/ZipCPU/wbscope), the [GPS controlled\nclock](https://github.com/ZipCPU/openarty/blob/master/rtl/gpsclock.v),\nor even the [PWM Audio Controller](https://github.com/ZipCPU/wbpwmaudio).\nAll of these peripherals have a very similar format when included within a\ntop level design, all of these require a certain amount of care and feeding\nas part of that top level design, but yet rebuilding that top level design over\nand over just to repeat this information becomes a pain.\n\nWhere things were really starting to get annoying is where the C++ information\nwas depending upon Verilog information.  A classic example of this is the\nbase address of any bus components.  However, if you add clock rate into\nthe mix, you can then also control things such as any default UART\nconfiguration, default clock stepping information (for the RTC clock),\nor even default video clock information--just by knowing the FPGA's clock rate\nwithin your C++ environment.\n\nSharing information between Verilog and C++ then became one of the primary\nreasons for creating AutoFPGA.  While peripheral address decoding is typically\ndone in some [main Verilog\nfile](https://github.com/ZipCPU/openarty/blob/master/rtl/main.v),\nother files depend upon what this peripheral decoding is.  These other files\ninclude the [host register definition\nfile](https://github.com/ZipCPU/openarty/blob/master/sw/host/regdefs.h) (used\nfor debugging access), the [register naming\nfile](https://github.com/ZipCPU/openarty/blob/master/sw/host/regdefs.cpp), the\n[software board definition\nfile](https://github.com/ZipCPU/openarty/blob/master/sw/zlib/board.h) used\nby newlib, the [linker\nscript](https://github.com/ZipCPU/openarty/blob/master/sw/board/board.ld) used\nby the compiler, and even the [LaTeX\nspecification](https://github.com/ZipCPU/openarty/blob/master/doc/src/spec.tex)\nfor the board.  Creating and updating all of these files by hand anytime I\ncreate a new board file can get tedious.  Further, every time a board is\nreconfigured, the constraints file, whether\n[XDC](https://github.com/ZipCPU/openarty/blob/master/arty.xdc) or\n[UCF](https://github.com/ZipCPU/xulalx25soc/blob/master/xula.ucf) file, needs\nto be updated to match the current constraints.\n\nSolving this multi-language coordination problem is the purpose of AutoFPGA.\n\nUnlike many of the other tools out there, such as Xilinx's board design flow,\nAutoFPGA is not built with the clueless beginner in mind, neither is it built\nto hide the details of what is going within the project it creates.  Instead,\nAutoFPGA is built with the sole purpose of alleviating any burden on the FPGA\ndesigner who otherwise has to create and maintain coherency between multiple\ndesign files.\n\nThat this program facilitates composing and building new designs from existing\ncomponents ... is just a bonus.\n\n# Goal\n\nThe goal of AutoFPGA is to be able to take a series of bus component\nconfiguration files and to compose a design consisting of the various bus\ncomponents, linked together in logic, having an appropriate bus interconnect\nand more.\n\nFrom a user's point of view, one would run AutoFPGA with a list of component\ndefinition files, given on the command line, and to thus be able to generate\n(or update?) the various design files discussed above:\n\n- [rtl/toplevel.v](demo-out/toplevel.v)\n- [rtl/main.v](demo-out/main.v)\n- [rtl/make.inc](demo-out/rtl.make.inc)\n- [rtl/iscachable.v](demo-out/iscachable.v) -- a function of bus address determining what addresses are cachable and which are not\n- [sw/host/regdefs.h](demo-out/regdefs.h)\n- [sw/host/regdefs.cpp](demo-out/regdefs.cpp)\n- [sw/zlib/board.h](demo-out/board.h)\n- [sw/zlib/board.ld](demo-out/board.ld)\n- [build.xdc](demo-out/build.xdc) (Created by modifying an existing XDC file.  LPF, PCF, and UCF files are also supported)\n- [sim/verilated/testb.h](demo-out/testb.h)\n- [sim/verilated/main_tb.h](demo-out/main_tb.cpp)\n- doc/src/(component name).tex (Not started yet)\n\nSpecifically, the parser must determine:\n\n- If any of the components used in the project need to be configured, and if\n  so, what the configuration parameters are and how they need to be set.  For\n  example, the UART baud rate and RTC and GPS clock steps both need to be set\n  based upon the actual clock speed of the master clock.  Placing [a\n  clock module](auto-data/clock.txt) within the design that sets up a clock and\n  declares its rate is the current method for accomplishing this.  Designs using\n  more than one clock often have an\n  [allclocks.txt](https://github.com/ZipCPU/openarty/autodata/allclocks.txt)\n  file to define all of the various clocks used within a design.\n- If peripherals have or create interrupts, those need to be found and\n  determined, and (even better) wired up.\n\n- If an AutoFPGA configuration file describes one of the following classes of\n  items, then the file is wired up and connected to create the necessary bus\n  wiring as well.\n\n  * Bus masters\n\n    Are automatically connected to a crossbar with full access to all of the\n    slaves on the bus\n\n  * One-clock Peripherals (interrupt controller, etc.)\n\n  * Two-clock Peripherals (RTC clock, block RAM, scopes, etc.)\n\n  * Memory Peripherals\n\n    o These need a line within the linker script, and they need to define if\n      their memory region, within that linker script, has read, write, or\n\n    o Generic Peripherals ([flash](auto-data/flash.txt), SDRAM,\n      [MDIO](auto-data/mdio.txt), etc.)\n\n- Peripheral files need to be able to describe more than one peripheral.  For\n  example, the [GPS peripheral file](auto-data/gps.txt) has a GPS-Clock,\n  a companion test bench, GPS-TB, to measure the performance of the GPS clock,\n  and a serial port ([WBUART](https://github.com/ZipCPU/wbuart32)) to allow us\n  to read from the GPS and to write to it and so configure it.  Of course ...\n  this also includes a parameter that must be set (baud rate) based upon the\n  global clock rate.\n\n## Classes\n\nSome peripherals might exist at multiple locations within a design.\nFor example, the WBUART serial component can be used to create multiple\nserial ports within a design.\n\nTo handle this case, the WBUART configuration file may be subclassed within\nother component configuration files by defining a key\n@INCLUDEFILE=[wbuart.txt](auto-data/wbuart.txt).  This will provide a set of\nkeys that the current file can then override (inherit from).\n\nUnfortunately, this only works if the included file has only one component\ndefined within it.\n\n## Math\n\nSome peripherals need to be able to perform basic integer math on a given\nvalue to determine an appropriate setting value.  These peripherals need\naccess to variables.  The classic examples are the baud rate, which depends\nupon the clock rate, as well as the step size necessary for the RTC and the\nGPS clocks, both of which also depend upon the master clock rate.  Other\nexamples might include determining the size of the address space to assign\nto a core based upon the memory size of the component and so forth.\n\nThis feature is currently fully supported using integer math.\n\n## Legacy Updates\n\nThe original version of AutoFPGA supported only one bus master, one bus type,\nand an interconnect with a known bug in it.\n\nSpecifically, the broken interconnect would allow a master to make requests\nof one peripheral and then another before the first peripheral had responded,\nwhile not preventing the requests from returning out of order.\n\nFixing this bug introduced several incompatible changes, therefore there is\nan AutoFPGA `legacy` git tag defined to get back to the older version.\n\nThis newer version, however, now supports:\n\n- Multiple bus types: [Wishbone (pipelined)](sw/bus/wb.cpp),\n  [AXI-Lite](sw/bus/axil.cpp), and [AXI](sw/bus/axi.cpp)\n\n  Additional busses may be supported by simply creating a C++ bus component\n  definition class for them.\n\n- Full crossbar support, using bus helper files from my [WB2AXIP](https://github.com/ZipCPU/wb2axip) repository.\n\nMuch to my surprise, the full crossbar support has proved to be simpler, in\nterms of logic elements used, than the legacy interconnect I had been using.\n\n# Status\n\nThis project now has several designs built around it.  These include the\n[basic AutoFPGA-demo](https://github.com/ZipCPU/autofpga-demo) project,\n[OpenArty](https://github.com/ZipCPU/openarty),\n[ArrowZip](https://github.com/ZipCPU/arrowzip) (legacy AutoFPGA only),\n[AXI DMA test bench](https://github.com/ZipCPU/axidmacheck),\n[ICOZip](https://github.com/ZipCPU/icozip),\n[SDR](https://github.com/ZipCPU/sdr) (a gateware defined radio),\n[ZBasic](https://github.com/ZipCPU/zbasic),\n[ZipStorm-mx](https://github.com/ZipCPU/zipstormmx) (legacy AutoFGPA only), and\n[ZipVersa](https://github.com/ZipCPU/zipversa).  There's also a rather nice\n[Nexys Video project](https://github.com/ZipCPU/videozip) that I've used for\nmodifying and delivering to customers, although the current version on github\nis currently a touch out of date.  You can see the autogenerated logic generated\nfor this project in the [demo directory](demo-out/).\n\nI've also used AutoFPGA to generate a design for the Cyclone-V on the DE-10\nNano, as well as a design for an [Arty Z7-20](https://github.com/ZipCPU/openz7).\n\nIn sum:\n\n- Simple bus components ... just work.  This includes both bus masters and bus\n  slaves.  Not only that, the bus simplifier logic also \"just works\", with\n  the caveat below.\n\n  Note that the AXI SINGLE simplifier itself hasn't (yet) been built.  (It's\n  waiting on a funded need.)  For now, the [AXI DOUBLE bus\n  simplifier](https://github.com/ZipCPU/wb2axip/blob/master/rtl/axidouble.v)\n  should work quite well.  To use it, just declare a bus slave to be a slave\n  of an AXI type bus, with SLAVE.TYPE set to SINGLE, then follow the rule\n  listed in the\n  [simplifier](https://github.com/ZipCPU/wb2axip/blob/master/rtl/axidouble.v).\n  The same applies to the AXI-lite simplifiers.  Wishbone simplifiers, both\n  SINGLE and DOUBLE, are handled by logic inserted into `main.v`, rather\n  than referenced by `main.v`.\n\n- Components with logic in the toplevel work nicely as well.\n\n- AutoFPGA can now support multiple, dissimilar clock rates.  Users just need\n  to specify a clock to generate it.  The clock is then made available for\n  configuration files to reference.  This includes creating a test bench\n  wrapper for Verilator that will drive a multi-clock simulation.\n\n- Addresses get assigned in three groups, and processed in three groups:\n  simple `SINGLE` components having only one address, simple `DOUBLE`\n  components having more addresses but only a single clock delay, and all\n  other components and memories.\n\n- Multiple bus support is now included, allowing you to create and attach\n  components through bus adapters.  This will allow a request to transition\n  from one component to the next, while also keeping track of what the final\n  addresses are for reference from the top level bus.\n\n  This makes it possible for the SDRAM to be on one bus, supporting video\n  reads/writes, and for the CPU to be able to access that bus as\n  well--as a sub-bus of the main peripheral/memory bus.\n\n- Interrupts get assigned to a named controller, and then C++ header files are\n  updated to reflect the interrupt assignments\n\n- A simple integer mathematical expression evaluator exists, allowing simple\n  math expressions and print formats.  This makes it possible to set a global\n  clock frequency value, and to then set baud rates and other clock dividers\n  from it.\n\n- Only one type of address building is supported.  I'd like to be able to\n  support others, but so far this has been sufficient for my first project.\n\n  o Likewise, the project only supports WB B4/pipelined.  No support is\n    provided for WB B3/classic (yet), although creating such support shoud not\n    be difficult at all.\n\n- AutoFPGA now builds a [ZipCPU Linker Script](demo-out/board.ld) for the\n  project.  This script is highly configurable, and many of my projects contain\n  configurations for multiple linker scripts--depending upon which memories\n  I decide to include in the design, or which ones I want a particular piece of\n  software to use.\n\n- The LaTeX specification table building isn't there ... yet.\n\n# Sample component files\n\nComponent files now exist for many of the components I've been using regularly.\nThese include: a [Flash](auto-data/flash.txt) controller,\n[block RAM](auto-data/bkram.txt), a [UART console](auto-data/wbuart.txt),\na very simple [GPIO controller](auto-data/gpio.txt),\n[RMII ethernet controller](auto-data/enet.txt),\n[MDIO ethernet control interface](auto-data/mdio.txt),\na [GPS UART and PPS-driven internal clock](auto-data/gps.txt),\na [Real-Time (GPS driven) Clock](auto-data/rtcgps.txt),\na [PS/2 Mouse](auto-data/wbmouse.txt),\nan [OLED component](auto-data/wboledbw.txt), and more.\nMany of these component cores exist and have their own repositories elsewhere.\nFor example, the wishbone UART core may be found\n[here](https://github.com/ZipCPU/wbuart32), and you can find a [MIG-based,\nWishbone controlled SDRAM component\nhere](https://github.com/ZipCPU/openarty/blob/master/autodata/sdram.txt).\nYou can also find a AXI examples, such as [AXI S2MM stream-to-memory data\nmover](https://github.com/ZipCPU/axidmacheck/blob/master/autodata/axis2mm.txt),\nan [AXI MM2S memory-to-stream data\nmover](https://github.com/ZipCPU/axidmacheck/blob/master/autodata/axis2mm.txt),\nor an [AXM block RAM\ncomponent](https://github.com/ZipCPU/axidmacheck/blob/master/autodata/axiram.txt)\nin the [AXI DMA test repository](https://github.com/ZipCPU/axidmacheck).\nBuilding the cores themselves is not a part of this project, but rather\nfiguring out how to compose multiple cores into a top level design from\nboth cores and component descriptions.\n\n# The ZipCPU blog\n\nSeveral articles have now been written to date about AutoFPGA on the ZipCPU\nblog.  These includes:\n\n1. [A brief introduction to AutoFPGA](https://zipcpu.com/zipcpu/2017/10/05/autofpga-intro.html)\n\n2. [Using AutoFPGA to connect simple registers to a debugging bus](https://zipcpu.com/zipcpu/2017/10/06/autofpga-dataword.html)\n\n   This article is really out of date, in that it describes only the legacy\n   mode (one master, one bus type, etc.)\n\n3. [AutoFPGA's linker script support gets an update](https://zipcpu.com/zipcpu/2018/12/22/autofpga-ld.html)\n\n4. [Technology debt and AutoFPGA, the bill just came due](https://zipcpu.com/zipcpu/2019/08/22/tech-debt.html)\n\n5. [Understanding AutoFPGA's address assignment algorithm](https://zipcpu.com/zipcpu/2019/09/03/address-assignment.html)\n\n# Getting Started\n\nThe current best reference for AutoFPGA is the [icd.txt](doc/icd.txt) file,\nwhich describes all of the various tags AutoFPGA understands and how they\ncan be used.  I've also started working on an [intermediate\ndesign](https://zipcpu.com/tutorial/intermediate.html)\ntutorial based around AutoFPGA, so you might find that a useful place to start\nas well.\n\n# License\n\nAutoFPGA is designed for release under the GPLv3 license.  The AutoFPGA\ngenerated code is yours, and free to be relicensed as you see fit.\n\n# Commercial Applications\n\nShould you find the GPLv3 license insufficient for your needs, other licenses\ncan be purchased from Gisselquist Technology, LLC.  Given that the AutoFPGA\ngenerated code is not encumbered by any license requirements, I really don't\nexpect any such requests.\n\nLikewise, please contact us should you wish to guide, direct, or otherwise\nfund the development of this project.  You can contact me at my user name,\ndgisselq, at the wonderful ieee.org host.\n\n"
  },
  {
    "path": "auto-data/allclocks.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/allclocks.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tDescribe how to create the clocks necessary for the design\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2015-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=iclock\n@ACCESS=ALLCLOCKS_PRESENT\n@CLOCK.NAME=clk\n@CLOCK.WIRE=i_clk\n@CLOCK.FREQUENCY=100000000\n@CLOCK.TOP=i_clk\n@BDEFS.DEFN=\n#define\tCLOCK_FREQUENCY_HZ\t@$(CLOCK.FREQUENCY)\n#define\tCLKFREQHZ\t@$(CLOCK.FREQUENCY)\n@REGDEFS.H.DEFNS=\n#define\tCLKFREQHZ\t@$(CLOCK.FREQUENCY)\n#\n#\n@PREFIX=masterclk\n@TOP.DEFNS=\n\t// Clock/reset definitions\n\t// {{{\n\twire\ts_clk_200mhz,  s_clk_200mhz_unbuffered,\n\t\tsysclk_locked, sysclk_feedback, sysclk_feedback_buffered,\n\t\ts_clk_250mhz,  s_clk_250_unbuffered,\n\t\ts_clk_125mhz,  s_clk_125_unbuffered,\n\t\ts_clk_125d,    s_clk_125d_unbuffered,\n\t\ts_clksync,     s_clksync_unbuffered,\n\t\ts_clk_400mhz,  s_clk_400mhz_unbuffered,\t// Pixclk * 10\n\t\ts_clk_80mhz_unbuffered,\t// 80MHz\n\t\tnetclk_locked, netclk_feedback, netclk_feedback_buffered;\n\twire\ti_clk_buffered;\n\twire\tclocks_locked;\n\twire\tdly_ctrl_ready;\n\treg\t[3:0]\tsysclk_stable, syncd_stable;\n\treg\t[4:0]\tpll_reset_sreg;\n\treg\t\tpll_reset;\n\t// }}}\n@TOP.PORTLIST=\n@TOP.IODECL=\n@TOP.MAIN=\n\t\t// PLL generated clocks\n\t\ts_clk_125mhz\n@TOP.INSERT=\n\t// Buffer the incoming clock\n\tBUFG @$(PREFIX)clkbufi(.I(i_clk), .O(i_clk_buffered));\n\n\t// pll_reset\n\tinitial\t{ pll_reset, pll_reset_sreg } = -1;\n\talways @(posedge i_clk_buffered)\n\t\t{ pll_reset, pll_reset_sreg } <= { pll_reset_sreg, 1'b0 };\n\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// PLL #1: 100MHz, 200MHz, 400MHz, and 80MHz\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t//\n\n\t// But ... the delay controller requires a 200 MHz reference clock,\n\t// the generic clock generator requires a 400MHz clock and a clock\n\t// synchronized to it\n\tPLLE2_BASE #(\n\t\t// {{{\n\t\t.CLKFBOUT_MULT(8),\n\t\t.CLKFBOUT_PHASE(0.0),\n\t\t.CLKIN1_PERIOD(10),\n\t\t.CLKOUT0_DIVIDE(4),\t// 200 MHz\n\t\t.CLKOUT1_DIVIDE(2),\t// 400 MHz\n\t\t.CLKOUT2_DIVIDE(8),\t// 100 MHz\n\t\t.CLKOUT3_DIVIDE(10)\t//  80 MHz\n\t\t// }}}\n\t) gen_sysclk(\n\t\t// {{{\n\t\t.CLKIN1(i_clk_buffered),\n\t\t.CLKOUT0(s_clk_200mhz_unbuffered),\n\t\t.CLKOUT1(s_clk_400mhz_unbuffered),\n\t\t.CLKOUT2(s_clksync_unbuffered),\n\t\t.CLKOUT3(s_clk_80mhz_unbuffered),\n\t\t// .CLKOUT4(),\n\t\t// .CLKOUT5(),\n\t\t.PWRDWN(1'b0), .RST(pll_reset),\n\t\t.CLKFBOUT(sysclk_feedback),\n\t\t.CLKFBIN(sysclk_feedback_buffered),\n\t\t.LOCKED(sysclk_locked)\n\t\t// }}}\n\t);\n\n\tBUFG\tsysbuf(     .I(s_clk_200mhz_unbuffered),.O(s_clk_200mhz));\n\tBUFG\tclksync_buf(.I(s_clksync_unbuffered),   .O(s_clksync));\n\tBUFG\tclk4x_buf(  .I(s_clk_400mhz_unbuffered),.O(s_clk_400mhz));\n\tBUFG\tsys_feedback(.I(sysclk_feedback),.O(sysclk_feedback_buffered));\n\n\t// }}}\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// PLL #2: 125MHz, 250MHz\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t//\n\n\t// The ethernet MAC requires a 125MHz clock\n\t//   We can't trust the RX 125MHz clock for this, since there's a\n\t//   possibility the RX 125MHz clock might arrive at a different rate.\n\t//\n\tPLLE2_BASE #(\n\t\t// {{{\n\t\t.CLKFBOUT_MULT(10),\n\t\t.CLKFBOUT_PHASE(0.0),\n\t\t.CLKIN1_PERIOD(10),\n\t\t.CLKOUT0_DIVIDE(8),\t// 125 MHz\n\t\t.CLKOUT0_PHASE(0),\n\t\t.CLKOUT1_DIVIDE(4),\t// 250 MHz\n\t\t.CLKOUT1_PHASE(0)\n\t\t// }}}\n\t) gen_netclk(\n\t\t// {{{\n\t\t.CLKIN1(i_clk_buffered),\n\t\t.CLKOUT0(s_clk_125_unbuffered),\n\t\t.CLKOUT1(s_clk_250_unbuffered),\n\t\t// .CLKOUT2(),\n\t\t// .CLKOUT3(),\n\t\t// .CLKOUT4(),\n\t\t// .CLKOUT5(),\n\t\t.PWRDWN(1'b0), .RST(pll_reset),\n\t\t.CLKFBOUT(netclk_feedback),\n\t\t.CLKFBIN(netclk_feedback_buffered),\n\t\t.LOCKED(netclk_locked)\n\t\t// }}}\n\t);\n\n\tBUFG\tnetbuf(.I(s_clk_125_unbuffered), .O(s_clk_125mhz));\n\tBUFG\tnetbf5(.I(s_clk_250_unbuffered), .O(s_clk_250mhz));\n\tBUFG\tnetfb(.I(netclk_feedback), .O(netclk_feedback_buffered));\n\n\tassign\tclocks_locked = (netclk_locked && sysclk_locked && dly_ctrl_ready);\n\n\t// }}}\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// reg\t[3:0]\tsysclk_stable;\n\t// {{{\n\tinitial\tsysclk_stable = 0;\n\talways @(posedge i_clk_buffered or negedge clocks_locked)\n\tif (!clocks_locked)\n\t\tsysclk_stable <= 0;\n\telse\n\t\tsysclk_stable <= { sysclk_stable[2:0], 1'b1 };\n\n\tinitial\tsyncd_stable = 0;\n\talways @(posedge i_clk_buffered)\n\tif (!sysclk_stable[3])\n\t\tsyncd_stable <= 0;\n\telse\n\t\tsyncd_stable <= { syncd_stable[2:0], 1'b1 };\n\n\t// }}}\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// IDELAYCTRL\n\tIDELAYCTRL\n\tu_delay_control (\n\t\t.REFCLK(s_clk_200mhz),\n\t\t.RST(!sysclk_locked),\n\t\t.RDY(dly_ctrl_ready)\n\t);\n\n@MAIN.PORTLIST=\n\t\t// Extra clocks\n\t\ti_clk_125mhz\n@MAIN.IODECL=\n\t// Extra clocks\n\t// Verilator lint_off UNUSED\n\tinput\twire\t\ti_clk_125mhz;\n\t// Verilator lint_on  UNUSED\n@MAIN.DEFNS=\n\twire\ti_net_tx_clk;\n@MAIN.INSERT=\n\tassign\ti_net_tx_clk = i_clk_125mhz;\n@CLOCK.WIRE=i_clk_125mhz\n@CLOCK.NAME=clk_125mhz\n@CLOCK.FREQUENCY=125000000\n@CLOCK.TOP=\n@MAIN.IODECL=\n\tinput\twire\t\ti_net_tx_clk;\n@XDC.INSERT=\nset_false_path -from [get_cells -hier -filter {NAME=~ pll_reset*}] -to [get_cells -hier -filter {NAME=~ net*/reset_pipe*}]\nset_false_path -from [get_cells -hier -filter {NAME=~ pll_reset*}] -to [get_cells -hier -filter {NAME=~ net*/sync_reset*}]\n"
  },
  {
    "path": "auto-data/bkram.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/bkram.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tTo define the interface to a generic block RAM device for the\n##\t\tpurposes of autofpga.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=bkram\n@DEVID=BKRAM\n@$LGMEMSZ=20\n@LGMEMSZ.FORMAT=%d\n@$NADDR=(1<<(@$(THIS.LGMEMSZ)))/(@$(SLAVE.BUS.WIDTH)/8)\n@$NBYTES=(1<<(@$THIS.LGMEMSZ))\n@NBYTES.FORMAT=0x%08x\n@ACCESS=@$(DEVID)_ACCESS\n@SLAVE.TYPE=MEMORY\n@SLAVE.BUS=wbwide\n@MAIN.INSERT=\n\tmemdev #(\n\t\t.LGMEMSZ(@$(THIS.LGMEMSZ)),\n\t\t.DW(@$(SLAVE.BUS.WIDTH)),\n\t\t.EXTRACLOCK(1)\n\t) u_@$(PREFIX) (\n\t\t.i_clk(@$(SLAVE.BUS.CLOCK.WIRE)),\n\t\t.i_reset(@$(SLAVE.BUS.CLOCK.RESET)),\n\t\t@$(SLAVE.ANSIPORTLIST)\n\t);\n@REGS.N=1\n@REGS.0= 0 R_@$(DEVID) RAM\n@REGDEFS.H.DEFNS=\n#define\t@$(DEVID)BASE\t@$[0x%08x](REGBASE)\n#define\t@$(DEVID)LEN\t@$NBYTES\n@BDEF.OSDEF=_BOARD_HAS_@$(DEVID)\n@MEM.NAME= @$(PREFIX)\n@BDEF.OSVAL=extern char\t_@$(MEM.NAME)[@$NBYTES];\n@LD.PERM=\twx\n@LD.NAME=\t@$(MEM.NAME)\n@RTL.MAKE.GROUP= @$(DEVID)\n@RTL.MAKE.SUBD=\n@RTL.MAKE.FILES= memdev.v\n@$NADDRHX = @$NADDR\n@NADDRHX.FORMAT= 0x%x\n@SIM.INCLUDE=\n#include \"byteswap.h\"\n@SIM.DEFINES=\n#ifndef VVAR\n#ifdef  ROOT_VERILATOR\n#include \"Vmain___024root.h\"\n\n#define VVAR(A) rootp->main__DOT_ ## A\n#elif\tdefined(NEW_VERILATOR)\n#define VVAR(A) main__DOT_ ## A\n#else\n#define VVAR(A) v__DOT_ ## A\n#endif\n#endif\n\n#define\tblock_ram\trootp->main__DOT__u_@$(PREFIX)__DOT__mem.m_storage\n\n@$BUSBYTES=@$(SLAVE.BUS.WIDTH)/8\n@SLAVE.ORDER=1\n@SIM.LOAD=\n\t\t\tstart = start & (-4);\n\t\t\twlen = (wlen+3)&(-4);\n\n\t\t\t// Need to byte swap data to get it into the memory\n\t\t\tif (@$(SLAVE.BUS.WIDTH) == 32) {\n\t\t\t\tchar\t*bswapd = new char[len+8];\n\t\t\t\tmemcpy(bswapd, &buf[offset], wlen);\n\t\t\t\tbyteswapbuf(len>>2, (uint32_t *)bswapd);\n\t\t\t\tmemcpy(&m_core->block_ram[start], bswapd, wlen);\n\t\t\t\tdelete[] bswapd;\n\t\t\t} else {\n\t\t\t\tfor(unsigned jk=0; jk<wlen; jk=jk+1) {\n\t\t\t\t\tunsigned word_addr, subword_addr;\n\t\t\t\t\tunsigned\t*wp;\n\t\t\t\t\tchar\t\t*cp;\n\n\t\t\t\t\tword_addr = start+jk;\n\t\t\t\t\tword_addr /= @$(SLAVE.BUS.WIDTH)/8;\n\t\t\t\t\twp = m_core->block_ram[word_addr];\n\t\t\t\t\tcp = (char *)wp;\n\n\t\t\t\t\tsubword_addr = start+jk;\n\t\t\t\t\tsubword_addr = ~subword_addr;\n\t\t\t\t\tsubword_addr &= @$(SLAVE.BUS.WIDTH)/8-1;\n\t\t\t\t\t// subword_addr = @$(SLAVE.BUS.WIDTH)/8-subword_addr;\n\t\t\t\t\tcp[subword_addr] = buf[offset+jk];\n\t\t\t\t}\n\t\t\t}\n"
  },
  {
    "path": "auto-data/buserr.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/buserr.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tProvide a readable memory location containing the address of the\n##\t\tlast bus error.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=buserr\n@NADDR=1\n@SLAVE.TYPE=SINGLE\n@SLAVE.BUS=wb32\n@SINGLE.INPUT= r_bus_err\n@CLOCK.NAME=clk\n@$RWID=(@$(zip.MASTER.BUS.AWID) > @$(wbu.MASTER.BUS.AWID)) ? @$(zip.MASTER.BUS.AWID) : @$(wbu.MASTER.BUS.AWID)\n@MAIN.DEFNS=\n\treg\t[@$(RWID)-1:0]\tr_@$(PREFIX)_addr;\n@MAIN.INSERT=\n\talways @(posedge @$(CLOCK.WIRE))\n\tif (@$(zip.MASTER.PREFIX)_err)\n\tbegin\n\t\tr_@$(PREFIX)_addr <= 0;\n\t\tr_@$(PREFIX)_addr[@$(zip.MASTER.BUS.AWID)-1:0] <= @$(zip.MASTER.PREFIX)_addr[@$(zip.MASTER.BUS.AWID)-1:0];\n\tend else if (@$(wbu.MASTER.PREFIX)_err)\n\tbegin\n\t\tr_@$(PREFIX)_addr <= 0;\n\t\tr_@$(PREFIX)_addr[@$(wbu.MASTER.BUS.AWID)-1:0] <= @$(wbu.MASTER.PREFIX)_addr[@$(wbu.MASTER.BUS.AWID)-1:0];\n\tend\n\tassign\t@$(SLAVE.PREFIX)_stall= 1'b0;\n\tassign\t@$(SLAVE.PREFIX)_ack  = @$(SLAVE.PREFIX)_stb;\n\tassign\t@$(SLAVE.PREFIX)_idata = { {(30-@$(RWID)){1'b0}},\n\t\t\tr_@$(PREFIX)_addr, 2'b00 };\n@REGS.N=1\n@REGS.0= 0 R_BUSERR BUSERR\n@BDEF.IONAME=io_buserr\n@BDEF.IOTYPE=unsigned\n@BDEF.OSDEF=_BOARD_HAS_BUSERR\n@BDEF.OSVAL=static volatile @$THIS.BDEF.IOTYPE *const _buserr = ((@$THIS.BDEF.IOTYPE *)@$[0x%08x](REGBASE));\n"
  },
  {
    "path": "auto-data/clkcheck.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/clkcheck.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tTo describe the clkcounter's interface for autofpga to work\n##\t\twith.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=rtc_pps\n@MAIN.DEFNS=\n\t// Verilator lint_off UNUSED\n\treg\t\t@$(PREFIX);\n\treg\t[26:0]\t@$(PREFIX)_counter;\n\t// Verilator lint_on  UNUSED\n@MAIN.INSERT=\n\tinitial\t@$(PREFIX) = 1'b0;\n\tinitial\t@$(PREFIX)_counter = 0;\n\talways @(posedge i_clk)\n\tif (@$(PREFIX)_counter > 0)\n\tbegin\n\t\t@$(PREFIX)_counter <= @$(PREFIX)_counter - 1;\n\t\t@$(PREFIX) <= 1'b0;\n\tend else begin\n\t\t@$(PREFIX)_counter <= 27'd100_000_000 - 1;\n\t\t@$(PREFIX) <= 1'b1;\n\tend\n@PREFIX=rxeth0ck\n@DEVID=RXETH0CK\n@INCLUDEFILE=clkcounter.txt\n@TSTCLOCK=i_eth0_rx_clk\n@DEPENDS=MEGANET_ACCESS\n##\n@PREFIX=txclk\n@DEVID=TXCLK\n@INCLUDEFILE=clkcounter.txt\n@DEPENDS=ALLCLOCKS_PRESENT\n@TSTCLOCK=i_net_tx_clk\n##\n@PREFIX=adcclk\n@DEVID=ADCCLK\n@INCLUDEFILE=clkcounter.txt\n@DEPENDS=ALLCLOCKS_PRESENT\n@TSTCLOCK=i_clk_200mhz\n##\n## @PREFIX=pixclk\n## @DEVID=PIXCLK\n## @INCLUDEFILE=clkcounter.txt\n## @DEPENDS=ALLCLOCKS_PRESENT\n## @TSTCLOCK=i_pixclk\n##\n## @PREFIX=audioclk\n## @DEVID=AUDIOCLK\n## @INCLUDE=clkcounter.txt\n## @TSTCLOCK=i_pixclk\n"
  },
  {
    "path": "auto-data/clkcounter.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/clkcounter.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tThe clkcounter peripheral counts the number of a given clocks\n##\t\tticks per second as defined by a second clock.  This particular\n##\tfile tells us how to connect the clkcounter to the rest of the design\n##\tusing AutoFPGA.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=sysclk\n@DEVID=SYSCLK\n@ACCESS=@$(DEVID)\n@NADDR=\t1\n@SLAVE.TYPE=\tSINGLE\n@SLAVE.BUS=wb32\n@TSTCLOCK=i_clk\n# @SINGLE.INPUTS=\tck_pps\n@MAIN.DEFNS=\n\treg\tr_@$(PREFIX)_ack;\n@MAIN.INSERT=\n\tclkcounter #(\n\t\t.CLOCKFREQ_HZ(0)\t// We'll count PPS externally\n\t) clk@$(PREFIX)ctr(\n\t\t.i_sys_clk(i_clk),\n\t\t.i_tst_clk(@$(TSTCLOCK)),\n\t\t.i_sys_pps(rtc_pps),\n\t\t.o_sys_counts(@$(SLAVE.PREFIX)_idata)\n\t);\n\n\tinitial\tr_@$(PREFIX)_ack = 0;\n\talways @(posedge i_clk)\n\t\tr_@$(PREFIX)_ack <= !i_reset && @$(SLAVE.PREFIX)_stb;\n\tassign\t@$(SLAVE.PREFIX)_ack   = r_@$(PREFIX)_ack;\n\tassign\t@$(SLAVE.PREFIX)_stall = 1'b0;\n@REGS.NOTE = // SYSCLK Clock Counter (measures clock speed)\n@REGS.N = 1\n@REGS.0 = 0 R_@$(DEVID) @$(DEVID)\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE= unsigned\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$(BDEF.IOTYPE) *)@$[0x%08x](REGBASE));\n@XDC.INSERT=\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *clk@$(PREFIX)ctr/avgs*}]       -to [ get_cells -hier -filter {NAME =~*clk@$(PREFIX)ctr/q_v*}]   8.0\n"
  },
  {
    "path": "auto-data/crossbus.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/crossbus.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tProvides access to the smaller 32-bit bus from the 512-bit bus.\n##\t\tAccesses are limited to a single controller only, but perhaps\n##\tthis is okay since I don't expect anything but the CPU and the debugging\n##\tport to control the 32-bit bus.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=crossbus\n@SLAVE.TYPE=BUS\n@SLAVE.BUS=wbwide\n@SLAVE.ANSPREFIX=w\n@SLAVE.ORDER=0\n@ERROR.WIRE=@$(SLAVE.PREFIX)_err\n## @$SLAVE.AWID=@$(MASTER.AWID) >> (@$(SLAVE.BUS_WIDTH)-@$(MASTER.BUS.WIDTH))\n@MASTER.TYPE=SUBBUS\n@MASTER.BUS=wb32\n@OPT_LITTLE_ENDIAN=1'b0\n@OPT_LOWLOGIC=1'b0\n@MAIN.INSERT=\n\twbdown #(\n\t\t// {{{\n\t\t// Slave bus address width: @$(SLAVE.BUS.AWID)\n\t\t// Slave address width    : @$(SLAVE.AWID)\n\t\t// Master address width   : @$(MASTER.BUS.AWID)\n\t\t.ADDRESS_WIDTH(@$(SLAVE.AWID)+$clog2(@$(SLAVE.BUS.WIDTH)/8)),\n\t\t.WIDE_DW(@$(SLAVE.BUS.WIDTH)),\n\t\t.SMALL_DW(@$(MASTER.BUS.WIDTH)),\n\t\t.OPT_LITTLE_ENDIAN(@$(OPT_LITTLE_ENDIAN)),\n\t\t.OPT_LOWLOGIC(@$(OPT_LOWLOGIC))\n\t\t// }}}\n\t) u_@$(PREFIX) (\n\t\t// {{{\n\t\t.i_clk(@$(MASTER.BUS.CLOCK.WIRE)),\n\t\t.i_reset(@$(MASTER.BUS.CLOCK.RESET)),\n\t\t// Slave/incoming\n\t\t// {{{\n\t\t.i_wcyc(  @$(SLAVE.PREFIX)_cyc),\n\t\t.i_wstb(  @$(SLAVE.PREFIX)_stb),\n\t\t.i_wwe(   @$(SLAVE.PREFIX)_we),\n\t\t.i_waddr( @$(SLAVE.PREFIX)_addr[@$(SLAVE.AWID)-1:0]),\n\t\t.i_wdata( @$(SLAVE.PREFIX)_data),\n\t\t.i_wsel(  @$(SLAVE.PREFIX)_sel),\n\t\t.o_wstall(@$(SLAVE.PREFIX)_stall),\n\t\t.o_wack(  @$(SLAVE.PREFIX)_ack),\n\t\t.o_wdata( @$(SLAVE.PREFIX)_idata),\n\t\t.o_werr(  @$(SLAVE.PREFIX)_err),\n\t\t// }}}\n\t\t// Master/down-range/outgoing\n\t\t// {{{\n\t\t.o_scyc(  @$(MASTER.PREFIX)_cyc),\n\t\t.o_sstb(  @$(MASTER.PREFIX)_stb),\n\t\t.o_swe(   @$(MASTER.PREFIX)_we),\n\t\t.o_saddr( @$(MASTER.PREFIX)_addr[@$(MASTER.BUS.AWID)-1:0]),\n\t\t.o_sdata( @$(MASTER.PREFIX)_data),\n\t\t.o_ssel(  @$(MASTER.PREFIX)_sel),\n\t\t.i_sstall(@$(MASTER.PREFIX)_stall),\n\t\t.i_sack(  @$(MASTER.PREFIX)_ack),\n\t\t.i_sdata( @$(MASTER.PREFIX)_idata),\n\t\t.i_serr(  @$(MASTER.PREFIX)_err)\n\t\t// }}}\n\t\t// }}}\n\t);\n"
  },
  {
    "path": "auto-data/ddr3.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/ddr3.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tTo describe how to connect an open source DDR3 controller to\n##\t\tthe design, via the Wishbone bus.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n# Wishbone 1\n@PREFIX=ddr3\n@DEVID=SDRAM\n@ACCESS=@$(DEVID)_ACCESS\n## LGMEMSZ is the size of the SDRAM in bytes. For a 1GB DDR3 RAM: 30 => 1GB\n@$LGMEMSZ=30\n@LGMEMSZ.FORMAT=%d\n@$NADDR=(1<< @$(LGMEMSZ))/(@$(SLAVE.BUS.WIDTH)/8)\n@$NBYTES=(1<<(@$LGMEMSZ))\n@NBYTES.FORMAT=0x%08x\n@$MADDR= @$(REGBASE)\n@MADDR.FORMAT=0x%08x\n@$NLANES=@$(SLAVE.BUS.WIDTH)/64\n@SLAVE.TYPE=MEMORY\n@SLAVE.BUS=wbwide\n@SLAVE.ORDER=100\n@BUS=wbwide\n@LD.PERM=wx\n@LD.NAME=sdram\n#\n@REGS.N=1\n@REGS.0= 0 R_@$(DEVID) @$(DEVID)\n@REGDEFS.H.DEFNS=\n#define\t@$(DEVID)BASE\t@$[0x%08x](REGBASE)\n#define\t@$(DEVID)LEN\t@$(NBYTES)\n@BDEF.OSDEF=_BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL=extern char\t_@$(PREFIX)[@$NBYTES];\n\n@TOP.PORTLIST=\n\t\t// DDR3 I/O port wires\n\t\to_ddr3_reset_n, o_ddr3_cke, o_ddr3_clk_p, o_ddr3_clk_n,\n\t\t\to_ddr3_vsel,\n\t\to_ddr3_cs_n, o_ddr3_ras_n, o_ddr3_cas_n, o_ddr3_we_n,\n\t\to_ddr3_ba, o_ddr3_a,\n\t\to_ddr3_odt, o_ddr3_dm,\n\t\tio_ddr3_dqs_p, io_ddr3_dqs_n, io_ddr3_dq\n\n@TOP.PARAM=\n\tlocalparam real @$(DEVID)CONTROLLER_CLK_PERIOD = 10_000,  //ps, clock period of the controller interface\n\t\tDDR3_CLK_PERIOD = 2_500; //ps, clock period of the DDR3 RAM device (must be 1/4 of the CONTROLLER_CLK_PERIOD) \n\tlocalparam @$(DEVID)ROW_BITS = 14,  // width of row address\n\t\t@$(DEVID)COL_BITS = 10,  // width of column address\n\t\t@$(DEVID)BA_BITS  =  3,  // width of bank address\n\t\t@$(DEVID)DQ_BITS  =  8,  // Size of one octet\n\t\t@$(DEVID)BYTE_LANES = @$(NLANES), //8 lanes of DQ\n\t\t@$(DEVID)AUX_WIDTH = 4, //width of aux line (must be >= 4) \n\t\t@$(DEVID)SERDES_RATIO = $rtoi(@$(DEVID)CONTROLLER_CLK_PERIOD/DDR3_CLK_PERIOD),\n\t\t//4 is the width of a single ddr3 command {cs_n, ras_n, cas_n, we_n} plus 3 (ck_en, odt, reset_n) plus bank bits plus row bits\n\t\t@$(DEVID)CMD_LEN = 4 + 3 + @$(DEVID)BA_BITS + @$(DEVID)ROW_BITS;\n\n\n@TOP.IODECL=\n\t// I/O declarations for the DDR3 SDRAM\n\t// {{{\n\toutput\twire\t\to_ddr3_reset_n;\n\toutput\twire\t[0:0]\to_ddr3_cke;\n\toutput\twire\t[0:0]\to_ddr3_clk_p, o_ddr3_clk_n;\n\toutput\twire\t[0:0]\to_ddr3_cs_n; // o_ddr3_s_n[1] is set to 0 since controller only support single rank\n\toutput\twire\t\to_ddr3_vsel;\n\toutput\twire\t[0:0]\to_ddr3_ras_n, o_ddr3_cas_n, o_ddr3_we_n;\n\toutput\twire\t[@$(DEVID)BA_BITS-1:0]\to_ddr3_ba;\n\toutput\twire\t[14:0]\to_ddr3_a; //set to max of 16 bits, but only ROW_BITS bits are relevant\n\toutput\twire\t[0:0]\to_ddr3_odt;\n\toutput\twire\t[@$(DEVID)BYTE_LANES-1:0]\to_ddr3_dm;\n\tinout\twire\t[(@$(DEVID)DQ_BITS*@$(DEVID)BYTE_LANES)/8-1:0]\tio_ddr3_dqs_p, io_ddr3_dqs_n;\n\tinout\twire\t[(@$(DEVID)DQ_BITS*@$(DEVID)BYTE_LANES)-1:0]\tio_ddr3_dq;\n\t// }}}\n\n@TOP.DEFNS=\n\twire\t\ts_clk, s_reset;\n\treg\t[2:0]\tclk_reset_pipe;\n\t// Wires connected to PHY interface of DDR3 controller\n\t// {{{\n\tgenvar @$(PREFIX)gen_index;\n\n\twire\t[@$(DEVID)DQ_BITS*@$(DEVID)BYTE_LANES*8-1:0] @$(PREFIX)_iserdes_data;\n\twire\t[@$(DEVID)BYTE_LANES*8-1:0] @$(PREFIX)_iserdes_dqs,\n\t\t\t\t@$(PREFIX)_iserdes_bitslip_reference;\n\twire    [@$(DEVID)CMD_LEN*@$(DEVID)SERDES_RATIO-1:0]\n\t\t\t\t@$(PREFIX)_cmd;\n\twire    [@$(DEVID)DQ_BITS*@$(DEVID)BYTE_LANES*8-1:0]\n\t\t\t\t@$(PREFIX)_data;\n\twire    [(@$(DEVID)DQ_BITS*@$(DEVID)BYTE_LANES*8)/8-1:0]\n\t\t\t\t@$(PREFIX)_dm;\n\twire    [4:0]\t@$(PREFIX)_odelay_data_cntvaluein,\n\t\t\t@$(PREFIX)_odelay_dqs_cntvaluein,\n\t\t\t@$(PREFIX)_idelay_data_cntvaluein,\n\t\t\t@$(PREFIX)_idelay_dqs_cntvaluein;\n\twire    [@$(DEVID)BYTE_LANES-1:0]\t@$(PREFIX)_odelay_data_ld,\n\t\t\t@$(PREFIX)_odelay_dqs_ld, @$(PREFIX)_idelay_data_ld,\n\t\t\t@$(PREFIX)_idelay_dqs_ld, @$(PREFIX)_bitslip,\n\t\t\t@$(PREFIX)_debug_read_dqs_p,\n\t\t\t@$(PREFIX)_debug_read_dqs_n;\n\twire    @$(PREFIX)_idelayctrl_rdy,\n\t\t@$(PREFIX)_dqs_tri_control, @$(PREFIX)_dq_tri_control,\n\t\t@$(PREFIX)_toggle_dqs, @$(PREFIX)_write_leveling_calib,\n\t\t@$(PREFIX)_reset;\n\twire    @$(PREFIX)_debug_clk_p, @$(PREFIX)_debug_clk_n;\n\t// }}}\n@TOP.MAIN=\n\t// DDR3 Controller-PHY Interface\n\t@$(PREFIX)_iserdes_data, @$(PREFIX)_iserdes_dqs,\n\t@$(PREFIX)_iserdes_bitslip_reference,\n\t@$(PREFIX)_idelayctrl_rdy,\n\t@$(PREFIX)_cmd,\n\t@$(PREFIX)_dqs_tri_control, @$(PREFIX)_dq_tri_control,\n\t@$(PREFIX)_toggle_dqs, @$(PREFIX)_data, @$(PREFIX)_dm,\n\t@$(PREFIX)_odelay_data_cntvaluein, @$(PREFIX)_odelay_dqs_cntvaluein,\n\t@$(PREFIX)_idelay_data_cntvaluein, @$(PREFIX)_idelay_dqs_cntvaluein,\n\t@$(PREFIX)_odelay_data_ld, @$(PREFIX)_odelay_dqs_ld,\n\t@$(PREFIX)_idelay_data_ld, @$(PREFIX)_idelay_dqs_ld,\n\t@$(PREFIX)_bitslip,\n\t@$(PREFIX)_write_leveling_calib,\n\t@$(PREFIX)_reset\n@TOP.INSERT=\n\tassign\ts_clk = s_clksync;\n\tassign\to_ddr3_vsel = 1'bz;\n\n\talways @(posedge s_clk or negedge clocks_locked)\n\tif (!clocks_locked)\n\t\tclk_reset_pipe <= 3'h7;\n\telse\n\t\tclk_reset_pipe <= { clk_reset_pipe[1:0], 1'b0 };\n\n\tassign\ts_reset = clk_reset_pipe[2];\n\n\t// DDR3 PHY Instantiation\n\tddr3_phy #(\n\t\t// {{{\n\t\t.ROW_BITS(@$(DEVID)ROW_BITS),\t//width of row address\n\t\t.BA_BITS(@$(DEVID)BA_BITS),\t//width of bank address\n\t\t.DQ_BITS(@$(DEVID)DQ_BITS),\t//width of DQ\n\t\t.LANES(@$(DEVID)BYTE_LANES), //8 lanes of DQ\n\t\t.CONTROLLER_CLK_PERIOD(@$(DEVID)CONTROLLER_CLK_PERIOD), //ns, period of clock input to this DDR3 controller module\n\t\t.DDR3_CLK_PERIOD(DDR3_CLK_PERIOD), //ns, period of clock input to DDR3 RAM device\n\t\t.ODELAY_SUPPORTED(1)\n\t\t// }}}\n\t) ddr3_phy_inst (\n\t\t// {{{\n\t\t// clock and reset\n\t\t.i_controller_clk(s_clksync),\n\t\t.i_ddr3_clk(s_clk_400mhz),\n\t\t.i_ref_clk(s_clk_200mhz),\n\t\t.i_ddr3_clk_90(0), //required only when ODELAY_SUPPORTED is zero\n\t\t.i_rst_n(!s_reset),\n\t\t// Controller Interface\n\t\t.i_controller_reset(@$(PREFIX)_reset),\n\t\t.i_controller_cmd(@$(PREFIX)_cmd),\n\t\t.i_controller_dqs_tri_control(@$(PREFIX)_dqs_tri_control),\n\t\t.i_controller_dq_tri_control(@$(PREFIX)_dq_tri_control),\n\t\t.i_controller_toggle_dqs(@$(PREFIX)_toggle_dqs),\n\t\t.i_controller_data(@$(PREFIX)_data),\n\t\t.i_controller_dm(@$(PREFIX)_dm),\n\t\t.i_controller_odelay_data_cntvaluein(@$(PREFIX)_odelay_data_cntvaluein),\n\t\t.i_controller_odelay_dqs_cntvaluein(@$(PREFIX)_odelay_dqs_cntvaluein),\n\t\t.i_controller_idelay_data_cntvaluein(@$(PREFIX)_idelay_data_cntvaluein),\n\t\t.i_controller_idelay_dqs_cntvaluein(@$(PREFIX)_idelay_dqs_cntvaluein),\n\t\t.i_controller_odelay_data_ld(@$(PREFIX)_odelay_data_ld),\n\t\t.i_controller_odelay_dqs_ld(@$(PREFIX)_odelay_dqs_ld),\n\t\t.i_controller_idelay_data_ld(@$(PREFIX)_idelay_data_ld),\n\t\t.i_controller_idelay_dqs_ld(@$(PREFIX)_idelay_dqs_ld),\n\t\t.i_controller_bitslip(@$(PREFIX)_bitslip),\n\t\t.i_controller_write_leveling_calib(@$(PREFIX)_write_leveling_calib),\n\t\t.o_controller_iserdes_data(@$(PREFIX)_iserdes_data),\n\t\t.o_controller_iserdes_dqs(@$(PREFIX)_iserdes_dqs),\n\t\t.o_controller_iserdes_bitslip_reference(@$(PREFIX)_iserdes_bitslip_reference),\n\t\t.o_controller_idelayctrl_rdy(@$(PREFIX)_idelayctrl_rdy),\n\t\t// DDR3 I/O Interface\n\t\t.o_ddr3_clk_p(o_ddr3_clk_p),\n\t\t.o_ddr3_clk_n(o_ddr3_clk_n),\n\t\t.o_ddr3_reset_n(o_ddr3_reset_n),\n\t\t.o_ddr3_cke(o_ddr3_cke[0]), // CKE\n\t\t.o_ddr3_cs_n(o_ddr3_cs_n[0]), // chip select signal (controls rank 1 only)\n\t\t.o_ddr3_ras_n(o_ddr3_ras_n), // RAS#\n\t\t.o_ddr3_cas_n(o_ddr3_cas_n), // CAS#\n\t\t.o_ddr3_we_n(o_ddr3_we_n), // WE#\n\t\t.o_ddr3_addr(o_ddr3_a[@$(DEVID)ROW_BITS-1:0]),\n\t\t.o_ddr3_ba_addr(o_ddr3_ba),\n\t\t.io_ddr3_dq(io_ddr3_dq),\n\t\t.io_ddr3_dqs(io_ddr3_dqs_p),\n\t\t.io_ddr3_dqs_n(io_ddr3_dqs_n),\n\t\t.o_ddr3_dm(o_ddr3_dm),\n\t\t.o_ddr3_odt(o_ddr3_odt[0]), // on-die termination\n\t\t// DEBUG PHY\n\t\t.o_ddr3_debug_read_dqs_p(@$(PREFIX)_debug_read_dqs_p),\n\t\t.o_ddr3_debug_read_dqs_n(@$(PREFIX)_debug_read_dqs_n)\n\t\t// }}}\n\t);\n\n\tgenerate for(@$(PREFIX)gen_index = @$(DEVID)ROW_BITS;\n\t\t\t@$(PREFIX)gen_index < 15;\n\t\t\t@$(PREFIX)gen_index = @$(PREFIX)gen_index + 1)\n\tbegin : GEN_UNUSED_@$(DEVID)_ASSIGN\n\t\tassign o_ddr3_a[@$(PREFIX)gen_index] = 0;\n\tend endgenerate\n@MAIN.PORTLIST=\n\t\t// DDR3 Controller Interface\n\t\ti_@$(PREFIX)_iserdes_data, i_@$(PREFIX)_iserdes_dqs,\n\t\ti_@$(PREFIX)_iserdes_bitslip_reference,\n\t\ti_@$(PREFIX)_idelayctrl_rdy,\n\t\to_@$(PREFIX)_cmd,\n\t\to_@$(PREFIX)_dqs_tri_control, o_@$(PREFIX)_dq_tri_control,\n\t\to_@$(PREFIX)_toggle_dqs, o_@$(PREFIX)_data, o_@$(PREFIX)_dm,\n\t\to_@$(PREFIX)_odelay_data_cntvaluein, o_@$(PREFIX)_odelay_dqs_cntvaluein,\n\t\to_@$(PREFIX)_idelay_data_cntvaluein, o_@$(PREFIX)_idelay_dqs_cntvaluein,\n\t\to_@$(PREFIX)_odelay_data_ld, o_@$(PREFIX)_odelay_dqs_ld,\n\t\to_@$(PREFIX)_idelay_data_ld, o_@$(PREFIX)_idelay_dqs_ld,\n\t\to_@$(PREFIX)_bitslip,\n\t\to_@$(PREFIX)_leveling_calib,\n\t\to_@$(PREFIX)_reset\n@MAIN.PARAM=@$(TOP.PARAM)\n@MAIN.IODECL=\n\t// DDR3 Controller I/O declarations\n\t// {{{\n\tinput\twire\t[@$(DEVID)DQ_BITS*@$(DEVID)BYTE_LANES*8-1:0] i_@$(PREFIX)_iserdes_data;\n\tinput wire    [@$(DEVID)BYTE_LANES*8-1:0] i_@$(PREFIX)_iserdes_dqs;\n\tinput wire    [@$(DEVID)BYTE_LANES*8-1:0] i_@$(PREFIX)_iserdes_bitslip_reference;\n\tinput wire    i_@$(PREFIX)_idelayctrl_rdy;\n\toutput wire    [@$(DEVID)CMD_LEN*@$(DEVID)SERDES_RATIO-1:0] o_@$(PREFIX)_cmd;\n\toutput wire    o_@$(PREFIX)_dqs_tri_control, o_@$(PREFIX)_dq_tri_control;\n\toutput wire    o_@$(PREFIX)_toggle_dqs;\n\toutput wire    [@$(DEVID)DQ_BITS*@$(DEVID)BYTE_LANES*8-1:0] o_@$(PREFIX)_data;\n\toutput wire    [(@$(DEVID)DQ_BITS*@$(DEVID)BYTE_LANES*8)/8-1:0] o_@$(PREFIX)_dm;\n\toutput wire    [4:0] o_@$(PREFIX)_odelay_data_cntvaluein, o_@$(PREFIX)_odelay_dqs_cntvaluein;\n\toutput wire    [4:0] o_@$(PREFIX)_idelay_data_cntvaluein, o_@$(PREFIX)_idelay_dqs_cntvaluein;\n\toutput wire    [@$(DEVID)BYTE_LANES-1:0] o_@$(PREFIX)_odelay_data_ld, o_@$(PREFIX)_odelay_dqs_ld;\n\toutput wire    [@$(DEVID)BYTE_LANES-1:0] o_@$(PREFIX)_idelay_data_ld, o_@$(PREFIX)_idelay_dqs_ld;\n\toutput wire    [@$(DEVID)BYTE_LANES-1:0] o_@$(PREFIX)_bitslip;\n\toutput wire    o_@$(PREFIX)_leveling_calib;\n\toutput wire    o_@$(PREFIX)_reset;\n\t// }}}\n@MAIN.DEFNS=\n\t// Verilator lint_off UNUSED\n\twire\t[@$(DEVID)AUX_WIDTH-1:0]\t@$(PREFIX)_aux_out;\n\twire\t[31:0]\t@$(PREFIX)_debug;\n\t// Verilator lint_on  UNUSED\n@MAIN.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// DDR3 Controller instantiation\n\t// {{{\n           \n\tddr3_controller #(\n\t\t// {{{\n\t\t.CONTROLLER_CLK_PERIOD(@$(DEVID)CONTROLLER_CLK_PERIOD), //ps, clock period of the controller interface\n\t\t.DDR3_CLK_PERIOD(DDR3_CLK_PERIOD), //ps, clock period of the DDR3 RAM device (must be 1/4 of the CONTROLLER_CLK_PERIOD) \n\t\t.ROW_BITS(@$(DEVID)ROW_BITS),\t//width of row address\n\t\t.COL_BITS(@$(DEVID)COL_BITS),\t//width of column address\n\t\t.BA_BITS(@$(DEVID)BA_BITS),\t//width of bank address\n\t\t.DQ_BITS(@$(DEVID)DQ_BITS),\t//width of DQ\n\t\t.LANES(@$(DEVID)BYTE_LANES),\t\t// byte lanes\n\t\t.AUX_WIDTH(@$(DEVID)AUX_WIDTH),\t//width of aux line (must be >= 4) \n\t\t.WB2_ADDR_BITS(7), \t\t//width of 2nd wishbone address bus \n            \t.WB2_DATA_BITS(32),  \t\t//width of 2nd wishbone data bus\n\t\t.MICRON_SIM(0),\t\t//simulation for micron ddr3 model (shorten POWER_ON_RESET_HIGH and INITIAL_CKE_LOW)\n\t\t.ODELAY_SUPPORTED(1),\t\t//set to 1 when ODELAYE2 is supported\n\t\t.SECOND_WISHBONE(1) \t\t//set to 1 if 2nd wishbone is needed \n\t\t// }}}\n\t) u_@$(PREFIX) (\n\t\t// {{{\n\t\t.i_controller_clk(i_clk), //i_controller_clk has period of CONTROLLER_CLK_PERIOD\n\t\t.i_rst_n(!i_reset), //200MHz input clock\n\t\t// Wishbone 1 (Controller)\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t.i_aux(0),\n\t\t.o_aux(@$(PREFIX)_aux_out),\t// Leaving this empty would've caused a Verilator warning\n\t\t// Wishbone 2 (PHY)\n\t\t@$(ddr3_phy.SLAVE.ANSIPORTLIST),\n\t\t//\n\t\t// PHY interface\n\t\t.i_phy_iserdes_data(i_@$(PREFIX)_iserdes_data),\n\t\t.i_phy_iserdes_dqs(i_@$(PREFIX)_iserdes_dqs),\n\t\t.i_phy_iserdes_bitslip_reference(i_@$(PREFIX)_iserdes_bitslip_reference),\n\t\t.i_phy_idelayctrl_rdy(i_@$(PREFIX)_idelayctrl_rdy),\n\t\t.o_phy_cmd(o_@$(PREFIX)_cmd),\n\t\t.o_phy_dqs_tri_control(o_@$(PREFIX)_dqs_tri_control),\n\t\t.o_phy_dq_tri_control(o_@$(PREFIX)_dq_tri_control),\n\t\t.o_phy_toggle_dqs(o_@$(PREFIX)_toggle_dqs),\n\t\t.o_phy_data(o_@$(PREFIX)_data),\n\t\t.o_phy_dm(o_@$(PREFIX)_dm),\n\t\t.o_phy_odelay_data_cntvaluein(o_@$(PREFIX)_odelay_data_cntvaluein),\n\t\t.o_phy_odelay_dqs_cntvaluein(o_@$(PREFIX)_odelay_dqs_cntvaluein),\n\t\t.o_phy_idelay_data_cntvaluein(o_@$(PREFIX)_idelay_data_cntvaluein),\n\t\t.o_phy_idelay_dqs_cntvaluein(o_@$(PREFIX)_idelay_dqs_cntvaluein),\n\t\t.o_phy_odelay_data_ld(o_@$(PREFIX)_odelay_data_ld),\n\t\t.o_phy_odelay_dqs_ld(o_@$(PREFIX)_odelay_dqs_ld),\n\t\t.o_phy_idelay_data_ld(o_@$(PREFIX)_idelay_data_ld),\n\t\t.o_phy_idelay_dqs_ld(o_@$(PREFIX)_idelay_dqs_ld),\n\t\t.o_phy_bitslip(o_@$(PREFIX)_bitslip),\n\t\t.o_phy_write_leveling_calib(o_@$(PREFIX)_leveling_calib),\n\t\t.o_phy_reset(o_@$(PREFIX)_reset),\n\t\t// Debug port\n\t\t.o_debug1(@$(PREFIX)_debug),\n\t\t// Verilator lint_off PINCONNECTEMPTY\n\t\t.o_debug2(),\n\t\t.o_debug3()\n\t\t// Verilator lint_on  PINCONNECTEMPTY\n\t\t// }}}\n\t);\n\t// }}}\n##\n##\n@PREFIX=ddr3_phy\n@DEVID=DDR3_PHY\n@ACCESS=@$(DEVID)_ACCESS\n@$NADDR=128\n@SLAVE.TYPE=OTHER\n@SLAVE.BUS=wb32\n@SLAVE.ANSPREFIX=wb2_\n#\n@REGS.N=7\n@REGS.0= 0 R_@$(DEVID) @$(DEVID) DPHYSTAT0\n@REGS.1=1 R_@$(DEVID)STAT1 @$(DEVID)STAT1 DPHYSTAT1\n@REGS.2=2 R_@$(DEVID)STAT2 @$(DEVID)STAT2 DPHYSTAT2\n@REGS.3=3 R_@$(DEVID)STAT3 @$(DEVID)STAT3 DPHYSTAT3\n@REGS.4=4 R_@$(DEVID)CTRLSTAT @$(DEVID)CTRLSTAT DCTRLSTAT\n@REGS.5=17 R_@$(DEVID)RESET @$(DEVID)RESET DCTRLRESET\n@REGS.6=19 R_@$(DEVID)DBGSEL @$(DEVID)DBGSEL DCTRLDBG\n@BDEF.DEFN=\n\n## Define the structure of your PHY controller here.  How are the bits all\n## layout out?  What register names do you have?  That should all go here.\n\ntypedef\tstruct\t@$(DEVID)_S {\n\tunsigned\tph_something;\n} @$(DEVID);\n\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE=@$(DEVID)\n@BDEF.OSDEF=_BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$(BDEF.IOTYPE) *)@$[0x%08x](REGBASE));\n\n@RTL.MAKE.GROUP=DDR3\n@RTL.MAKE.SUBD=ddr3\n@RTL.MAKE.FILES= ddr3_controller.v ddr3_phy.v\n"
  },
  {
    "path": "auto-data/edid.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/edid.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tExtended Display Identification Data.  This peripheral is\n##\t\tresponsible for the ability to both read EDID from the\n##\tdownstream display, for forwarding it to the upstream (receive)\n##\tdisplay generator, and for making things available for the CPU to\n##\tread.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2015-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=edid\n@DEVID=EDID\n@ACCESS=@$(DEVID)_ACCESS\n@INCLUDEFILE=i2ccpu.txt\n@IOSDA=io_hdmitx_sda\n@IOSCL=io_hdmitx_scl\n@INTERRUPT=edid_int\n@INT.I2C.WIRE=\n@INT.I2C.PIC=\n@INT.EDID.WIRE=@$(INTERRUPT)\n@INT.EDID.PIC=syspic\n@BDEF.DEFN=\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE= I2CCPU\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$(BDEF.IOTYPE) *)@$[0x%08x](REGBASE));\n\n@MAIN.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// The EDID I2C Controller\n\t// {{{\n\n\twbi2ccpu #(\n\t\t.ADDRESS_WIDTH(@$(MASTER.BUS.AWID)),\n\t\t.DATA_WIDTH(@$(MASTER.BUS.WIDTH)),\n\t\t.AXIS_ID_WIDTH(@$(IDW))\n\t) u_@$(PREFIX) (\n\t\t// {{{\n\t\t.i_clk(@$(SLAVE.BUS.CLOCK.WIRE)), .i_reset(@$(SLAVE.BUS.CLOCK.RESET)),\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t@$(MASTER.ANSIPORTLIST),\n\t\t.i_i2c_sda(i_@$(PREFIX)_sda), .i_i2c_scl(i_@$(PREFIX)_scl),\n\t\t.o_i2c_sda(o_@$(PREFIX)_sda), .o_i2c_scl(o_@$(PREFIX)_scl),\n\t\t.M_AXIS_TVALID(@$(PREFIX)_valid), .M_AXIS_TREADY(@$(PREFIX)_ready),\n\t\t\t.M_AXIS_TDATA(@$(PREFIX)_data), .M_AXIS_TLAST(@$(PREFIX)_last),\n\t\t\t.M_AXIS_TID(@$(PREFIX)_id),\n\t\t.i_sync_signal(rtc_pps),\n\t\t//\n\t\t.o_interrupt(@$(INTERRUPT)),\n\t\t.o_debug(@$(PREFIX)_debug)\n\t\t// }}}\n\t);\n\n\t// }}}\n##\n################################################################################\n################################################################################\n################################################################################\n##\n@PREFIX=edidslv\n@DEVID=EDIDRX\n@NADDR=64\n@SLAVE.BUS=wb32\n@SLAVE.TYPE=DOUBLE\n@STREAM=edid\n@IOSDA=io_hdmirx_sda\n@IOSCL=io_hdmirx_scl\n@TOP.PORTLIST=\n\t\t// EDID RX definitions\n\t\t@$(IOSCL), @$(IOSDA)\n@TOP.IODECL=\n\t// EDID RX definitions\n\tinout\twire\t@$(IOSCL), @$(IOSDA);\n@TOP.DEFNS=\n\twire\tw_@$(PREFIX)_scl, w_@$(PREFIX)_sda;\n@TOP.INSERT=\n\tassign\t@$(IOSCL) = w_@$(PREFIX)_scl ? 1'bz : 1'b0;\n\tassign\t@$(IOSDA) = w_@$(PREFIX)_sda ? 1'bz : 1'b0;\n@TOP.MAIN=\n\t// EDID RX definitions\n\t@$(IOSCL), @$(IOSDA),\n\tw_@$(PREFIX)_scl,  w_@$(PREFIX)_sda\n@MAIN.PORTLIST=\n\t\t// EDID RX definitions\n\t\ti_@$(PREFIX)_scl, i_@$(PREFIX)_sda,\n\t\to_@$(PREFIX)_scl, o_@$(PREFIX)_sda\n@MAIN.IODECL=\n\t// EDID RX definitions\n\tinput\twire\ti_@$(PREFIX)_scl, i_@$(PREFIX)_sda;\n\toutput\twire\to_@$(PREFIX)_scl, o_@$(PREFIX)_sda;\n@MAIN.DEFNS=\n\t// Verilator lint_off UNUSED\n\twire\t[31:0]\t@$(PREFIX)_dbg;\n\t// Verilator lint_on  UNUSED\n@MAIN.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// @$(DEVID)\n\t// {{{\n\twbi2cslave #(\n\t\t.AXIS_SUPPORT(1'b1),\n\t\t.SLAVE_ADDRESS(7'h50)\n\t) u_@$(PREFIX) (\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t.s_valid(@$(STREAM)_valid), .s_ready(@$(STREAM)_ready),\n\t\t\t.s_data(@$(STREAM)_data), .s_last(@$(STREAM)_last),\n\t\t.i_i2c_scl(i_@$(PREFIX)_scl), .i_i2c_sda(i_@$(PREFIX)_sda),\n\t\t.o_i2c_scl(o_@$(PREFIX)_scl), .o_i2c_sda(o_@$(PREFIX)_sda),\n\t\t.o_dbg(@$(PREFIX)_dbg)\n\t);\n\t// }}}\n\n@REGS.N=1\n@REGS.0=0 R_EDIDRX EDIDRX\n@RTL.MAKE.FILES=wbi2cslave.v\n@RTL.MAKE.GROUP=I2CSLV\n@RTL.MAKE.SUBD=wbi2c\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE=char\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$(BDEF.IOTYPE) *)@$[0x%08x](REGBASE));\n\n"
  },
  {
    "path": "auto-data/edidslvscope.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/edidslvscope.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tDescribes how to connect the EDID/I2C debugging port to a\n##\t\t(compressed) wishbone scope, then to be connected to the bus\n##\tby autofpga.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=edidslvscope\n@DEVID=EDIDSLVSCOPE\n@TARGET=edidslv\n@TRIGGER=edidslv_dbg[31]\n@DEBUG=edidslv_dbg[30:0]\n@LOG_CAPTURE_SIZE=13\n@INCLUDEFILE=wbscopc.txt\n@INT.EDIDSLVSCOPE.PIC=altpic\n@INT.EDIDSLVSCOPE.WIRE=@$(PREFIX)_int\n@$DEFHOLDOFF=0\n@MAIN.DEFNS=\n"
  },
  {
    "path": "auto-data/exconsole.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/exconsole.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tProvide access to both a debugging bus and a console port for\n##\t\tthe CPU.  The debugging bus will be given 7-bit transfer codes\n##\twith the high bit set, the console the same codes but with bit 8 clear.\n##\n##\tThis particular version of the console uses the exbus debugging bus.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=wbu\n@DEVID=DBGBUS\n@ACCESS=EXBUS_MASTER\n@MASTER.BUS=wbu\n@MASTER.TYPE=HOST\n@MASTER.PREFIX=@$(PREFIX)\n@BUS.NAME=wbu\n@BUS.CLOCK=clk\n@BUS.WIDTH=32\n@BUS.TYPE=wb\n@BUS.OPT_DBLBUFFER=1\n@$BAUDRATE=1000000\n@OFF_TIL_ACCESS=1'b0\n@CLOCK.NAME=clk\n@CLOCK.RESET=i_reset\n@$SETUP=(@$(CLOCK.FREQUENCY) + @$(BAUDRATE)/2) / @$BAUDRATE\n@SETUP.FORMAT=24'h%x\n@$BUS_ADDRESS_WIDTH=@$(MASTER.BUS.AWID)\n@MAIN.PORTLIST=\n\t\t// UART/host to wishbone interface\n\t\ti_@$(PREFIX)_uart_rx, o_@$(PREFIX)_uart_tx\n@MAIN.IODECL=\n\tinput\twire\t\ti_@$(PREFIX)_uart_rx;\n\toutput\twire\t\to_@$(PREFIX)_uart_tx;\n@MAIN.PARAM=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// EXBUS parameters\n\t// {{{\n\t// Baudrate : @$[%9d](BAUDRATE)\n\t// Clock    : @$[%9d](CLOCK.FREQUENCY)\n\tlocalparam [23:0] BUSUART = @$SETUP;\t// @$[%9d](BAUDRATE) baud\n\tlocalparam\t@$(DEVID)BITS = $clog2(BUSUART);\n\t// }}}\n@MAIN.DEFNS=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// EXBUS: USB-UART interface declarations\n\t// {{{\n\t//\n\twire\t[7:0]\t@$(PREFIX)_rx_data, @$(PREFIX)_tx_data;\n\twire\t\t@$(PREFIX)_rx_stb;\n\twire\t\t@$(PREFIX)_tx_stb, @$(PREFIX)_tx_busy;\n\n\t// Verilator lint_off UNUSED\n\twire\t[0:0]\tex_reset;\n\twire\t[1:0]\tex_gpio;\n\t// Verilator lint_on  UNUSED\n\t// }}}\n@MAIN.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// EXBUS: USB-UART driven bus master and console\n\t// {{{\n\t// The Host USB interface, to be used by the WB-UART bus\n\trxuartlite\t#(\n\t\t// {{{\n\t\t.TIMER_BITS(@$(DEVID)BITS),\n\t\t.CLOCKS_PER_BAUD(BUSUART[@$(DEVID)BITS-1:0])\n\t\t// }}}\n\t) rcv(\n\t\t// {{{\n\t\t.i_clk(      @$(CLOCK.WIRE)),\n\t\t.i_uart_rx(i_@$(PREFIX)_uart_rx),\n\t\t.o_wr(       @$(PREFIX)_rx_stb),\n\t\t.o_data(     @$(PREFIX)_rx_data)\n\t\t// }}}\n\t);\n\n\ttxuartlite\t#(\n\t\t// {{{\n\t\t.TIMING_BITS(@$(DEVID)BITS[4:0]),\n\t\t.CLOCKS_PER_BAUD(BUSUART[@$(DEVID)BITS-1:0])\n\t\t// }}}\n\t) txv(\n\t\t// {{{\n\t\t.i_clk(    @$(CLOCK.WIRE)),\n\t\t.i_wr(     @$(PREFIX)_tx_stb),\n\t\t.i_data(   @$(PREFIX)_tx_data),\n\t\t.o_uart_tx(o_@$(PREFIX)_uart_tx),\n\t\t.o_busy(   @$(PREFIX)_tx_busy)\n\t\t// }}}\n\t);\n\n`ifndef\tBUSPIC_ACCESS\n\twire\tw_bus_int;\n\tassign\tw_bus_int = 1'b0;\n`endif\n\t// Verilator lint_off UNUSED\n\twire\t[29:0]\t@$(MASTER.PREFIX)_tmp_addr;\n\t// Verilator lint_on  UNUSED\n\texbuswb #(\n\t\t// {{{\n\t\t// .LGWATCHDOG(@$(DEVID)WATCHDOG)\n\t\t.ADDRESS_WIDTH(@$(BUS_ADDRESS_WIDTH))\n\t\t// }}}\n\t) u_exbus(\n\t\t// {{{\n\t\t.i_clk(@$(CLOCK.WIRE)), .i_reset(@$(CLOCK.RESET)),\n\t\t.o_reset(ex_reset),\n\t\t.i_rx_stb(@$(PREFIX)_rx_stb), .i_rx_byte(@$(PREFIX)_rx_data),\n\t\t.o_tx_stb(@$(PREFIX)_tx_stb), .o_tx_byte(@$(PREFIX)_tx_data),\n\t\t\t.i_tx_busy(@$(PREFIX)_tx_busy),\n\t\t//\n\t\t.i_gpio(2'b00), .o_gpio(ex_gpio),\n\t\t//\n\t\t.i_console_stb(w_console_tx_stb),\n\t\t\t.i_console_byte(w_console_tx_data),\n\t\t\t.o_console_busy(w_console_busy),\n\t\t.o_console_stb(w_console_rx_stb),\n\t\t\t.o_console_byte(w_console_rx_data),\n\t\t//\n\t\t.o_wb_cyc(@$(MASTER.PREFIX)_cyc), .o_wb_stb(@$(MASTER.PREFIX)_stb),\n\t\t\t.o_wb_we(@$(MASTER.PREFIX)_we),\n\t\t\t.o_wb_addr(@$(MASTER.PREFIX)_addr),\n\t\t\t.o_wb_data(@$(MASTER.PREFIX)_data),\n\t\t\t.o_wb_sel(@$(MASTER.PREFIX)_sel),\n\t\t.i_wb_stall(@$(MASTER.PREFIX)_stall),\n\t\t\t.i_wb_ack(@$(MASTER.PREFIX)_ack),\n\t\t.i_wb_data(@$(MASTER.PREFIX)_idata),\n\t\t.i_wb_err(@$(MASTER.PREFIX)_err),\n\t\t.i_interrupt(w_bus_int)\n\t\t// }}}\n\t);\n\t// }}}\n@REGDEFS.H.DEFNS=\n#define\tBAUDRATE\t@$[%d](BAUDRATE)\n@RTL.MAKE.GROUP= EXBUS\n@RTL.MAKE.SUBD=exbus\n@RTL.MAKE.FILES= exbuswb.v excompress.v exdecompress.v exdeword.v\n\texidle.v exmkword.v exwb.v exfifo.v\n@SIM.INCLUDE=\n#include \"dbluartsim.h\"\n@SIM.CLOCK=@$(CLOCK.NAME)\n@SIM.DEFNS=\n\tDBLUARTSIM\t*m_@$(PREFIX);\n@SIM.INIT=\n\t\tm_@$(PREFIX) = new DBLUARTSIM();\n\t\tm_@$(PREFIX)->setup(@$[%d](SETUP));\n@SIM.TICK=\n\t\tm_core->i_@$(PREFIX)_uart_rx = (*m_@$(PREFIX))(m_core->o_@$(PREFIX)_uart_tx);\n"
  },
  {
    "path": "auto-data/flash.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/flash.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tDescribes the flash in our new data format.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=flash\n@DEVID=FLASH\n@ACCESS=@$(DEVID)_ACCESS\n@$LGFLASHSZ=24\n@$NADDR=(1<<(@$LGFLASHSZ-2))\n@$NBYTES=(1<<@$LGFLASHSZ)\n@NBYTES.FORMAT=0x%08x\n@SLAVE.TYPE=MEMORY\n@SLAVE.BUS=wbflash\n@BUS.NAME=wbflash\n@BUS.WIDTH=32\n@BUS.TYPE=wb\n@BUS.CLOCK=clk\n@BUS.NULLSZ=0x100\n@NDUMMY=6\n@RDDELAY=2\n@STARTUP_SCRIPT=\"spansion.hex\"\n@TOP.PORTLIST=\n\t\t// Top level Quad-SPI I/O ports\n\t\to_@$(PREFIX)_cs_n, io_@$(PREFIX)_dat\n@TOP.IODECL=\n\t// Quad SPI flash\n\toutput\twire\t\to_@$(PREFIX)_cs_n;\n\tinout\twire\t[3:0]\tio_@$(PREFIX)_dat;\n@TOP.DEFNS=\n\twire\t\tw_@$(PREFIX)_sck, w_@$(PREFIX)_cs_n;\n\twire\t[1:0]\t@$(PREFIX)_bmod;\n\twire\t[3:0]\t@$(PREFIX)_dat;\n@TOP.MAIN=\n\t\t// Quad SPI flash\n\t\tw_@$(PREFIX)_cs_n, w_@$(PREFIX)_sck, @$(PREFIX)_dat, io_@$(PREFIX)_dat, @$(PREFIX)_bmod\n@TOP.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// QSPI Flash IO pin handling\n\t// {{{\n\t//\n\t// Wires for setting up the QSPI flash wishbone peripheral\n\t//\n\t//\n\t// QSPI)BMOD, Quad SPI bus mode, Bus modes are:\n\t//\t0?\tNormal serial mode, one bit in one bit out\n\t//\t10\tQuad SPI mode, going out\n\t//\t11\tQuad SPI mode coming from the device (read mode)\n\txqflex #(\n\t\t.OPT_CLOCK(1'b0), .OPT_PHASE(1'b1)\n\t) u_xqflex (\n\t\t.i_clk(s_clk), .i_cs_n(w_@$(PREFIX)_cs_n), .i_sck(w_@$(PREFIX)_sck),\n\t\t.i_dat(o_@$(PREFIX)_dat), .o_dat(i_@$(PREFIX)_dat), .i_bmod(@$(PREFIX)_bmod),\n\t\t//\n\t\t.o_cs_n(o_@$(PREFIX)_cs_n), .o_sck(o_@$(PREFIX)_sck), .io_dat(io_@$(PREFIX)_dat)\n\t);\n\n\t// The following primitive is necessary in many designs order to gain\n\t// access to the o_@$(PREFIX)_sck pin.  It's not necessary on the Arty,\n\t// simply because they provide two pins that can drive the QSPI\n\t// clock pin.\n\twire\t[3:0]\tsu_nc;\t// Startup primitive, no connect\n\tSTARTUPE2 #(\n\t\t// {{{\n\t\t// Leave PROG_USR false to avoid activating the program\n\t\t// event security feature.  Notes state that such a feature\n\t\t// requires encrypted bitstreams.\n\t\t.PROG_USR(\"FALSE\"),\n\t\t// Sets the configuration clock frequency (in ns) for\n\t\t// simulation.\n\t\t.SIM_CCLK_FREQ(0.0)\n\t\t// }}}\n\t) STARTUPE2_inst (\n\t\t// {{{\n\t\t// CFGCLK, 1'b output: Configuration main clock output -- no\n\t\t//\tconnect\n\t\t.CFGCLK(su_nc[0]),\n\t\t// CFGMCLK, 1'b output: Configuration internal oscillator clock\n\t\t//\toutput\n\t\t.CFGMCLK(su_nc[1]),\n\t\t// EOS, 1'b output: Active high output indicating the End Of\n\t\t//\tStartup.\n\t\t.EOS(su_nc[2]),\n\t\t// PREQ, 1'b output: PROGRAM request to fabric output\n\t\t//\tOnly enabled if PROG_USR is set.  This lets the fabric\n\t\t//\tknow that a request has been made (either JTAG or pin\n\t\t//\tpulled low) to program the device\n\t\t.PREQ(su_nc[3]),\n\t\t// CLK, 1'b input: User start-up clock input\n\t\t.CLK(1'b0),\n\t\t// GSR, 1'b input: Global Set/Reset input\n\t\t.GSR(1'b0),\n\t\t// GTS, 1'b input: Global 3-state input\n\t\t.GTS(1'b0),\n\t\t// KEYCLEARB, 1'b input: Clear AES Decrypter Key input from\n\t\t//\tBBRAM\n\t\t.KEYCLEARB(1'b0),\n\t\t// PACK, 1-bit input: PROGRAM acknowledge input\n\t\t//\tThis pin is only enabled if PROG_USR is set.  This\n\t\t//\tallows the FPGA to acknowledge a request for reprogram\n\t\t//\tto allow the FPGA to get itself into a reprogrammable\n\t\t//\tstate first.\n\t\t.PACK(1'b0),\n\t\t// USRCLKO, 1-bit input: User CCLK input -- This is why I am\n\t\t//\tusing this module at all.\n\t\t.USRCCLKO(o_@$(PREFIX)_sck),\n\t\t// USRCCLKTS, 1'b input: User CCLK 3-state enable input\n\t\t//\tAn active high here places the clock into a high\n\t\t//\timpedence state.  Since we wish to use the clock as an\n\t\t//\tactive output always, we drive this pin low.\n\t\t.USRCCLKTS(1'b0),\n\t\t// USRDONEO, 1'b input: User DONE pin output control\n\t\t//\tSet this to \"high\" to make sure that the DONE LED pin\n\t\t//\tis high.\n\t\t.USRDONEO(1'b1),\n\t\t// USRDONETS, 1'b input: User DONE 3-state enable output\n\t\t//\tThis enables the FPGA DONE pin to be active.  Setting\n\t\t//\tthis active high sets the DONE pin to high impedence,\n\t\t//\tsetting it low allows the output of this pin to be as\n\t\t//\tstated above.\n\t\t.USRDONETS(1'b1)\n\t\t// }}}\n\t);\n\t// }}}\n@MAIN.PORTLIST=\n\t\t// The Universal QSPI Flash\n\t\to_@$(PREFIX)_cs_n, o_@$(PREFIX)_sck, o_@$(PREFIX)_dat, i_@$(PREFIX)_dat, o_@$(PREFIX)_mod\n@MAIN.IODECL=\n\t// The Universal QSPI flash\n\toutput\twire\t\to_@$(PREFIX)_cs_n, o_@$(PREFIX)_sck;\n\toutput\twire\t[3:0]\to_@$(PREFIX)_dat;\n\tinput\twire\t[3:0]\ti_@$(PREFIX)_dat;\n\toutput\twire\t[1:0]\to_@$(PREFIX)_mod;\n@MAIN.DEFNS=\n\t// Definitions for the @$(PREFIX) debug port\n\t// Verilator lint_off UNUSED\n\twire\t\t@$(PREFIX)_dbg_trigger;\n\twire\t[31:0]\t@$(PREFIX)_debug;\n\t// Verilator lint_on  UNUSED\n@MAIN.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// Flash controller\n\t// {{{\n\tqflexpress #(\n\t\t// {{{\n\t\t.LGFLASHSZ(@$LGFLASHSZ), .OPT_CLKDIV(1),\n\t\t.OPT_ENDIANSWAP(0),\n\t\t.NDUMMY(@$(NDUMMY)), .RDDELAY(@$(RDDELAY)),\n\t\t.OPT_STARTUP_FILE(@$(STARTUP_SCRIPT)),\n`ifdef\tFLASHCFG_ACCESS\n\t\t.OPT_CFG(1'b1)\n`else\n\t\t.OPT_CFG(1'b0)\n`endif\n\t\t// }}}\n\t) u_@$(PREFIX) (\n\t\t// {{{\n\t\t.i_clk(@$(SLAVE.BUS.CLOCK.WIRE)),\n\t\t.i_reset(@$(SLAVE.BUS.CLOCK.RESET)),\n\t\t// Primary memory reading inputs\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t// Configuration bus ports\n\t\t@$(flashcfg.SLAVE.ANSIPORTLIST),\n\t\t.o_qspi_sck(o_@$(PREFIX)_sck),\n\t\t.o_qspi_cs_n(o_@$(PREFIX)_cs_n),\n\t\t.o_qspi_mod(o_@$(PREFIX)_mod),\n\t\t.o_qspi_dat(o_@$(PREFIX)_dat),\n\t\t.i_qspi_dat(i_@$(PREFIX)_dat),\n\t\t.o_dbg_trigger(flash_dbg_trigger),\n\t\t.o_debug(flash_debug)\n\t\t// }}}\n\t);\n\t// }}}\n@MAIN.ALT=\n\tassign\to_@$(PREFIX)_sck  = 1'b1;\n\tassign\to_@$(PREFIX)_cs_n = 1'b1;\n\tassign\to_@$(PREFIX)_mod  = 2'b01;\n\tassign\to_@$(PREFIX)_dat  = 4'b1111;\n\t// Verilator lint_off UNUSED\n\twire\t@$(PREFIX)_unused = &{ 1'b0, i_@$(PREFIX)_dat };\n\t// Verilator lint_on UNUSED\n@MEM.NAME= flash\n@MEM.ACCESS = rx\n@REGS.N= 1\n@REGDEFS.H.DEFNS=\n#define\t@$(DEVID)BASE\t@$[0x%08x](REGBASE)\n#define\t@$(DEVID)LEN\t@$NBYTES\n#define\t@$(DEVID)LGLEN\t@$LGFLASHSZ\n//\n#define\tFLASH_RDDELAY\t@$(RDDELAY)\n#define\tFLASH_NDUMMY\t@$(NDUMMY)\n//\n@REGS.0= 0 R_@$(DEVID) @$(DEVID)\n@BDEF.OSDEF=_BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL=extern int _@$(PREFIX)[1];\n@LD.PERM=\trx\n@LD.NAME=\t@$(PREFIX)\n@SIM.CLOCK=clk\n@SIM.INCLUDE=\n#include \"flashsim.h\"\n@SIM.DEFNS=\n#ifdef\t@$(ACCESS)\n\tFLASHSIM\t*m_@$(MEM.NAME);\n#endif // @$(ACCESS)\n@SIM.INIT=\n#ifdef\t@$(ACCESS)\n\t\tm_@$(MEM.NAME) = new FLASHSIM(FLASHLGLEN, false, @$RDDELAY, @$NDUMMY);\n#endif // @$(ACCESS)\n@SIM.TICK=\n#ifdef\t@$(ACCESS)\n\t\tm_core->i_@$(PREFIX)_dat = m_@$(MEM.NAME)->simtick(\n\t\t\tm_core->o_@$(PREFIX)_cs_n,\n\t\t\tm_core->o_@$(PREFIX)_sck,\n\t\t\tm_core->o_@$(PREFIX)_dat,\n\t\t\tm_core->o_@$(PREFIX)_mod);\n#endif // @$(ACCESS)\n@SIM.LOAD=\n\t\t\tm_@$(MEM.NAME)->load(start, &buf[offset], wlen);\n@PREFIX=crossflash\n@INCLUDEFILE=crossbus.txt\n@MASTER.BUS=wbflash\n"
  },
  {
    "path": "auto-data/flashcfg.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/flashcfg.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tDescribes the configuration interface of the flash in our new\n##\t\tdata format.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=flashcfg\n@NADDR=1\n@DEVID=FLASHCFG\n@ACCESS=@$(DEVID)_ACCESS\n@DEPENDS= FLASH_ACCESS\n## Although this is really a SLAVE.TYPE=SINGLE interface, it receives its\n## acknowledgements from the flash above.  SLAVE.TYPE=SINGLE will create\n## acknowledgements in the interconnect, resulting in bus errors.  As a result,\n## this must be a SLAVE.TYPE=OTHER\n##\n@SLAVE.TYPE=OTHER\n@SLAVE.BUS=wb32\n@SLAVE.ANSPREFIX=cfg_\n@MAIN.INSERT=\n\t// The Flash control interface is defined by the flash instantiation\n\t// hence we don't need to do anything to define it here.\n@REGS.NOTE= // FLASH erase/program configuration registers\n@REGS.N= 1\n@REGS.0= 0 R_@$(DEVID) @$(DEVID) QSPIC\n@REGDEFS.H.INSERT=\n// Flash control constants\n#define\tQSPI_FLASH\t// This core and hardware support a Quad SPI flash\n#define\tSZPAGEB\t\t256\n#define\tPGLENB\t\t256\n#define\tSZPAGEW\t\t64\n#define\tPGLENW\t\t64\n#define\tNPAGES\t\t256\n#define\tSECTORSZB\t(NPAGES * SZPAGEB)\t// In bytes, not words!!\n#define\tSECTORSZW\t(NPAGES * SZPAGEW)\t// In words\n#define\tNSECTORS\t64\n#define\tSECTOROF(A)\t((A) & (-1<<16))\n#define\tSUBSECTOROF(A)\t((A) & (-1<<12))\n#define\tPAGEOF(A)\t((A) & (-1<<8))\n\n@BDEF.IONAME= _@$(PREFIX)\n@BDEF.OSDEF= _BOARD_HAS_@$(DEVID)\n@BDEF.IOTYPE=unsigned\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) * const @$(BDEF.IONAME) = ((@$BDEF.IOTYPE *)(@$[0x%08x](REGBASE)));\n##\n@RTL.MAKE.GROUP= FLASH\n@RTL.MAKE.SUBD=\n@RTL.MAKE.FILES= qflexpress.v\n"
  },
  {
    "path": "auto-data/global.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/global.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tCapture any global configuration parameters\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2015-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@LEGAL=../auto-data/legalgen.txt\n@PROJECT=AutoFPGA, a utility for composing FPGA designs from peripherals\n#\n# @KEYS.TRIMLIST is a list of all string keys that need to be trimmed (have\n# spaces removed from either side) before being used\n# @KEYS.INTLIST is a list of all things that need to be converted to integers\n@KEYS.INTLIST= BUS_ADDRESS_WIDTH NADDR NPIC NSCOPES PIC.MAX REGS.N ID\n@DEFAULT.BUS=wbwide\n@$RESET_ADDRESS=@$flash.REGBASE+(@$flash.NADDR)\n@RESET_ADDRESS.FORMAT=32'h%08x\n@REGISTER.BUS=wbu\n@VERILATOR_PREFIX=v\n@REGDEFS.H.INSERT=\ntypedef\tstruct {\n\tunsigned\tm_addr;\n\tconst char\t*m_name;\n} REGNAME;\n\nextern\tconst\tREGNAME\t*bregs;\nextern\tconst\tint\tNREGS;\n// #define\tNREGS\t(sizeof(bregs)/sizeof(bregs[0]))\n\nextern\tunsigned\taddrdecode(const char *v);\nextern\tconst\tchar *addrname(const unsigned v);\n@REGDEFS.CPP.INCLUDE=\n#include <stdio.h>\n#include <stdlib.h>\n#include <strings.h>\n#include <ctype.h>\n@REGDEFS.CPP.INSERT=\n#define\tRAW_NREGS\t(sizeof(raw_bregs)/sizeof(bregs[0]))\n\nconst\tREGNAME\t\t*bregs = raw_bregs;\nconst\tint\tNREGS = RAW_NREGS;\n\nunsigned\taddrdecode(const char *v) {\n\tif (isalpha(v[0])) {\n\t\tfor(int i=0; i<NREGS; i++)\n\t\t\tif (strcasecmp(v, bregs[i].m_name)==0)\n\t\t\t\treturn bregs[i].m_addr;\n\t\tfprintf(stderr, \"Unknown register: %s\\n\", v);\n\t\texit(-2);\n\t} else\n\t\treturn strtoul(v, NULL, 0);\n}\n\nconst\tchar *addrname(const unsigned v) {\n\tfor(int i=0; i<NREGS; i++)\n\t\tif (bregs[i].m_addr == v)\n\t\t\treturn bregs[i].m_name;\n\treturn NULL;\n}\n\n@SIM.INCLUDE=\n#include \"verilated.h\"\n#include \"Vmain.h\"\n#define\tBASECLASS\tVmain\n\n#include \"design.h\"\n#include \"regdefs.h\"\n#include \"testb.h\"\n@PREFIX=wb32\n@BUS.NAME=wb32\n@BUS.TYPE=wb\n@$BUS.WIDTH=32\n@BUS.CLOCK=clk\n@$BUS.NULLSZ=0x400\n@PREFIX=wbwide\n@BUS.NAME=wbwide\n@BUS.WIDTH=128\n@BUS.CLOCK=clk\n@BUS.TYPE=wb\n@BUS.RESET=i_reset\n"
  },
  {
    "path": "auto-data/gpio.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/gpio.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\t\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=gpio\n@DEVID=GPIO\n@NADDR=1\n@ACCESS=@$(DEVID)_ACCESS\n@SLAVE.TYPE=SINGLE\n@SLAVE.BUS=wb32\n@NUMOUTPUT=10\n@NUMINPUT=8\n@INT.GPIO.WIRE=gpio_int\n@INT.GPIO.PIC=syspic\n@TOP.PORTLIST=\n\t\t// @$(DEVID) ports\n\t\to_hdmirx_hpa,\t// Hotplug assert\n\t\to_hdmirx_txen,\n\t\ti_hdmitx_hpd_n, // Hotplug detect\n\t\to_sd_reset,\n\t\ti_gps_3df,\n\t\to_oled_reset_n, o_oled_panel_en, o_oled_logic_en\n@TOP.IODECL=\n\t// @$(DEVID) ports\n\toutput\twire\to_hdmirx_hpa;\n\toutput\twire\to_hdmirx_txen;\n\tinput\twire\ti_hdmitx_hpd_n;\t\t// Hotplug detect\n\toutput\twire\to_sd_reset;\n\tinput\twire\ti_gps_3df;\n\toutput\twire\to_oled_reset_n, o_oled_panel_en, o_oled_logic_en;\n@TOP.DEFNS=\n\t// @$(DEVID) declarations.  The two wire busses are just virtual lists\n\t// of input (or output) ports.\n\twire\t[@$(NUMINPUT)-1:0]\ti_@$(PREFIX);\n\t// Verilator lint_off UNUSED\n\t// Two of our outputs, o_trace and o_halt, will be unused at the top\n\t// level.\n\twire\t[@$(NUMOUTPUT)-1:0]\to_@$(PREFIX);\n\t// Verilator lint_on  UNUSED\n@TOP.MAIN=\n\t\t// @$(DEVID) wires\n\t\ti_@$(PREFIX), o_@$(PREFIX)\n@TOP.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// GPIO adjustments\n\t// {{{\n\tassign\ti_@$(PREFIX) = { 8'h0,\n\t\t\tpxrx_locked,\n\t\t\tsysclk_locked,\n`ifdef\tGPSTRK_ACCESS\n\t\t\ti_gps_3df,\n`else\n\t\t\t1'b0,\n`endif\n\t\t\t!i_hdmitx_hpd_n,\t// Hotplug detect\n\t\t\t!i_sd_cd_n,\n\t\t\t1'b0,\n\t\t\ti_hdmitx_cec, i_hdmirx_cec };\n\tassign\to_hdmirx_txen = o_gpio[2];\n\tassign\to_hdmirx_hpa  = o_gpio[3];\t// Hotplug assert\n\tassign\to_sd_reset  = !w_sdio_hwreset_n;\n\tassign\to_oled_reset_n  = !o_gpio[5];\n\tassign\to_oled_panel_en =  o_gpio[6];\n\tassign\to_oled_logic_en =  o_gpio[7];\n\t// These two pins are only used in simulation, and only within the\n\t// MAIN RTL component.\n\t// assign o_trace     = o_gpio[8];\n\t// assign o_halt      = o_gpio[9];\n\n\t// }}}\n@MAIN.PORTLIST=\n\t\t// @$(DEVID) ports\n`ifdef\tVERILATOR\n\t\to_trace, o_halt,\n`endif\n\t\ti_@$(PREFIX), o_@$(PREFIX)\n@MAIN.IODECL=\n\tlocalparam\tNGPI = @$(NUMINPUT), NGPO=@$(NUMOUTPUT);\n\t// @$(DEVID) ports\n`ifdef\tVERILATOR\n\toutput\twire\t\t\to_trace;\n\toutput\twire\t\t\to_halt;\n`endif\n\tinput\t\t[(NGPI-1):0]\ti_@$(PREFIX);\n\toutput\twire\t[(NGPO-1):0]\to_@$(PREFIX);\n@MAIN.DEFNS=\n\twire\tsd_reset;\n@MAIN.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// @$(DEVID)\n\t// {{{\n\t// This interface should allow us to control up to 16 @$(DEVID) inputs,\n\t// and another 16 @$(DEVID) outputs.  The interrupt trips when any of\n\t// the inputs changes.  (Sorry, which input isn't (yet) selectable.)\n\t//\n\tlocalparam [NGPO-1:0]\tINITIAL_@$(DEVID) = @$(NUMOUTPUT)'h13;\n\n\twbgpio\t#(\n\t\t.NIN(NGPI), .NOUT(NGPO), .DEFAULT(INITIAL_@$(DEVID))\n\t) u_@$(PREFIX) (\n\t\t// {{{\n\t\t.i_clk(i_clk),\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t.i_gpio(i_@$(PREFIX)), .o_gpio(o_@$(PREFIX)),\n\t\t.o_int(@$(PREFIX)_int)\n\t\t// }}}\n\t);\n\n`ifdef\tSDIO_ACCESS\n\t// This bit is used by the SDSPI controller, not the SDIO controller.\n\tassign\tsd_reset = !o_sdio_hwreset_n;\n`else\n\tassign\tsd_reset = o_@$(PREFIX)[3];\n`endif\n\n`ifdef\tVERILATOR\n\twire\tverilator_halt;\n\tassign\to_trace = o_@$(PREFIX)[8];\n\n\tassign\tverilator_halt = o_@$(PREFIX)[9];\n\tassign\to_halt = verilator_halt;\n\talways @(posedge verilator_halt)\n\t\t$finish;\n`endif\n\t// }}}\n@REGS.N=1\n@REGS.0= 0 R_@$(DEVID) @$(DEVID) GPI GPO\n@BDEF.DEFN=\n//\n// @$(DEVID) input wires\n//\n#define\tGPIO_HDMIRX_CEC\t\t0x000010000\n#define\tGPIO_HDMITX_CEC\t\t0x000020000\n#define\tGPIO_SD_DETECTED\t0x000080000\n#define\tGPIO_HDMITX_DETECT\t0x000100000\n#define\tGPIO_GPS_3DF\t\t0x000200000\n#define\tGPIO_SYSCLK_LOCKED\t0x000400000\n#define\tGPIO_VIDCLK_LOCKED\t0x000800000\n//\n// @$(DEVID) output wires\n//\n#define\t@$(DEVID)_SET(WIRE)\t(((WIRE)<<16)|(WIRE))\n#define\t@$(DEVID)_CLR(WIRE)\t ((WIRE)<<16)\n//\n#define\tGPIO_HDMIRX_CEC_SET\t0x000010001\n#define\tGPIO_HDMIRX_CEC_CLR\t0x000010000\n#define\tGPIO_HDMITX_CEC_SET\t0x000020002\n#define\tGPIO_HDMITX_CEC_CLR\t0x000020000\n//\n#define\tGPIO_HDMIRX_TXEN\t0x000000004\n#define\tGPIO_HDMIRX_HPA\t\t0x000000008\n#define\tGPIO_SD_RESET\t\t0x000000010\n#define\tGPIO_OLED_RESET\t\t0x000000020\n#define\tGPIO_OLED_PANELEN\t0x000000040\n#define\tGPIO_OLED_LOGICEN\t0x000000080\n#define\tGPIO_TRACE\t\t0x000000100\n#define\tGPIO_TESTHALT\t\t0x000000200\n//\n#define\tGPIO_EDID_SCL_SET\tGPIO_SET(GPIO_EDID_SCL)\n#define\tGPIO_EDID_SCL_CLR\tGPIO_CLR(GPIO_EDID_SCL)\n#define\tGPIO_EDID_SDA_SET\tGPIO_SET(GPIO_EDID_SDA)\n#define\tGPIO_EDID_SDA_CLR\tGPIO_CLR(GPIO_EDID_SDA)\n#define\tGPIO_HDMIRX_HPA_SET\tGPIO_SET(GPIO_HDMIRX_HPA)\n#define\tGPIO_HDMIRX_HPA_CLR\tGPIO_CLR(GPIO_HDMIRX_HPA)\n#define\tGPIO_SD_RESET_SET\tGPIO_SET(GPIO_SD_RESET)\n#define\tGPIO_SD_RESET_CLR\tGPIO_CLR(GPIO_SD_RESET)\n#define\tGPIO_HDMIRX_TXEN_SET\tGPIO_SET(GPIO_HDMIRX_TXEN)\n#define\tGPIO_HDMIRX_TXEN_CLR\tGPIO_CLR(GPIO_HDMIRX_TXEN)\n#define\tOLED_RESET\t\tGPIO_SET(GPIO_OLED_RESET)\n#define\tOLED_RUN\t\tGPIO_CLR(GPIO_OLED_RESET)\n#define\tOLED_PANELEN\t\tGPIO_SET(GPIO_OLED_PANELEN)\n#define\tOLED_PANELDIS\t\tGPIO_CLR(GPIO_OLED_PANELEN)\n#define\tOLED_LOGICEN\t\tGPIO_SET(GPIO_OLED_LOGICEN)\n#define\tOLED_LOGICDIS\t\tGPIO_CLR(GPIO_OLED_LOGICEN)\n#define\tGPIO_TRACE_SET\t\tGPIO_SET(GPIO_TRACE)\n#define\tGPIO_TRACE_CLR\t\tGPIO_CLR(GPIO_TRACE)\n#define\tGPIO_HALT_SET\t\tGPIO_SET(GPIO_TESTHALT)\n#define\tGPIO_HALT_CLR\t\tGPIO_CLR(GPIO_TESTHALT)\n@BDEF.IONAME=\ti_@$(PREFIX)\n@BDEF.IOTYPE=\tunsigned\n@BDEF.OSDEF=\t_BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL=\tstatic volatile @$(BDEF.IOTYPE) *const _@$(PREFIX) = ((@$(BDEF.IOTYPE) *)@$[0x%08x](REGBASE));\n@RTL.MAKE.FILES=wbgpio.v\n@RTL.MAKE.GROUP=@$(DEVID)\n"
  },
  {
    "path": "auto-data/gps.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/gps.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tThis file describes the three interfaces created by the GPS:\n##\t\t1) a GPS-locked clock, 2) a \"testbench\" which is used to\n##\tmeasure the performance of the GPS-locked lock, and 3) a wishbone\n##\tcontrolled UART which can be used to read from the UART stream coming\n##\tfrom the GPS.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@$GPSPORT_OFFSET=2\n@PREFIX=gck\n@DEVID=GPSTRK\n@ACCESS=@$(DEVID)_ACCESS\n@NADDR=4\n@SLAVE.TYPE=DOUBLE\n@SLAVE.BUS=wb32\n@CLOCK.NAME=clk\n@$CLKFREQHZ=@$(CLOCK.FREQUENCY)\n@$GPS_STEP_EXPONENT=10\n@$GPS_STEP=((((1<<60)/@$CLKFREQHZ)>>(@$.GPS_STEP_EXPONENT-4))&0x0fffffff)|((@$.GPS_STEP_EXPONENT&0x0f)<<28)\n@GPS_STEP.FORMAT=32'h%08x\n@MAIN.PORTLIST=\n\t\t// The GPS 1PPS signal port\n\t\ti_gps_pps\n@MAIN.PARAM=\n\tlocalparam [31:0] GPSCLOCK_DEFAULT_STEP = @$.GPS_STEP;\n@MAIN.IODECL=\n\t//The GPS Clock\n\tinput\twire\t\ti_gps_pps;\n@MAIN.DEFNS=\n\twire\t\tck_pps;\n\twire\t\tgps_pps, gps_led, gps_locked, gps_tracking;\n\twire\t[63:0]\tgps_now, gps_err, gps_step;\n\twire\t[1:0]\tgps_dbg_tick;\n@MAIN.INSERT=\n\t// Verilator lint_off UNUSED\n\twire\t[1:0]\tck_dbg;\n\t// Verilator lint_on  UNUSED\n\n\tgpsclock #(\n\t\t.DEFAULT_STEP(GPSCLOCK_DEFAULT_STEP)\n\t) ppsck (\n\t\t.i_clk(i_clk), .i_rst(1'b0), .i_pps(gps_pps), .o_pps(ck_pps),\n\t\t\t.o_led(gps_led),\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t.o_tracking(gps_tracking), .o_count(gps_now), .o_step(gps_step),\n\t\t.o_err(gps_err), .o_locked(gps_locked), .o_dbg(ck_dbg)\n\t);\n\n\tassign\t@$(PREFIX)_pps = ck_pps;\n\n@MAIN.ALT=\n\treg\t\tr_ck_pps;\n\treg\t[63:0]\tr_gps_now;\n\treg\t[31:0]\tr_gps_prior;\n\twire\t[47:0]\tpre_step;\n\tassign\tpre_step = { 16'h00, (({GPSCLOCK_DEFAULT_STEP[27:0],20'h00})\n\t\t\t\t>>GPSCLOCK_DEFAULT_STEP[31:28]) };\n\n\tinitial\t{ r_ck_pps, r_gps_prior } = 33'h0;\n\talways @(posedge i_clk)\n\t\t{ r_ck_pps, r_gps_prior[31:0] } <= r_gps_prior + pre_step[31:0];\n\n\tinitial\tr_gps_now = 64'h0;\n\talways @(posedge i_clk)\n\tbegin\n\t\tr_gps_now[63:32] <= r_gps_now[63:32]+(r_ck_pps ? 32'h1:32'h0);\n\t\tr_gps_now[31:0]  <= r_gps_prior;\n\tend\n\tassign\tck_pps     = r_ck_pps;\n\tassign\tgps_now    = r_gps_now;\n\tassign\tgps_err    = 64'h0;\n\tassign\tgps_step   = pre_step;\n\tassign\tgps_led    = 1'b0;\n\tassign\tgps_locked = 1'b0;\n\n@INT.PPS.WIRE=@$(PREFIX)_pps\n@INT.PPS.PIC=syspic\n@REGS.NOTE= // GPS clock tracker, control loop settings registers\n@REGS.N=4\n@REGS.0= 0 R_GPS_ALPHA\tALPHA\n@REGS.1= 1 R_GPS_BETA\tBETA\n@REGS.2= 2 R_GPS_GAMMA\tGAMMA\n@REGS.3= 3 R_GPS_STEP\tSTEP\n@BDEF.DEFN=\ntypedef\tstruct\tGPSTRACKER_S\t{\n\tunsigned\tg_alpha, g_beta, g_gamma, g_step;\n} GPSTRACKER;\n@BDEF.INSERT=\n#define\tSYSINT_PPS\tSYSINT(@$(INT.PPS.syspic.ID))\n@BDEF.IONAME=_gps\n@BDEF.IOTYPE= GPSTRACKER\n@BDEF.OSVAL=\nstatic volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$BDEF.IOTYPE *)@$[0x%08x](REGBASE));\n##\n##\n##\n@PREFIX=gtb\n@NADDR=8\n@DEPENDS=GPSTRK_ACCESS\n@SLAVE.TYPE=DOUBLE\n@SLAVE.BUS=wb32\n@CLOCK.NAME=clk\n@MAIN.DEFNS=\n\twire\ttb_pps;\n@MAIN.INSERT=\n\t// Generate a PPS signal independent of the GPS--useful for testing\n\tgpsclock_tb #(\n\t\t.CLOCK_FREQUENCY_HZ(@$(CLOCK.FREQUENCY))\n\t) ppstb(\n\t\t.i_clk(i_clk), .i_lcl_pps(ck_pps), .o_pps(tb_pps),\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t.i_err(gps_err), .i_count(gps_now), .i_step(gps_step)\n\t);\n\n\tassign\tgps_pps = tb_pps;\n@MAIN.ALT=\n\tassign\tgps_pps = i_gps_pps;\n\n@REGS.NOTE= // GPS clock test bench registers, for measuring the clock trackers performance\n@REGS.N=8\n@REGS.0=  0 R_GPSTB_FREQ    GPSFREQ\n@REGS.1=  1 R_GPSTB_JUMP    GPSJUMP\n@REGS.2=  2 R_GPSTB_ERRHI   ERRHI\n@REGS.3=  3 R_GPSTB_ERRLO   ERRLO\n@REGS.4=  4 R_GPSTB_COUNTHI CNTHI\n@REGS.5=  5 R_GPSTB_COUNTLO CNTLO\n@REGS.6=  6 R_GPSTB_STEPHI  STEPHI\n@REGS.7=  7 R_GPSTB_STEPLO  STEPLO\n@BDEF.DEFN=\ntypedef\tstruct\tGPSTB_S\t{\n\tunsigned\ttb_maxcount, tb_jump;\n\tunsigned long\ttb_err, tb_count, tb_step;\n} GPSTB;\n@BDEF.IONAME=_gpstb\n@BDEF.IOTYPE=GPSTB\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$(BDEF.IOTYPE) *)@$[0x%08x](REGBASE));\n#\n#\n#\n@PREFIX=gpsu\n@INCLUDEFILE=wbuart.txt\n@$BAUDRATE=9600\n@CLOCK.NAME=clk\n@$UARTSETUP=@$(CLOCK.FREQUENCY)/@$(BAUDRATE)\n@ACCESS=GPSUART_ACCESS\n@INT.INTLIST= GPSRX GPSTX GPSRXF GPSTXF\n@INT.GPSRX.WIRE=  gpsurx_int\n@INT.GPSTX.WIRE=  gpsutx_int\n@INT.GPSRXF.WIRE= gpsurxf_int\n@INT.GPSTXF.WIRE= gpsutxf_int\n@INT.GPSRX.PIC=  altpic\n@INT.GPSTX.PIC=  altpic\n@INT.GPSRXF.PIC= altpic\n@INT.GPSTXF.PIC= altpic\n# Clear the other inherited wires, as we don't need them any more.\n@INT.UARTRX.WIRE=\n@INT.UARTTX.WIRE=\n@INT.UARTRXF.WIRE=\n@INT.UARTTXF.WIRE=\n@INT.UARTRX.PIC=\n@INT.UARTTX.PIC=\n@INT.UARTRXF.PIC=\n@INT.UARTTXF.PIC=\n@BDEF.INSERT=\n#define\tSYSINT_GPSRXF\tALTINT(@$(INT.GPSRXF.syspic.ID))\n#define\tSYSINT_GPSTXF\tALTINT(@$(INT.GPSTXF.altpic.ID))\n#define\tSYSINT_GPSRX\tALTINT(@$(INT.GPSRX.altpic.ID))\n#define\tSYSINT_GPSTX\tALTINT(@$(INT.GPSTX.altpic.ID))\n@TOP.PORTLIST=\n\t\t// The GPS-UART\n\t\ti_@$(PREFIX)_rx, o_@$(PREFIX)_tx\n@MAIN.PORTLIST=\n\t\t// The GPS-UART\n\t\ti_@$(PREFIX)_rx, o_@$(PREFIX)_tx\n@MAIN.IODECL=\n\tinput\twire\t\ti_@$(PREFIX)_rx;\n\toutput\twire\t\to_@$(PREFIX)_tx;\n@MAIN.DEFNS=\n\twire\tw_@$(PREFIX)_cts_n, w_@$(PREFIX)_rts_n;\n\tassign\tw_@$(PREFIX)_cts_n=1'b1;\n@RTS=w_@$(PREFIX)_rts_n\n@CTS=w_@$(PREFIX)_cts_n\n@REGS.NOTE= // GPS UART registers, similar to WBUART\n@REGS.N=4\n@REGS.0= 0 R_GPSU_SETUP  GPSSETUP\n@REGS.1= 1 R_GPSU_FIFO   GPSFIFO\n@REGS.2= 2 R_GPSU_UARTRX GPSRX\n@REGS.3= 3 R_GPSU_UARTTX GPSTX\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.OSDEF=_BOARD_HAS_GPS_UART\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$(BDEF.IOTYPE) *)(@$[0x%08x](REGBASE)));\n@$SIM.PORTOFFSET=@/GPSPORT_OFFSET\n@SIM.INIT=\n#ifdef\t@$(ACCESS)\n\t\tm_@$(PREFIX) = new UARTSIM(FPGAPORT+@$(SIM.PORTOFFSET));\n\t\tm_@$(PREFIX)->setup(@$[0x%08x](UARTSETUP));\n#endif // @$(ACCESS)\n#\n@RTL.MAKE.GROUP=GPS\n@RTL.MAKE.FILES=gpsclock_tb.v gpsclock.v bigadd.v bigsub.v bigsmpy.v\n"
  },
  {
    "path": "auto-data/hdmi.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/hdmi.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tTo direct the build of the autofpga automatically generated\n##\t\tfiles.  The various configuration files are the *.txt files\n##\tfound in this directory.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=hdmi\n@DEVID=VIDPIPE\n@ACCESS=@$(DEVID)_ACCESS\n@NADDR=1024\n@SLAVE.BUS=wb32\n@SLAVE.TYPE=OTHER\n@MASTER.BUS=wbwide\n@MASTER.TYPE=DMA\n@MASTER.ANSPREFIX=dma_\n@INT.VIDFRAME.WIRE=@$(PREFIX)_int\n@INT.VIDFRAME.PIC=syspic\n@TOP.PORTLIST=\n\t\ti_hdmirx_clk_p, i_hdmirx_clk_n,\n\t\ti_hdmirx_p, i_hdmirx_n,\n\t\to_hdmitx_clk_p, o_hdmitx_clk_n,\n\t\to_hdmitx_p, o_hdmitx_n\n@TOP.IODECL=\n\tinput\twire\t\ti_hdmirx_clk_p, i_hdmirx_clk_n;\n\tinput\twire\t[2:0]\ti_hdmirx_p, i_hdmirx_n;\n\toutput\twire\t\to_hdmitx_clk_p, o_hdmitx_clk_n;\n\toutput\twire\t[2:0]\to_hdmitx_p, o_hdmitx_n;\n@TOP.DEFNS=\n\twire\t[9:0]\thdmirx_red, hdmirx_grn, hdmirx_blu;\n\twire\t[9:0]\thdmitx_red, hdmitx_grn, hdmitx_blu;\n\twire\t[1:0]\tw_pxclk_cksel;\n\twire\t\thdmirx_clk, hdmi_ck, hdmi_serdes_clk;\n\twire\t\tpxrx_locked, pix_reset_n, hdmirx_reset_n;\n\twire [15-1:0]\tset_hdmi_delay, actual_hdmi_delay;\n@TOP.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// HDMI\n\t// {{{\n\n\t// Ingest the HDMI data lines\n\t// {{{\n\txhdmiin\n\tu_hdmirx_red(\n\t\t.i_clk(hdmi_ck), .i_hsclk(hdmi_serdes_clk),\n\t\t.i_reset_n(hdmirx_reset_n),\n\t\t.i_delay(set_hdmi_delay[14:10]),\n\t\t.o_delay(actual_hdmi_delay[14:10]),\n\t\t.i_hs_wire({ i_hdmirx_p[2], i_hdmirx_n[2] }),\n\t\t.o_word(hdmirx_red)\n\t);\n\n\txhdmiin\n\tu_hdmirx_grn(\n\t\t.i_clk(hdmi_ck), .i_hsclk(hdmi_serdes_clk),\n\t\t.i_reset_n(hdmirx_reset_n),\n\t\t.i_delay(set_hdmi_delay[9:5]),\n\t\t.o_delay(actual_hdmi_delay[9:5]),\n\t\t.i_hs_wire({ i_hdmirx_p[1], i_hdmirx_n[1] }),\n\t\t.o_word(hdmirx_grn)\n\t);\n\n\txhdmiin\n\tu_hdmirx_blu(\n\t\t.i_clk(hdmi_ck), .i_hsclk(hdmi_serdes_clk),\n\t\t.i_reset_n(hdmirx_reset_n),\n\t\t.i_delay(set_hdmi_delay[4:0]),\n\t\t.o_delay(actual_hdmi_delay[4:0]),\n\t\t.i_hs_wire({ i_hdmirx_p[0], i_hdmirx_n[0] }),\n\t\t.o_word(hdmirx_blu)\n\t);\n\t// }}}\n\n\t// Output the HDMI TX data lines\n\t// {{{\n\txhdmiout\n\tu_hdmitx_clk(\n\t\t.i_clk(hdmi_ck), .i_hsclk(hdmi_serdes_clk),\n\t\t.i_reset_n(pix_reset_n), .i_en(1'b1),\n\t\t.i_word(10'b11111_00000),\n\t\t.o_port({ o_hdmitx_clk_p, o_hdmitx_clk_n })\n\t);\n\n\txhdmiout\n\tu_hdmitx_red(\n\t\t.i_clk(hdmi_ck), .i_hsclk(hdmi_serdes_clk),\n\t\t.i_reset_n(pix_reset_n), .i_en(1'b1),\n\t\t.i_word(hdmitx_red),\n\t\t.o_port({ o_hdmitx_p[2], o_hdmitx_n[2] })\n\t);\n\n\txhdmiout\n\tu_hdmitx_grn(\n\t\t.i_clk(hdmi_ck), .i_hsclk(hdmi_serdes_clk),\n\t\t.i_reset_n(pix_reset_n), .i_en(1'b1),\n\t\t.i_word(hdmitx_grn),\n\t\t.o_port({ o_hdmitx_p[1], o_hdmitx_n[1] })\n\t);\n\n\txhdmiout\n\tu_hdmitx_blu(\n\t\t.i_clk(hdmi_ck), .i_hsclk(hdmi_serdes_clk),\n\t\t.i_reset_n(pix_reset_n), .i_en(1'b1),\n\t\t.i_word(hdmitx_blu),\n\t\t.o_port({ o_hdmitx_p[0], o_hdmitx_n[0] })\n\t);\n\t// }}}\n\n\t// }}}\n@TOP.MAIN=\n\t\t// HDMI control ports\n\t\thdmirx_clk, hdmi_ck,\t// Depending on s_siclk\n\t\thdmirx_red, hdmirx_grn, hdmirx_blu,\n\t\thdmitx_red, hdmitx_grn, hdmitx_blu,\n\t\tset_hdmi_delay, actual_hdmi_delay,\n\t\tpix_reset_n, pxrx_locked, hdmirx_reset_n,\n\t\tw_pxclk_cksel\n@MAIN.PORTLIST=\n\t\t// HDMI control ports\n`ifndef\tVERILATOR\n\t\ti_hdmiclk,\n`endif\n\t\ti_pixclk,\n\t\ti_hdmi_red, i_hdmi_grn, i_hdmi_blu,\n\t\to_hdmi_red, o_hdmi_grn, o_hdmi_blu,\n\t\to_hdmi_iodelay, i_hdmi_iodelay,\n\t\to_pix_reset_n, i_pxpll_locked, o_hdmirx_reset_n,\n\t\to_pxclk_cksel\n@MAIN.IODECL=\n\t// @$(PREFIX) declarations\n\t// {{{\n`ifndef\tVERILATOR\n\tinput\twire\t\ti_hdmiclk;\n`endif\n\tinput\twire\t\ti_pixclk;\n\tinput\twire\t[9:0]\ti_hdmi_red, i_hdmi_grn, i_hdmi_blu;\n\toutput\twire\t[9:0]\to_hdmi_red, o_hdmi_grn, o_hdmi_blu;\n\toutput\twire\t[14:0]\to_hdmi_iodelay;\n\tinput\twire\t[14:0]\ti_hdmi_iodelay;\n\toutput\twire\t\to_pix_reset_n, o_hdmirx_reset_n;\n\tinput\twire\t\ti_pxpll_locked;\n\toutput\twire\t[1:0]\to_pxclk_cksel;\n\t// }}}\n@MAIN.DEFNS=\n\t// Verilator lint_off UNUSED\n`ifdef\tVERILATOR\n\twire\t\ti_hdmiclk;\n`endif\n\twire\t\thdmidbg_ce, hdmidbg_trigger;\n\twire\t[31:0]\thdmiclr_debug;\n\t// Verilator lint_on  UNUSED\n@MAIN.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// HDMI Video processing pipeline\n\t// {{{\n`ifdef\tVERILATOR\n\tassign\ti_hdmiclk = i_pixclk;\n`endif\n\n\tvidpipe #(\n\t\t.AW(@$(MASTER.BUS.AWID)),\n\t\t.DW(@$(MASTER.BUS.WIDTH))\n\t) u_@$(PREFIX) (\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t.i_hdmiclk(i_hdmiclk),\n\t\t.i_altclk(i_pixclk),\n\t\t.i_pixclk(i_pixclk),\n\t\t.i_hdmi_red(i_hdmi_red), .i_hdmi_grn(i_hdmi_grn),\n\t\t\t\t.i_hdmi_blu(i_hdmi_blu),\n\t\t@$(MASTER.ANSIPORTLIST),\n\t\t.o_hdmi_red(o_hdmi_red), .o_hdmi_grn(o_hdmi_grn),\n\t\t\t\t.o_hdmi_blu(o_hdmi_blu),\n\t\t.o_pix_reset_n(o_pix_reset_n),\n\t\t.i_pxpll_locked(i_pxpll_locked),\n\t\t.o_hdmirx_reset_n(o_hdmirx_reset_n),\n\t\t.o_pxclk_sel(o_pxclk_cksel),\n\t\t.o_iodelay(o_hdmi_iodelay),\n\t\t.i_iodelay(i_hdmi_iodelay),\n\t\t.o_interrupt(@$(INT.VIDFRAME.WIRE)),\n\t\t//\n\t\t.o_dbg_ce(hdmidbg_ce),\n\t\t.o_dbg_trigger(hdmidbg_trigger),\n\t\t.o_pixdebug(hdmiclr_debug)\n\t);\n\n\t// }}}\n@REGS.NOTE=// HDMI video processing pipe registers\n@REGS.N=23\n@REGS.0=   0  R_@$(DEVID) @$(DEVID) VIDCTRL\n@REGS.1=   1  R_HDMIFREQ  HDMIFREQ\n@REGS.2=   2  R_SIFREQ    SIFREQ\n@REGS.3=   3  R_PXFREQ    PXFREQ\n@REGS.4=   4  R_INSIZE    INSIZE\n@REGS.5=   5  R_INPORCH   INPORCH\n@REGS.6=   6  R_INSYNC    INSYNC\n@REGS.7=   7  R_INRAW     INRAW\n@REGS.8=   8  R_HDMISIZE  HDMISIZE\n@REGS.9=   9  R_HDMIPORCH HDMIPORCH\n@REGS.10= 10  R_HDMISYNC  HDMISYNC\n@REGS.11= 11  R_HDMIRAW   HDMIRAW\n@REGS.12= 12  R_OVADDR    OVADDR\n@REGS.13= 13  R_OVSIZE    OVSIZE\n@REGS.14= 14  R_OVOFFSET  OVOFFSET\n@REGS.15= 15  R_FPS       FPS\n@REGS.16= 16  R_CAPTURE   VCAPTURE\n@REGS.17= 17  R_CAPBASE   VCAPBASE\n@REGS.18= 18  R_CAPWORDS  VCAPWORDS\n@REGS.19= 19  R_CAPPOSN   VCAPPOSN\n@REGS.20= 20  R_CAPSIZE   VCAPSIZE\n@REGS.21= 24  R_SYNCWORD  VSYNCWORD\n@REGS.22=512  R_CMAP      CMAP\n@BDEF.INCLUDE=\n#include <stdint.h>\n@BDEF.DEFN=\n#ifndef @$(DEVID)_H\n#define @$(DEVID)_H\n\n#define\tVIDPIPE_RESET\t0x000001\n#define\tVIDPIPE_RXPLLCK\t0x000002\n#define\tVIDPIPE_LOCALCK\t0x000000\n#define\tVIDPIPE_RXCLOCK\t0x000020\n#define\tVIDPIPE_LCLSRC\t0x000000\n#define\tVIDPIPE_RXSRC\t0x000040\n#define\tVIDPIPE_RXSYNCD\t0x010000\n#define\tVIDPIPE_OVLYERR\t0x020000\n\n#define\tVIDCMAP_BW\t0x000000\n#define\tVIDCMAP_2GRAY\t0x000100\n#define\tVIDCMAP_4CMAP\t0x000200\n#define\tVIDCMAP_8CMAP\t0x000300\n#define\tVIDCMAP_8CLR\t0x000400\n#define\tVIDCMAP_16CLR\t0x000500\n#define\tVIDCMAP_24CLR\t0x000600\n#define\tVIDCMAP_32CLR\t0x000700\n\ntypedef struct __attribute__((packed)) VIDMODE_S {\n\tuint16_t\tm_height,     m_width;\n\tuint16_t\tm_vporch,     m_hporch;\n\tuint16_t\tm_vsync,      m_hsync;\n\tuint16_t\tm_raw_height, m_raw_width;\n} VIDMODE;\n\ntypedef struct __attribute__((packed)) @$(DEVID)_S {\n\tuint32_t\tv_control, v_hdmifreq, v_sifreq, v_pxfreq;\n\tVIDMODE\t\tv_in, v_src;\n\tconst char\t*v_overlay;\n\tuint16_t\tv_ovheight, v_ovwidth;\n\tuint16_t\tv_ovypos,  v_ovhpos;\n\tunsigned\tv_fps;\n\tuint32_t\tv_capture;\n\tconst char\t*v_capbase;\n\tuint32_t\tv_capwords, v_capposn, v_capsize;\n\tunsigned\tv_ovwords;\n\tunsigned\tv_unused2[2];\n\tunsigned\tv_syncword;\n\tuint32_t\tv_unused[512-25];\n\tuint32_t\tv_clrmap[256];\n} @$(DEVID);\n\n#endif // @$(DEVID)_H\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE=@$(DEVID)\n@BDEF.OSDEF=_BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$(BDEF.IOTYPE) *)@$[0x%08x](REGBASE));\n@RTL.MAKE.GROUP=HDMI\n@RTL.MAKE.SUBD=video\n@RTL.MAKE.FILES= axishdmi.v axisvoverlay.v hdmi2vga.v\n\t\thdmibitsync.v hdmipixelsync.v sync2stream.v synccount.v\n\t\ttfrstb.v tmdsdecode.v tmdsencode.v vid_empty.v\n\t\tvid_mux.v vidpipe.v vidstream2pix.v vid_wbframebuf.v\n\t\tvid_crop.v xhdmiin_deserdes.v xhdmiin.v xhdmiout.v xpxclk.v\n@CLOCK.NAME=pixclk\n@CLOCK.WIRE=i_pixclk\n@CLOCK.FREQUENCY=40000000\n@SIM.CLOCK=pixclk\n@SIM.INCLUDE=\n#include \"hdmisource.h\"\n#include \"hdmisim.h\"\n@SIM.DEFNS=\n#ifdef @$(ACCESS)\n\tHDMISOURCE\t*m_hdmirx;\n\tHDMIWIN\t\t*m_hdmitx;\n#endif\t// @$(ACCESS)\n@SIM.INIT=\n#ifdef\t@$(ACCESS)\n\t\tm_hdmirx = NULL;\n\t\tm_hdmitx = NULL;\n\t\tif (gbl_use_gui) {\n\t\t\tm_hdmirx = new HDMISOURCE(800, 600);\n\t\t\tm_hdmitx = new HDMIWIN(800, 600);\n\t\t}\n#endif\t// @$(ACCESS)\n@SIM.METHODS=\n\tvoid\tconnect_idler(void) {\n\t\tGlib::signal_idle().connect(\n\t\t\tsigc::mem_fun((*this),&MAINTB::on_tick));\n\t}\n\n\tbool\ton_tick(void) {\n\t\tfor(int i=0; i<15; i++)\n\t\t\ttick();\n\t\treturn true;\n\t}\n@SIM.TICK=\n#ifdef\t@$(ACCESS)\n\t\t// Simulate both an external HDMI source and monitor\n\t\tif (gbl_use_gui) {\n\t\t\tint\tr, g, b;\n\n\t\t\t// HDMI input received by the design\n\t\t\t(*m_hdmirx)(b, g, r);\n\t\t\tm_core->i_hdmi_blu = b;\n\t\t\tm_core->i_hdmi_grn = g;\n\t\t\tm_core->i_hdmi_red = r;\n\n\t\t\tm_core->i_pxpll_locked = 1;\n\n\t\t\t// HDMI output, transmitted from the design\n\t\t\t(*m_hdmitx)(m_core->o_hdmi_blu, m_core->o_hdmi_grn,\n\t\t\t\t\tm_core->o_hdmi_red);\n\t\t}\n#endif\t// @$(ACCESS)\n@XDC.INSERT=\n##\n## Can't (officially) go any faster than 119.05 MHz\n##\tYes, I know I've seen this board hit the 145 MHz required by 1080p, but Vivado's timing analyzer\n##\tsays we can't go that fast.\ncreate_clock -period 10.8 -name PXCLK -waveform { 0.0 5.4 } -add [get_ports i_hdmirx_clk_p ]\n## XCLKSW\n## {{{\n## set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~u_xpxclk/CLOCK_SWITCH.u_prepx/r_sel*}] -to [get_cells -hier -filter {NAME=~ u_xpxclk/CLOCK_SWITCH.u_prepx/u_bufg*}] 7.0\n# set_case_analysis 1 [get_nets -hier -filter {NAME=~ w_pxclk_cksel[1]*}]\n## }}}\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset_sys*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset_u*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset_sys*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset_pipe*}] 6.0\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/genhdmi/pix_reset*}] 6.0\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/hdmi_reset_sys*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/hdmi_reset_pipe*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/hdmi_reset_sys*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/hdmi_reset*}] 6.0\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/hdmi_reset*}] -to [get_cells -hier -filter {NAME=~ u_hdmirx_*/reset_pipe*}] 10.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/hdmi_reset*}] -to [get_cells -hier -filter {NAME=~ u_hdmirx_*/the_deserdes/reset_pipe*}] 10.0\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ u_hdmitx_*/reset_pipe*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ u_hdmitx_*/sync_reset_n*}] 6.0\n##\n## RXVIDXCLK\n## {{{\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_rxvidxclk/GEN_REGISTERED_READ.o_rd_empty*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_rxvidxclk/mem*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_rxvidxclk/GEN_REGISTERED_READ.o_rd_data*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_rxvidxclk/rd_addr*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_rxvidxclk/rgray*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_rxvidxclk/rd_wgray*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_rxvidxclk/wgray_cross*}] 6.0\n#\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_overlay/primary_skid/LOGIC.r_valid*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_rxvidxclk/rd_addr*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_overlay/primary_skid/LOGIC.r_valid*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_rxvidxclk/rgray*}] 6.0\n# set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_overlay/primary_skid/LOGIC.r_valid*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_rxvidxclk/GEN_REGISTERED_READ.o_rd_data*}] 6.0\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_rxvidxclk/wgray*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_rxvidxclk/wgray_cross*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_rxvidxclk/mem*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_rxvidxclk/GEN_REGISTERED_READ.o_rd_data*}] 6.0\n# set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_rxvidxclk/rd_addr*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_rxvidxclk/GEN_REGISTERED_READ.o_rd_data*}] 6.0\n##\n## }}}\n## u_new_frame\n## {{{\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_new_frame/a_req*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_new_frame/a_ack*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_new_frame/a_pipe*}] 6.0\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_new_frame/a_pipe*}] 6.0\n## }}}\n##\n## WB2PIX\n## {{{\n## set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.u_wb2pix/a_data*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.u_wb2pix/o_b_data*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.u_wb2pix/a_req*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.u_wb2pix/b_pipe*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.u_wb2pix/b_last*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.u_wb2pix/a_pipe*}] 6.0\n## }}}\n## PIX2WB\n## {{{\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.r_pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.u_pix2wb/o_b_data*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.r_pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.u_pix2wb/a_ack*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.r_pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.u_pix2wb/a_pipe*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.r_pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.u_pix2wb/a_req*}] 6.0\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.u_pix2wb/a_data*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.u_pix2wb/o_b_data*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.u_pix2wb/a_req*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.u_pix2wb/b_pipe*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.u_pix2wb/b_last*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.u_pix2wb/a_pipe*}] 6.0\n## }}}\n##\n## u_framebuf/GEN_ASYNC_FIFO.pxfifo\n## {{{\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.r_pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.pxfifo/wgray_cross*}] 6.0\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset_sys*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.r_pix_reset*}] 6.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.pxfifo/rgray*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.pxfifo/rgray_cross*}] 7.0\n#\n#\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.r_pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.pxfifo/rd_addr*}] 7.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.r_pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.pxfifo/rgray*}] 7.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.r_pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.pxfifo/rd_wgray*}] 7.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.r_pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.pxfifo/GEN_REGISTERED_READ.o_rd_empty*}] 7.0\n#\n#\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.pxfifo/wgray*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.pxfifo/wgray_cross*}] 7.0\n# set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.pxfifo/mem*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.pxfifo/GEN_REGISTERED_READ.o_rd_data*}] 7.0\n##\n# set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.pxfifo/mem*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_framebuf/GEN_ASYNC_FIFO.pxfifo/GEN_REGISTERED_READ.o_rd_data*}] 7.0\n## }}}\n## H2SYS\n## {{{\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_h2sys/a_data*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_h2sys/o_b_data*}] 10.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_h2sys/b_last*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_h2sys/a_pipe*}]   10.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_h2sys/a_req*}]  -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_h2sys/b_pipe*}]   10.0\n## }}}\n## H2PIX\n## {{{\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_h2pix/b_pipe*}] 6.7\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_h2pix/b_req*}] 6.7\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_h2pix/b_last*}] 6.7\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_h2pix/a_data*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_h2pix/o_b_data*}] 6.7\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_h2pix/b_last*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_h2pix/a_pipe*}]   6.7\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_h2pix/a_req*}]  -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_h2pix/b_pipe*}]   6.7\n## }}}\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_hdmi2vga/bitsync/*sync/pixloc/REQUIRE_QUALITY.o_val*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pre_wb_data*}] 10.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_hdmi2vga/bitsync/*sync/sync_valid*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pre_wb_data*}] 10.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_HDMIIN_TO_AXIVID.u_hdmi2vga/bitsync/all_locked*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pre_wb_data*}] 10.0\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_new_frame/b_last*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_new_frame/a_pipe*}] 7.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_new_frame/a_req*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_new_frame/b_pipe*}] 7.0\n##\n## PX2SYS\n## {{{\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_hdmi/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_hdmi/u_px2sys/a_req*}] 7.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_hdmi/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_hdmi/u_px2sys/a_ack*}] 7.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_hdmi/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_hdmi/u_px2sys/a_pipe*}] 7.0\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_hdmi/u_px2sys/b_last*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_hdmi/u_px2sys/a_pipe*}] 7.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_px2sys/a_req*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_px2sys/b_pipe*}] 7.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_px2sys/a_data*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_px2sys/o_b_data*}] 7.0\n## }}}\n##\n## SYS2PX\n##{{{\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_sys2px/b_req*}] 7.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_sys2px/b_last*}] 7.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/pix_reset*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_sys2px/b_pipe*}] 7.0\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_sys2px/a_data*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_sys2px/o_b_data*}] 7.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_sys2px/b_last*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_sys2px/a_pipe*}] 7.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_sys2px/a_req*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_sys2px/b_pipe*}] 7.0\n## set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_sys2px/o_b_data*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/genhdmi/vpos*}] 7.0\n## set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_sys2px/o_b_data*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/genhdmi/hpos*}] 7.0\n## }}}\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_mem2pix/cmap_reg*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/GEN_FRAMEBUF.u_mem2pix/cmap*reg*}] 7.0\n## CLKCOUNTER\n## {{{\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~thedesign/u_@$(PREFIX)/u_pixclk_counter/avgs*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_pixclk_counter/q_v*}] 7.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~thedesign/u_@$(PREFIX)/u_siclk_counter/avgs*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_siclk_counter/q_v*}] 7.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~thedesign/u_@$(PREFIX)/u_hdmiclk_counter/avgs*}] -to [get_cells -hier -filter {NAME=~ thedesign/u_@$(PREFIX)/u_hdmiclk_counter/q_v*}] 7.0\n## }}}\n@PREFIX=pxclk\n@SLAVE.TYPE=other\n@SLAVE.BUS=wb32\n@NADDR=128\n@TOP.DEFNS=\n\twire\t[31:0]\t@$(PREFIX)_debug;\n\twire\t\tw_@$(PREFIX)_cyc, w_@$(PREFIX)_stb, w_@$(PREFIX)_we,\n\t\t\tw_@$(PREFIX)_stall, w_@$(PREFIX)_ack;\n\twire\t[6:0]\tw_@$(PREFIX)_addr;\n\twire\t[31:0]\tw_@$(PREFIX)_data, w_@$(PREFIX)_idata;\n\twire\t[3:0]\tw_@$(PREFIX)_sel;\n@TOP.MAIN=\n\t\tw_@$(PREFIX)_cyc, w_@$(PREFIX)_stb, w_@$(PREFIX)_we,\n\t\tw_@$(PREFIX)_addr, w_@$(PREFIX)_data, w_@$(PREFIX)_sel,\n\t\tw_@$(PREFIX)_stall, w_@$(PREFIX)_ack, w_@$(PREFIX)_idata\n@MAIN.PORTLIST=\n\t\to_@$(PREFIX)_cyc, o_@$(PREFIX)_stb, o_@$(PREFIX)_we,\n\t\to_@$(PREFIX)_addr, o_@$(PREFIX)_data, o_@$(PREFIX)_sel,\n\t\ti_@$(PREFIX)_stall, i_@$(PREFIX)_ack, i_@$(PREFIX)_idata\n@MAIN.IODECL=\n\toutput\twire\to_@$(PREFIX)_cyc, o_@$(PREFIX)_stb, o_@$(PREFIX)_we;\n\toutput\twire\t[6:0]\to_@$(PREFIX)_addr;\n\toutput\twire\t[31:0]\to_@$(PREFIX)_data;\n\toutput\twire\t[3:0]\to_@$(PREFIX)_sel;\n\tinput\twire\t\ti_@$(PREFIX)_stall, i_@$(PREFIX)_ack;\n\tinput\twire\t[31:0]\ti_@$(PREFIX)_idata;\n@TOP.PORTLIST=\n@TOP.IODECL=\n@TOP.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// HDMI Clock generation\n\t// {{{\n\n\txpxclk\n\tu_xpxclk (\n\t\t.i_sysclk(s_clk),\t\t// System clock\n\t\t.i_cksel(w_pxclk_cksel),\t\t// Clock select switch\n\t\t//\n\t\t.i_hdmirx_clk_p(i_hdmirx_clk_p),\t// HDMI RX input clock\n\t\t.i_hdmirx_clk_n(i_hdmirx_clk_n),\n\t\t.i_lcl_pixclk(s_clk_80mhz_unbuffered),\t// Locally generated clk\n\t\t.i_siclk(s_clk_80mhz_unbuffered),\n\t\t//\n\t\t.o_hdmick_locked(pxrx_locked),\n\t\t.o_hdmirx_clk(hdmirx_clk),\t// Clk for measurement only\n\t\t.o_pixclk(hdmi_ck),\t\t// Pixel clock\n\t\t.o_hdmick(hdmi_serdes_clk),\t// HS pixel clock\n\t\t//\n\t\t.i_wb_clk(s_clk),\n\t\t//\n\t\t.i_wb_cyc(w_@$(PREFIX)_cyc), .i_wb_stb(w_@$(PREFIX)_stb),\n\t\t\t.i_wb_we(w_@$(PREFIX)_we),\n\t\t\t.i_wb_addr(w_@$(PREFIX)_addr[7-1:0]),\n\t\t\t.i_wb_data(w_@$(PREFIX)_data), // 32 bits wide\n\t\t\t.i_wb_sel(w_@$(PREFIX)_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(w_@$(PREFIX)_stall),.o_wb_ack(w_@$(PREFIX)_ack),\n\t\t\t.o_wb_data(w_@$(PREFIX)_idata),\n\t\t//\n\t\t.o_debug(@$(PREFIX)_debug)\n\t);\n\t// }}}\n@MAIN.INSERT=\n\tassign\to_@$(PREFIX)_cyc  = @$(SLAVE.PREFIX)_cyc;\n\tassign\to_@$(PREFIX)_stb  = @$(SLAVE.PREFIX)_stb;\n\tassign\to_@$(PREFIX)_we   = @$(SLAVE.PREFIX)_we;\n\tassign\to_@$(PREFIX)_addr = @$(SLAVE.PREFIX)_addr[6:0];\n\tassign\to_@$(PREFIX)_data = @$(SLAVE.PREFIX)_data;\n\tassign\to_@$(PREFIX)_sel  = @$(SLAVE.PREFIX)_sel;\n\tassign\t@$(SLAVE.PREFIX)_stall = i_@$(PREFIX)_stall;\n\tassign\t@$(SLAVE.PREFIX)_ack   = i_@$(PREFIX)_ack;\n\tassign\t@$(SLAVE.PREFIX)_idata = i_@$(PREFIX)_idata;\n@REGS.NOTE=// HDMI pixel clock PLL reconfiguration port\n@REGS.N=1\n@REGS.0=   0  R_PXPLL PXPLL\n## @BDEF.DEFN=\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE=unsigned\n@BDEF.OSDEF=_BOARD_HAS_PXPLL\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME)=((@$(BDEF.IOTYPE) *)@$[0x%08x](REGBASE));\n@SIM.CLOCK=clk\n@SIM.TICK=\n\t\tm_core->i_@$(PREFIX)_stall = 0;\n\t\tm_core->i_@$(PREFIX)_ack   = m_core->o_@$(PREFIX)_stb;\n\t\tm_core->i_@$(PREFIX)_idata = m_core->o_@$(PREFIX)_data;\n"
  },
  {
    "path": "auto-data/i2ccpu.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/i2ccpu.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tDrive and control the I2C bus\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=i2c\n@DEVID=I2CCPU\n@NADDR=4\n@ACCESS=@$(DEVID)_ACCESS\n@SLAVE.BUS=wb32\n@SLAVE.TYPE=DOUBLE\n@SLAVE.PREFIX=@$(SLAVE.BUS.NAME)_@$(PREFIX)s\n@MASTER.TYPE=CPU\n@MASTER.BUS=wbwide\n@MASTER.PREFIX=@$(MASTER.BUS.NAME)_@$(PREFIX)m\n@SGP=@$(BUS.PREFIX)\n@WBP=@$(SLAVE.BUS.PREFIX)\n@MASTER.ANSPREFIX=pf_\n@IOSDA=io_sda\n@IOSCL=io_scl\n@IDW=2\n@INTERRUPT=i2c_int\n@INT.I2C.WIRE=@$(INTERRUPT)\n@INT.I2C.PIC=syspic\n@TOP.PORTLIST=\n\t\t\t@$(IOSCL), @$(IOSDA)\n@TOP.IODECL=\n\tinout\twire\t@$(IOSCL), @$(IOSDA);\n@TOP.DEFNS=\n\t// I2CCPU definitions\n\t// {{{\n\twire\ti_@$(PREFIX)_sda, i_@$(PREFIX)_scl,\n\t\to_@$(PREFIX)_sda, o_@$(PREFIX)_scl;\n\t// }}}\n@TOP.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// I2C IO buffers\n\t// {{{\n\n\t// We need these in order to (properly) ensure the high impedance\n\t// states (pull ups) of the I2C I/O lines.  Our goals are:\n\t//\n\t//\to_@$(PREFIX)_X\tio_@$(PREFIX)_X\t\tDerived:T\n\t//\t1'b0\t\t1'b0\t\t\t1'b0\n\t//\t1'b1\t\t1'bz\t\t\t1'b1\n\t//\n\tIOBUF @$(PREFIX)sclp(\n\t\t// {{{\n\t\t.I(1'b0),\n\t\t.T(o_@$(PREFIX)_scl),\n\t\t.O(i_@$(PREFIX)_scl),\n\t\t.IO(@$(IOSCL))\n\t\t// }}}\n\t);\n\n\tIOBUF @$(PREFIX)sdap(\n\t\t// {{{\n\t\t.I(1'b0),\n\t\t.T(o_@$(PREFIX)_sda),\n\t\t.O(i_@$(PREFIX)_sda),\n\t\t.IO(@$(IOSDA))\n\t\t// }}}\n\t);\n\t// }}}\n@TOP.MAIN=\n\t\t// I2CCPU\n\t\ti_@$(PREFIX)_sda, i_@$(PREFIX)_scl,\n\t\to_@$(PREFIX)_sda, o_@$(PREFIX)_scl\n@MAIN.PORTLIST=\n\t\t\ti_@$(PREFIX)_sda, i_@$(PREFIX)_scl,\n\t\t\to_@$(PREFIX)_sda, o_@$(PREFIX)_scl\n@MAIN.IODECL=\n\t// I2C Port declarations\n\t// {{{\n\tinput\twire\ti_@$(PREFIX)_sda, i_@$(PREFIX)_scl;\n\toutput\twire\to_@$(PREFIX)_sda, o_@$(PREFIX)_scl;\n\t// }}}\n@MAIN.DEFNS=\n\t// I2C Controller\n\t// {{{\n\t// Verilator lint_off UNUSED\n\tlocalparam\t@$(DEVID)_WIDTH=(@$(IDW) == 0) ? 1 : @$(IDW);\n\n\twire\t\t@$(PREFIX)_valid, @$(PREFIX)_ready, @$(PREFIX)_last;\n\twire\t[7:0]\t@$(PREFIX)_data;\n\twire\t[@$(DEVID)_WIDTH-1:0]\t@$(PREFIX)_id;\n\n\twire\t[31:0]\t@$(PREFIX)_debug;\n\t// Verilator lint_on  UNUSED\n\t// }}}\n@MAIN.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// The I2C Controller\n\t// {{{\n\n\twbi2ccpu #(\n\t\t.ADDRESS_WIDTH(@$(MASTER.BUS.AWID)),\n\t\t.DATA_WIDTH(@$(MASTER.BUS.WIDTH)),\n\t\t.AXIS_ID_WIDTH(@$(IDW))\n\t) u_@$(PREFIX) (\n\t\t// {{{\n\t\t.i_clk(@$(SLAVE.BUS.CLOCK.WIRE)), .i_reset(@$(SLAVE.BUS.CLOCK.RESET)),\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t@$(MASTER.ANSIPORTLIST),\n\t\t.i_i2c_sda(i_@$(PREFIX)_sda), .i_i2c_scl(i_@$(PREFIX)_scl),\n\t\t.o_i2c_sda(o_@$(PREFIX)_sda), .o_i2c_scl(o_@$(PREFIX)_scl),\n\t\t.M_AXIS_TVALID(@$(PREFIX)_valid), .M_AXIS_TREADY(@$(PREFIX)_ready),\n\t\t\t.M_AXIS_TDATA(@$(PREFIX)_data), .M_AXIS_TLAST(@$(PREFIX)_last),\n\t\t\t.M_AXIS_TID(@$(PREFIX)_id),\n\t\t.i_sync_signal(rtc_pps),\n\t\t//\n\t\t.o_interrupt(@$(INTERRUPT)),\n\t\t.o_debug(@$(PREFIX)_debug)\n\t\t// }}}\n\t);\n\n\tassign\t@$(PREFIX)_ready = (!@$(PREFIX)_valid) || (1'b0\n\t\t\t|| (@$(PREFIX)_id == 0)\t\t// NULL address\n\t\t\t|| (@$(PREFIX)_id == 1)\n`ifdef\tI2CDMA_ACCESS\n\t\t\t|| (@$(PREFIX)_id == 2 && i2cdma_ready)\n`else\n\t\t\t|| (@$(PREFIX)_id == 2)\n`endif\n\t\t\t|| (@$(PREFIX)_id > 2));\n\n\t// }}}\n@MAIN.ALT=\n\tassign\to_@$(PREFIX)_scl = 1'b1;\n\tassign\to_@$(PREFIX)_sda = 1'b1;\n##\n## regdefs.h / regdefs.cpp\n##\n@REGS.N=4\n@REGS.NOTE=// I2C Controller registers\n@REGS.0= 0 R_@$(DEVID) @$(DEVID) @$(DEVID)_CTRL @$(DEVID)CTRL\n@REGS.1= 1 R_@$(DEVID)_OVW  @$(DEVID)_OVW @$(DEVID)_OVERRIDE\n@REGS.2= 2 R_@$(DEVID)_ADDR @$(DEVID)_ADDR @$(DEVID)_ADDRESS\n@REGS.3= 3 R_@$(DEVID)_CKCOUNT  @$(DEVID)CLK @$(DEVID)_CKCOUNT\n##\n## board.h\n##\n@BDEF.DEFN=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// I2C CPU data structures\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t//\n#ifndef\t@$(DEVID)_H\n#define\t@$(DEVID)_H\n\n#define\tI2CC_WAITING\t0x00800000\t// True if waiting for synch signal\n#define\tI2CC_HALT\t0x00400000\t// Halt request\n#define\tI2CC_ABORT\t0x00200000\t// Abort\n#define\tI2CC_ERROR\t0x00100000\n#define\tI2CC_HARDHALT\t0x00080000\n#define\tI2CC_SCL\t0x00000200\n#define\tI2CC_SDA\t0x00000100\n#define I2CC_STOPPED\tI2CC_HARDHALT\n#define I2CC_FAULT\t(I2CC_ERROR | I2CC_ABORT)\n#define I2CC_CLEAR\t(I2CC_FAULT | I2CC_HALT)\n\n// For the manual port\n#define\tI2CC_MANSCL\t0x00008000\n#define\tI2CC_MANSDA\t0x00004000\n#define\tI2CC_MANUAL\t0x00000800\n#define\tI2CC_TVALID\t0x00000200\n#define\tI2CC_TLAST\t0x00000100\n\ntypedef\tstruct\t@$(DEVID)_S {\n\tvolatile unsigned\tic_control,\n\t\t\t\tic_override,\n\t\t\t\tic_address,\n\t\t\t\tic_clkcount;\n} @$(DEVID);\n\n#endif\t// @$(DEVID)_H\n\t// }}}\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE=@$(DEVID)\n@BDEF.OSDEF=_BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME)=((@$(BDEF.IOTYPE) *)@$[0x%08x](REGBASE));\n##\n## Makefile insert info\n##\n@RTL.MAKE.GROUP=@$(DEVID)\n@RTL.MAKE.SUBD=wbi2c\n## RTL.MAKE.FILES *shoul* also include dblfetch, but that's a part of the CPU\n## directory, so we don't include it here a second time\n@RTL.MAKE.FILES=wbi2ccpu.v axisi2c.v\n##\n## Makefile insert info\n##\n@SIM.CLOCK=clk\n@SIM.TICK=\n\t\tm_core->i_@$(PREFIX)_scl = m_core->o_@$(PREFIX)_scl;\n\t\tm_core->i_@$(PREFIX)_sda = m_core->o_@$(PREFIX)_sda;\n"
  },
  {
    "path": "auto-data/i2cdma.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/i2cdma.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tConnect an (optional) DMA to the main I2C bus.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=i2cdma\n@DEVID=I2CDMA\n@ACCESS=@$(DEVID)_ACCESS\n@NADDR=4\n@SLAVE.BUS=wb32\n@SLAVE.TYPE=DOUBLE\n@MASTER.BUS=wbwide\n@MASTER.TYPE=DMA\n@MASTER.ANSPREFIX=dma_\n@STREAM=i2c\n@MAIN.DEFNS=\n\twire\t@$(PREFIX)_ready;\n@MAIN.INSERT=\n\twbi2cdma #(\n\t\t.AW(@$(MASTER.BUS.AWID)), .DW(@$(MASTER.BUS.WIDTH)), .SW(8),\n\t\t.OPT_LITTLE_ENDIAN(1'b0)\n\t) u_@$(PREFIX) (\n\t\t// {{{\n\t\t.i_clk(@$(SLAVE.BUS.CLOCK.WIRE)),\n\t\t.i_reset(@$(SLAVE.BUS.CLOCK.RESET)),\n\t\t//\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t.S_VALID(@$(STREAM)_valid && @$(STREAM)_id == 2),\n\t\t\t.S_READY(@$(PREFIX)_ready),\n\t\t\t.S_DATA(@$(STREAM)_data), .S_LAST(@$(STREAM)_last),\n\t\t@$(MASTER.ANSIPORTLIST)\n\t\t// }}}\n\t);\n\n@MAIN.ALT=\n\tassign\t@$(PREFIX)_ready = 1'b0;\n@RTL.MAKE.GROUP=@$(DEVID)\n@RTL.MAKE.SUBD=wbi2c\n@RTL.MAKE.FILES=wbi2cdma.v\n@REGS.N=4\n@REGS.0=0 R_@$(DEVID)      @$(DEVID)\n@REGS.1=1 R_@$(DEVID)_ADDR @$(DEVID)ADDR\n@REGS.2=2 R_@$(DEVID)_BASE @$(DEVID)BASE\n@REGS.3=3 R_@$(DEVID)_LEN  @$(DEVID)LEN\n##\n## board.h\n##\n@BDEF.DEFN=\n#ifndef\t@$(DEVID)_H\n#define\t@$(DEVID)_H\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// I2C DMA data structures\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t//\n\ntypedef struct  @$(DEVID)_S        {\n\tunsigned\tid_control, id_current, id_base, id_memlen;\n} @$(DEVID);\n\n#endif\t// @$(DEVID)_H\n\t// }}}\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE=@$(DEVID)\n@BDEF.OSDEF=_BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME)=((@$(BDEF.IOTYPE) *)@$[0x%08x](REGBASE));\n##\n"
  },
  {
    "path": "auto-data/i2saudio.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/i2saudio.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\t\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=i2saudio\n@ACCESS=I2SAUDIO\n@DEPENDS=ARBITRARY_CLOCK_GENERATOR_ACCESS\n@DEVID=AUDIO\n@SOURCE=audio_in\n@SINK=audio_out\n@NADDR=1\n@MAIN.PORTLIST=\n\t\to_i2s_lrclk, o_i2s_bclk, o_i2s_mclk, o_i2s_dac, i_i2s_adc\n@MAIN.IODECL=\n\toutput\twire\to_i2s_lrclk, o_i2s_bclk, o_i2s_mclk, o_i2s_dac;\n\tinput\twire\ti_i2s_adc;\n@MAIN.DEFNS=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// I2S Audio signal definitions\n\t// {{{\n\twire\t\tw_@$(PREFIX)_en;\n\t// Verilator lint_off UNUSED\n\t//\n\t// These wires may or may not be connected to anything ...\n\twire\t\tw_@$(SINK)_valid, w_@$(SINK)_ready, w_@$(SINK)_last;\n\twire\t[23:0]\tw_@$(SINK)_data;\n\t//\n\t// w_@$(SOURCE)... comes from the microphone (if present)\n\twire\t\tw_@$(SOURCE)_valid, w_@$(SOURCE)_ready,\n\t\t\tw_@$(SOURCE)_last;\n\twire\t[23:0]\tw_@$(SOURCE)_data;\n\n\twire\t[31:0]\tw_@$(PREFIX)_debug;\n\t// Verilator lint_on  UNUSED\n\t// }}}\n@MAIN.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// I2S Audio signal handler\n\t// {{{\n\n\tassign\to_i2s_mclk = i_genclk_clk;\n\tassign\tw_@$(PREFIX)_en = 1'b1;\n\n\taxisi2s #(\n\t\t.BDIV(4'h1)\n\t) u_@$(PREFIX) (\n\t\t// {{{\n\t\t.S_AXI_ACLK(i_clk), .S_AXI_ARESETN(!i_reset),\n\t\t//\n\t\t// Inputs to drive the speakers\n\t\t.S_AXIS_TVALID(w_@$(SINK)_valid),\n\t\t.S_AXIS_TREADY(w_@$(SINK)_ready),\n\t\t.S_AXIS_TDATA(w_@$(SINK)_data),\n\t\t.S_AXIS_TLAST(w_@$(SINK)_last),\n\t\t//\n\t\t// Outputs from the microphone\n\t\t.M_AXIS_TVALID(w_@$(SOURCE)_valid),\n\t\t.M_AXIS_TREADY(w_@$(SOURCE)_ready),\n\t\t.M_AXIS_TDATA(w_@$(SOURCE)_data),\n\t\t.M_AXIS_TLAST(w_@$(SOURCE)_last),\n\t\t//\n\t\t.i_mclk(o_i2s_mclk),\n\t\t.i_clken(w_@$(PREFIX)_en),\n\t\t.o_lrclk(o_i2s_lrclk),\n\t\t.o_bclk(o_i2s_bclk),\n\t\t.i_adc(i_i2s_adc),\n\t\t.o_dac(o_i2s_dac),\n\t\t.o_debug(w_@$(PREFIX)_debug)\n\t\t// }}}\n\t);\n\n`ifndef\tAUDIOSINK_ACCESS\n\tassign\tw_@$(SINK)_valid = 0;\n\tassign\tw_@$(SINK)_data  = 0;\n\tassign\tw_@$(SINK)_last  = 0;\n`endif\n`ifndef\tAUDIOSOURCE_ACCESS\n\tassign\tw_@$(SOURCE)_ready = 1;\n`endif\n\t// }}}\n@MAIN.ALT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// (No) I2S Audio signal handler (option)\n\t// {{{\n`ifndef\tAUDIOSINK_ACCESS\n\tassign\tw_@$(SINK)_valid = 0;\n\tassign\tw_@$(SINK)_data  = 0;\n\tassign\tw_@$(SINK)_last  = 0;\n`endif\n\tassign\tw_@$(SINK)_ready = 0;\n\n\tassign\tw_@$(SOURCE)_valid = 0;\n\tassign\tw_@$(SOURCE)_data  = 0;\n\tassign\tw_@$(SOURCE)_last  = 0;\n`ifndef\tAUDIOSOURCE_ACCESS\n\tassign\tw_@$(SOURCE)_ready = 0;\n`endif\n\t// }}}\n@XDC.INSERT=\n## set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ sdrami/r_sys_reset* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/mclk_reset* }] 10.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/u_adc_fifo/rgray* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/u_adc_fifo/rgray_cross* }] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/u_adc_fifo/wgray* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/u_adc_fifo/wgray_cross* }] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/u_adc_fifo/mem_reg* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/u_adc_fifo/GEN_REGISTERED_READ.o_rd_data* }] 8.0\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/u_dac_fifo/mem_reg* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/u_dac_fifo/GEN_REGISTERED_READ.o_rd_data* }] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/u_dac_fifo/rgray* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/u_dac_fifo/rgray_cross* }] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/u_dac_fifo/wgray* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/u_dac_fifo/wgray_cross* }] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/u_dac_fifo/wr_rgray* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/r_dac_data* }] 8.0\n##\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/lli2si/o_lrclk* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/xclk_pipe* }] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/lli2si/o_bclk* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/xclk_pipe* }] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/lli2si/o_dac* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/xclk_pipe* }] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *xgenclki/GEN_PLL.pll* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/xclk_pipe* }] 8.0\nset_false_path -hold -from [get_cells -hier -filter {NAME=~ *xgenclki/GEN_PLL.pll* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/xclk_pipe* }]\nset_false_path -hold -from [get_cells -hier -filter {NAME=~ *xgenclki/GEN_PLL.pll* }] -rise_to [get_clocks -filter {NAME=~ *clk_pll_i* }]\n##\n## set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/lli2si/o_lrclk* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/xclk_debug* }] 8.0\n## set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/lli2si/o_bclk* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/xclk_debug* }] 8.0\n## set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/lli2si/o_dac* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/xclk_debug* }] 8.0\n## set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *xgenclki/GEN_PLL.pll* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/xclk_debug* }] 8.0\n## set_false_path -hold -from [get_cells -hier -filter {NAME=~ *xgenclki/GEN_PLL.pll* }] -to [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/xclk_debug* }]\n@RTL.MAKE.GROUP=AUDIO\n@RTL.MAKE.SUBD=audio\n@RTL.MAKE.FILES=axisi2s.v lli2s.v\n@REGS.N=1\n@REGS.0= 0 R_@$(DEVID) @$(DEVID)\n"
  },
  {
    "path": "auto-data/icape.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/icape.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tA description of how to connect the wbicapetwo interface for\n##\t\tXilinx's ICAPE2 interface to a wishbone bus.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=icape\n@NADDR=32\n@ACCESS=CFG_ACCESS\n@SLAVE.TYPE=OTHER\n@SLAVE.BUS=wb32\n@MAIN.PARAM=\n\tlocalparam\tICAPE_LGDIV=3;\n@MAIN.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// ICAPE2 driver/controller\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t//\n`ifdef\tVERILATOR\n\treg\tr_@$(PREFIX)_ack;\n\n\tinitial\tr_@$(PREFIX)_ack = 1'b0;\n\talways @(posedge i_clk)\n\t\tr_@$(PREFIX)_ack <= @$(SLAVE.PREFIX)_stb;\n\tassign\t@$(SLAVE.PREFIX)_ack   = r_@$(PREFIX)_ack;\n\tassign\t@$(SLAVE.PREFIX)_stall = 1'b0;\n\tassign\t@$(SLAVE.PREFIX)_idata = 32'h00;\n`else\n\twbicapetwo #(\n\t\t.LGDIV(ICAPE_LGDIV)\n\t) u_@$(PREFIX) (\n\t\t// {{{\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t@$(SLAVE.ANSIPORTLIST)\n\t\t// }}}\n\t);\n`endif\n\t// }}}\n@REGS.NOTE=// FPGA CONFIG REGISTERS: 0x4e0-0x4ff\n@REGS.N=20\n@REGS.0=   0 R_CFG_CRC\t\tFPGACRC\n@REGS.1=   1 R_CFG_FAR\t\tFPGAFAR\n@REGS.2=   2 R_CFG_FDRI\t\tFPGAFDRI\n@REGS.3=   3 R_CFG_FDRO\t\tFPGAFDRO\n@REGS.4=   4 R_CFG_CMD\t\tFPGACMD\n@REGS.5=   5 R_CFG_CTL0\t\tFPGACTL0\n@REGS.6=   6 R_CFG_MASK\t\tFPGAMASK\n@REGS.7=   7 R_CFG_STAT\t\tFPGASTAT\n@REGS.8=   8 R_CFG_LOUT\t\tFPGALOUT\n@REGS.9=   9 R_CFG_COR0\t\tFPGACOR0\n@REGS.10= 10 R_CFG_MFWR\t\tFPGAMFWR\n@REGS.11= 11 R_CFG_CBC\t\tFPGACBC\n@REGS.12= 12 R_CFG_IDCODE\tFPGAIDCODE\n@REGS.13= 13 R_CFG_AXSS\t\tFPGAAXSS\n@REGS.14= 14 R_CFG_COR1\t\tFPGACOR1\n@REGS.15= 16 R_CFG_WBSTAR\tWBSTAR\n@REGS.16= 17 R_CFG_TIMER\t\tCFGTIMER\n@REGS.17= 22 R_CFG_BOOTSTS\tBOOTSTS\n@REGS.18= 24 R_CFG_CTL1\t\tFPGACTL1\n@REGS.19= 31 R_CFG_BSPI\t\tFPGABSPI\n@BDEF.DEFN=\n// Offsets for the ICAPE2 interface\n#define\tCFG_CRC\t\t0\n#define\tCFG_FAR\t\t1\n#define\tCFG_FDRI\t2\n#define\tCFG_FDRO\t3\n#define\tCFG_CMD\t\t4\n#define\tCFG_CTL0\t5\n#define\tCFG_MASK\t6\n#define\tCFG_STAT\t7\n#define\tCFG_LOUT\t8\n#define\tCFG_COR0\t9\n#define\tCFG_MFWR\t10\n#define\tCFG_CBC\t\t11\n#define\tCFG_IDCODE\t12\n#define\tCFG_AXSS\t13\n#define\tCFG_COR1\t14\n#define\tCFG_WBSTAR\t16\n#define\tCFG_TIMER\t17\n#define\tCFG_BOOTSTS\t22\n#define\tCFG_CTL1\t24\n#define\tCFG_BSPI\t31\n@BDEF.IONAME=_icape[32]\n@BDEF.IOTYPE=unsigned\n@BDEF.OSDEF=_BOARD_HAS_ICAPETWO\n@BDEF.OSVAL=static volatile @$THIS.BDEF.IOTYPE *const _icape = ((unsigned *)@$[0x%08x](REGBASE));\n@RTL.MAKE.GROUP=ICAP\n@RTL.MAKE.SUBD=\n@RTL.MAKE.FILES=wbicapetwo.v\n"
  },
  {
    "path": "auto-data/legalgen.txt",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tauto-data/legalgen.txt\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Computer Generated: This file is computer generated by AUTOFPGA. DO NOT EDIT.\n// DO NOT EDIT THIS FILE!\n//\n// CmdLine:\t\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n"
  },
  {
    "path": "auto-data/mdio.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/mdio.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tThis file describes how the network MDIO core is to be\n##\t\tconnected to the rest of the design, for use by the autofpga\n##\tprogram.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=mdio\n@NADDR=1024\n@ACCESS=NETCTRL_ACCESS\n@SLAVE.TYPE=OTHER\n@SLAVE.BUS=wb32\n@TOP.PORTLIST=\n\t\t// Toplevel ethernet MDIO ports\n\t\to_eth_mdclk, io_eth_mdio\n@TOP.IODECL=\n\t// Ethernet control (MDIO)\n\toutput\twire\t\to_eth_mdclk;\n\tinout\twire\t\tio_eth_mdio;\n@TOP.DEFNS=\n\t// Ethernet control (MDIO)\n\twire\t\tw_mdio, w_mdwe;\n@TOP.MAIN=\n\t\to_eth_mdclk, w_mdio, w_mdwe, io_eth_mdio\n@TOP.INSERT=\n\tassign\tio_eth_mdio = (w_mdwe)?w_mdio : 1'bz;\n@MAIN.PORTLIST=\n\t\t// The ethernet MDIO wires\n\t\to_mdclk, o_mdio, o_mdwe, i_mdio\n@MAIN.IODECL=\n\t// Ethernet control (MDIO)\n\toutput\twire\t\to_mdclk, o_mdio, o_mdwe;\n\tinput\twire\t\ti_mdio;\n@MAIN.DEFNS=\n\t// Verilator lint_off UNUSED\n\twire[31:0]\t@$(PREFIX)_debug;\n\t// Verilator lint_on  UNUSED\n@MAIN.INSERT=\n\tenetctrl #(\n\t\t.CLKBITS(6)\n\t) u_@$(PREFIX) (\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t.o_mdclk(o_mdclk), .o_mdio(o_mdio), .i_mdio(i_mdio),\n\t\t.o_mdwe(o_mdwe), .o_debug(@$(PREFIX)_debug)\n\t);\n@MAIN.ALT=\n\tassign\to_mdclk = 1'b1;\n\tassign\to_mdio  = 1'b1;\n\tassign\to_mdwe  = 1'b0;\n@REGS.NOTE= // Ethernet configuration (MDIO) port\n@REGS.N=30\n@REGS.0=  0 R_MDIO_BMCR  \tBMCR\n@REGS.1=  1 R_MDIO_BMSR \tBMSR\n@REGS.2=  2 R_MDIO_PHYIDR1\tPHYIDR1\n@REGS.3=  3 R_MDIO_PHYIDR2\tPHYIDR2\n@REGS.4=  4 R_MDIO_ANAR\t\tANAR\n@REGS.5=  5 R_MDIO_ANLPAR\tANLPAR\n@REGS.6=  6 R_MDIO_ANER\t\tANER\n@REGS.7=  7 R_MDIO_ANNPTR\tANNPTR\n@REGS.8=  8 R_MDIO_ANNPRR\tANNPRR\n@REGS.9=  9 R_MDIO_GBCR\t\tGBCR\n@REGS.10= 10 R_MDIO_GBSR\tGBSR\n@REGS.11= 13 R_MDIO_MACR\tMACR\n@REGS.12= 14 R_MDIO_MAADR\tMAADR\n@REGS.13= 15 R_MDIO_GBESR\tGBESR\n@REGS.14= 16 R_MDIO_PHYCR\tPHYCR\n@REGS.15= 17 R_MDIO_PHYSR\tPHYSR\n@REGS.16= 18 R_MDIO_INER\tINER\n@REGS.17= 19 R_MDIO_INSR\tINSR\n## 20-23 are reserved\n@REGS.18=24 R_MDIO_RXERC\tRXERC\n## 25-26 are reserved\n@REGS.19=27 R_MDIO_LDPSR\tLDPSR\n@REGS.20=30 R_MDIO_EPAGSR\tEPAGSR\n@REGS.21=31 R_MDIO_PAGSEL\tPAGSEL\n##\n@REGS.22=0 R_XMDIO_PC1R\t\tXPC1R\n@REGS.23=1 R_XMDIO_PS1R\t\tXPS1R\n@REGS.24=20 R_XMDIO_EEECR\tXEEECR\n@REGS.25=16 R_XMDIO_EEEWER\tXEEEWER\n@REGS.26=60 R_XMDIO_EEEAR\tXEEEAR\n@REGS.27=61 R_XMDIO_EEELPAR\tXEEELPAR\n@REGS.28=26 R_XMDIO_LACR\tXLACR\n@REGS.29=28 R_XMDIO_LCR\t\tXLCR\n@REGS.30=45 R_XMDIO_ACCR\tXACCR\n@BDEF.DEFN=\n//\n// The Ethernet MDIO interface\n//\n#define MDIO_BMCR\t0x00\n#define MDIO_BMSR\t0x01\n#define MDIO_PHYIDR1\t0x02\t// PHY ID Register #1\n#define MDIO_PHYIDR2\t0x03\t// PHY ID Register #2\n#define MDIO_ANAR\t0x04\t// Autonegotiation advertisement\n#define MDIO_ANLPAR\t0x05\t// Autonegotiation link partner ability\n#define MDIO_ANER\t0x06\t// Autonegotiation expansion\n#define MDIO_ANNPTR\t0x07\t// Autonegotiation next page\n#define MDIO_ANNPRR\t0x08\t// Autonegotiation link partner next page\n#define MDIO_GBCR\t0x09\t// 1GBase-T Control\n#define MDIO_GBSR\t0x0a\t// 1GBase-T Status\n#define MDIO_MACR\t0x0d\t// MMD Access control\n#define MDIO_MAADR\t0x0e\t// MMD Access register/data\n#define MDIO_GBESR\t0x0f\n#define MDIO_PHYCR\t0x10\n#define MDIO_PHYSR\t0x11\n#define MDIO_INER\t0x12\n#define MDIO_INSR\t0x13\n#define MDIO_LDPSR\t0x1b\n#define MDIO_EPAGSR\t0x1e\n#define MDIO_PAGSEL\t0x1f\n\n#define XMDIO_PC1R\t0x00\n#define XMDIO_PS1R\t0x01\n#define XMDIO_EEECR\t0x14\n#define XMDIO_EEEWER\t0x10\n// #define XMDIO_EEEAR\t0x\n// #define XMDIO_EEELPAR\t0x18\n#define XMDIO_LACR\t0x1a\n#define XMDIO_LCR\t0x1c\n// #define XMDIO_ACCR\t0x1b\n\ntypedef struct ENETMDIO_S {\n\tunsigned\te_v[32][32];\n} ENETMDIO;\n\n@BDEF.IOTYPE= ENETMDIO\n@BDEF.IONAME= io_netmdio\n@BDEF.OSDEF= _BOARD_HAS_NETMDIO\n@BDEF.OSVAL= static volatile @$THIS.BDEF.IOTYPE *const _mdio = ((@$THIS.BDEF.IOTYPE *)@$[0x%08x](REGBASE));\n@SIM.CLOCK=clk\n@SIM.INCLUDE=\n#include \"enetctrlsim.h\"\n@SIM.DEFNS=\n#ifdef\t@$(ACCESS)\n\tENETCTRLSIM\t*m_mdio;\n#endif // @$(ACCESS)\n@SIM.INIT=\n#ifdef\t@$(ACCESS)\n\t\tm_mdio = new ENETCTRLSIM;\n#endif // @$(ACCESS)\n@SIM.TICK=\n#ifdef\t@$(ACCESS)\n\t\tm_core->i_mdio = (*m_mdio)((m_core->i_reset)?1:0,\n\t\t\t\tm_core->o_mdclk,\n\t\t\t\t((m_core->o_mdwe)&&(!m_core->o_mdio))?0:1);\n#else\n\t\tm_core->i_mdio = ((m_core->o_mdwe)&&(!m_core->o_mdio))?0:1;\n#endif // @$(ACCESS)\n@RTL.MAKE.SUBD=ethernet\n@RTL.MAKE.GROUP=ENETMDIO\n@RTL.MAKE.FILES=enetctrl.v\n"
  },
  {
    "path": "auto-data/meganet.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/meganet.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\t\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2015-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=net\n@DEVID=MEGANET\n@ACCESS=@$(DEVID)_ACCESS\n@SLAVE.BUS=wb32\n@NADDR=32\n@SLAVE.TYPE=OTHER\n@$BASEPORT=6782\n@$UARTDBGPORT=@$(BASEPORT)\n@$UARTPORT=@$(BASEPORT)+1\n@$UDPDBGPORT=@$(BASEPORT)+2\n@$DATAPORT=@$(BASEPORT)+3\n@$HWMAC.0=0x82\n@$HWMAC.1=0x33\n@$HWMAC.2=0x48\n@$HWMAC.3=0x02\n@$HWMAC.4=0xe1\n@$HWMAC.5=0xc8\n@$IPADDR.0=192\n@$IPADDR.1=168\n@$IPADDR.2=15\n@$IPADDR.3=29\n@TOP.PORTLIST=\n\t\t// Ethernet control (packets) lines\n\t\to_@$(PREFIX)_reset_n,\n\t\ti_@$(PREFIX)_rx_clk, i_@$(PREFIX)_rx_ctl, i_@$(PREFIX)_rxd,\n\t\to_@$(PREFIX)_tx_clk, o_@$(PREFIX)_tx_ctl, o_@$(PREFIX)_txd\n@TOP.IODECL=\n\t// MegaNet I/O port declarations\n\t// {{{\n\toutput\twire\t\to_@$(PREFIX)_reset_n;\n\tinput\twire\t\ti_@$(PREFIX)_rx_clk, i_@$(PREFIX)_rx_ctl;\n\tinput\twire [3:0]\ti_@$(PREFIX)_rxd;\n\toutput\twire\t \to_@$(PREFIX)_tx_clk, o_@$(PREFIX)_tx_ctl;\n\toutput\twire [3:0]\to_@$(PREFIX)_txd;\n\t// }}}\n@TOP.DEFNS=\n\t// Mega Net definitions\n\t// {{{\n\twire\t[7:0]\t\tw_@$(PREFIX)_rxd, w_@$(PREFIX)_txd;\n\twire\t\t\tw_@$(PREFIX)_rxdv, w_@$(PREFIX)_rxerr,\n\t\t\t\tw_@$(PREFIX)_txctl;\n\twire\t[1:0]\t\tw_@$(PREFIX)_tx_clk;\n\treg\t@$(PREFIX)_last_tck;\n\t// }}}\n@TOP.MAIN=\n\t\t// Ethernet (RGMII) connections\n\t\to_net_reset_n,\n\t\ti_net_rx_clk, w_net_rxdv,  w_net_rxdv ^ w_net_rxerr, w_net_rxd,\n\t\tw_net_tx_clk, w_net_txctl, w_net_txd\n@TOP.INSERT=\n\t// RGMII control\n\t// {{{\n\txiddr\t@$(PREFIX)rx0(i_@$(PREFIX)_rx_clk, i_@$(PREFIX)_rxd[0], { w_@$(PREFIX)_rxd[4], w_@$(PREFIX)_rxd[0] });\n\txiddr\t@$(PREFIX)rx1(i_@$(PREFIX)_rx_clk, i_@$(PREFIX)_rxd[1], { w_@$(PREFIX)_rxd[5], w_@$(PREFIX)_rxd[1] });\n\txiddr\t@$(PREFIX)rx2(i_@$(PREFIX)_rx_clk, i_@$(PREFIX)_rxd[2], { w_@$(PREFIX)_rxd[6], w_@$(PREFIX)_rxd[2] });\n\txiddr\t@$(PREFIX)rx3(i_@$(PREFIX)_rx_clk, i_@$(PREFIX)_rxd[3], { w_@$(PREFIX)_rxd[7], w_@$(PREFIX)_rxd[3] });\n\txiddr\t@$(PREFIX)rxc(i_@$(PREFIX)_rx_clk, i_@$(PREFIX)_rx_ctl, { w_@$(PREFIX)_rxdv,   w_@$(PREFIX)_rxerr });\n\n\t//\n\t// All of the below is about delaying the clock 90 degrees from the data\n\t//\n\txoserdes\t@$(PREFIX)tx0(s_clk_125mhz, pll_reset, s_clk_250mhz, { {(2){w_@$(PREFIX)_txd[0]}}, {(2){w_@$(PREFIX)_txd[4]}} }, o_@$(PREFIX)_txd[0]);\n\txoserdes\t@$(PREFIX)tx1(s_clk_125mhz, pll_reset, s_clk_250mhz, { {(2){w_@$(PREFIX)_txd[1]}}, {(2){w_@$(PREFIX)_txd[5]}} }, o_@$(PREFIX)_txd[1]);\n\txoserdes\t@$(PREFIX)tx2(s_clk_125mhz, pll_reset, s_clk_250mhz, { {(2){w_@$(PREFIX)_txd[2]}}, {(2){w_@$(PREFIX)_txd[6]}} }, o_@$(PREFIX)_txd[2]);\n\txoserdes\t@$(PREFIX)tx3(s_clk_125mhz, pll_reset, s_clk_250mhz, { {(2){w_@$(PREFIX)_txd[3]}}, {(2){w_@$(PREFIX)_txd[7]}} }, o_@$(PREFIX)_txd[3]);\n\n\talways @(posedge s_clk_125mhz)\n\t\t@$(PREFIX)_last_tck <= w_@$(PREFIX)_tx_clk[0];\n\n\txoserdes\t@$(PREFIX)txc(s_clk_125mhz, pll_reset, s_clk_250mhz, {(4){w_@$(PREFIX)_txctl}}, o_@$(PREFIX)_tx_ctl );\n\n\txoserdes\t@$(PREFIX)txck(s_clk_125mhz, pll_reset, s_clk_250mhz, {@$(PREFIX)_last_tck, {(2){w_@$(PREFIX)_tx_clk[1]}},w_@$(PREFIX)_tx_clk[0]},o_@$(PREFIX)_tx_clk);\n\t// xoserdes\t@$(PREFIX)txck(s_clk_125mhz, pll_reset, s_clk_250mhz, { {(2){w_@$(PREFIX)_tx_clk[1]}},{(2){w_@$(PREFIX)_tx_clk[0]}} }, o_@$(PREFIX)_tx_clk);\n\t// }}}\n@MAIN.PORTLIST=\n                // Ethernet control (packets) lines\n                o_@$(PREFIX)_reset_n,\n                // eth_int_b    // Interrupt, leave floating\n                // eth_pme_b    // Power management event, leave floating\n                i_@$(PREFIX)_rx_clk, i_@$(PREFIX)_rx_dv, i_@$(PREFIX)_rx_err, i_@$(PREFIX)_rxd,\n                o_@$(PREFIX)_tx_clk, o_@$(PREFIX)_tx_ctl, o_@$(PREFIX)_txd\n@MAIN.PARAM=\n\tparameter\t[15:0]\tUDP_DBGPORT  = @$(UDPDBGPORT);\n\n\tlocalparam\t[47:0]\tDEF_HWMAC  = 48'h@$[%02x](HWMAC.0)_@$[%02x](HWMAC.1)_@$[%02x](HWMAC.2)_@$[%02x](HWMAC.3)_@$[%02x](HWMAC.4)_@$[%02x](HWMAC.5);\n\tlocalparam\t[31:0]\tDEF_IPADDR = { 8'd@$(IPADDR.0), 8'd@$(IPADDR.1), 8'd@$(IPADDR.2), 8'd@$(IPADDR.3) };\n@MAIN.IODECL=\n        // Ethernet (RGMII) control\n\t// {{{\n\t// Verilator lint_off SYNCASYNCNET\n        output  wire            o_net_reset_n;\n\t// Verilator lint_on  SYNCASYNCNET\n        input   wire            i_@$(PREFIX)_rx_clk, i_@$(PREFIX)_rx_dv, i_@$(PREFIX)_rx_err;\n        input   wire    [7:0]   i_@$(PREFIX)_rxd;\n        output  wire    [1:0]   o_@$(PREFIX)_tx_clk;\n        output  wire            o_@$(PREFIX)_tx_ctl;\n        output  wire    [7:0]   o_@$(PREFIX)_txd;\n\t// }}}\n@MAIN.DEFNS=\n        // Ethernet (RGMII) control\n\t// {{{\n\t// Verilator lint_off UNUSED\n\twire\t[47:0]\t@$(PREFIX)_hwmac, @$(PREFIX)_last_ping_hwmac;\n\twire\t[31:0]\t@$(PREFIX)_ip_addr, @$(PREFIX)_last_ping_ipaddr;\n\n\twire\t\t@$(PREFIX)cpurx_valid, @$(PREFIX)cpurx_ready;\n\twire\t[31:0]\t@$(PREFIX)cpurx_data;\n\twire\t[1:0]\t@$(PREFIX)cpurx_bytes;\n\twire\t\t@$(PREFIX)cpurx_last, @$(PREFIX)cpurx_abort;\n\n\twire\t\t@$(PREFIX)cputx_valid, @$(PREFIX)cputx_ready,\n\t\t\t@$(PREFIX)cputx_last, @$(PREFIX)cputx_abort;\n\twire\t[31:0]\t@$(PREFIX)cputx_data;\n\twire\t[1:0]\t@$(PREFIX)cputx_bytes;\n\n\twire\t\t@$(PREFIX)_dbg_valid, @$(PREFIX)_dbg_ready,\n\t\t\t@$(PREFIX)_dbg_last;\n\twire\t[31:0]\t@$(PREFIX)_dbg_data;\n\twire\t[1:0]\t@$(PREFIX)_dbg_bytes;\n\n\twire\t\t@$(PREFIX)_high_speed;\n\n\twire\t\t@$(PREFIX)_debug_clk;\n\twire\t[31:0]\t@$(PREFIX)_debug;\n\twire\t\tign_rxpkt_@$(PREFIX)_ready;\n\n\t// Verilator lint_on  UNUSED\n\t// }}}\n@MAIN.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// MegaNET @$(DEVID)\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t//\n\n\tmeganet #(\n\t\t// {{{\n\t\t.DEF_HWMAC(DEF_HWMAC),\n\t\t.DEF_IPADDR(DEF_IPADDR),\n\t\t.UDP_DBGPORT(UDP_DBGPORT)\n\t\t// }}}\n\t) u_@$(PREFIX) (\n\t\t// {{{\n\t\t.S_AXI_ACLK(i_clk), .S_AXI_ARESETN(!i_reset),\n\t\t//\n\t\t.o_hwmac(@$(PREFIX)_hwmac), .o_ipaddr(@$(PREFIX)_ip_addr),\n\t\t.o_ping_hwmac(@$(PREFIX)_last_ping_hwmac),\n\t\t\t.o_ping_ipaddr(@$(PREFIX)_last_ping_ipaddr),\n\t\t// Wishbone port\n\t\t// {{{\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t// }}}\n\t\t// ifdef @$(DEVID)CPUTX_ACCESS\n\t\t// {{{\n\t\t.S_CPU_VALID(@$(PREFIX)cputx_valid),\n\t\t\t.S_CPU_READY(@$(PREFIX)cputx_ready),\n\t\t\t.S_CPU_DATA(@$(PREFIX)cputx_data),\n\t\t\t.S_CPU_BYTES(@$(PREFIX)cputx_bytes),\n\t\t\t.S_CPU_LAST(@$(PREFIX)cputx_last),\n\t\t\t.S_CPU_ABORT(@$(PREFIX)cputx_abort),\n\t\t// }}}\n`ifdef\tNETBUS_ACCESS\n\t\t// {{{\n\t\t.S_DBG_VALID(@$(PREFIX)bus_valid),\n\t\t\t.S_DBG_READY(@$(PREFIX)bus_ready),\n\t\t\t.S_DBG_DATA(@$(PREFIX)bus_pkdata),\n\t\t\t// .S_DBG_BYTES(@$(PREFIX)bus_bytes),\n\t\t\t.S_DBG_LAST(@$(PREFIX)bus_last),\n`else\n\t\t.S_DBG_VALID(1'b0),\n\t\t\t.S_DBG_READY(@$(PREFIX)_dbg_ready),\n\t\t\t.S_DBG_DATA(32'h0),\n\t\t\t.S_DBG_LAST(1'b1),\n`endif\n\t\t// }}}\n\t\t// Data interface\n\t\t// {{{\n\t\t.S_DATA_VALID(1'b0),\n\t\t\t.S_DATA_READY(ign_rxpkt_@$(PREFIX)_ready),\n\t\t\t.S_DATA_DATA(32'h0),\n\t\t\t.S_DATA_BYTES(2'h0),\n\t\t\t.S_DATA_LAST(1'b1),\n\t\t// }}}\n\t\t// ifdef @$(DEVID)CPURX_ACCESS\n\t\t// {{{\n\t\t.M_CPU_VALID(@$(PREFIX)cpurx_valid),\n\t\t\t.M_CPU_READY(@$(PREFIX)cpurx_ready),\n\t\t\t.M_CPU_DATA(@$(PREFIX)cpurx_data),\n\t\t\t.M_CPU_BYTES(@$(PREFIX)cpurx_bytes),\n\t\t\t.M_CPU_LAST(@$(PREFIX)cpurx_last),\n\t\t\t.M_CPU_ABORT(@$(PREFIX)cpurx_abort),\n\t\t// }}}\n\t\t// Debug IP/UDP RX packets\n\t\t// {{{\n\t\t.M_DBG_VALID(@$(PREFIX)_dbg_valid),\n\t\t\t.M_DBG_READY(@$(PREFIX)_dbg_ready),\n\t\t\t.M_DBG_DATA( @$(PREFIX)_dbg_data),\n\t\t\t.M_DBG_BYTES(@$(PREFIX)_dbg_bytes),\n\t\t\t.M_DBG_LAST( @$(PREFIX)_dbg_last),\n\t\t// }}}\n\t\t// Interface to top-level IOs\n\t\t// {{{\n\t\t.o_net_reset_n(o_@$(PREFIX)_reset_n),\n\t\t.i_net_rx_clk(i_@$(PREFIX)_rx_clk), .i_net_rx_dv(i_@$(PREFIX)_rx_dv),\n\t\t.i_net_rx_err(i_@$(PREFIX)_rx_err), .i_net_rxd(i_@$(PREFIX)_rxd),\n\t\t//\n\t\t.i_net_tx_clk(i_net_tx_clk), .o_net_tx_ck(o_@$(PREFIX)_tx_clk),\n\t\t.o_net_tx_ctl(o_@$(PREFIX)_tx_ctl), .o_net_txd(o_@$(PREFIX)_txd),\n\t\t// }}}\n\t\t.o_debug_clk(@$(PREFIX)_debug_clk),\n\t\t.o_debug(@$(PREFIX)_debug)\n\t\t// }}}\n\t);\n\n`ifndef\tNETBUS_ACCESS\n\t// {{{\n\tassign\t@$(PREFIX)_dbg_ready = 1'b1;\n\t// Verilator lint_off UNUSED\n\twire\tunused_@$(PREFIX)_dbgrx;\n\tassign\tunused_@$(PREFIX)_dbgrx = &{ 1'b0,\n\t\t\t@$(PREFIX)_dbg_valid, @$(PREFIX)_dbg_data,\n\t\t\t\t@$(PREFIX)_dbg_bytes, @$(PREFIX)_dbg_last };\n\t// Verilator lint_on  UNUSED\n\t// }}}\n`endif\n\n`ifndef\t@$(DEVID)CPURX_ACCESS\n\t// {{{\n\tassign\t@$(PREFIX)cpurx_ready = 1'b1;\n\t// Verilator lint_off UNUSED\n\twire\tunused_@$(PREFIX)_cpu_rx;\n\tassign\tunused_@$(PREFIX)_cpu_rx = &{ 1'b0,\n\t\t\t@$(PREFIX)cpurx_valid, @$(PREFIX)cpurx_data,\n\t\t\t\t@$(PREFIX)cpurx_bytes,\n\t\t\t@$(PREFIX)cpurx_abort, @$(PREFIX)cpurx_last };\n\t// Verilator lint_on  UNUSED\n\t// }}}\n`endif\n\n`ifndef\t@$(DEVID)CPUTX_ACCESS\n\t// {{{\n\tassign\t@$(PREFIX)cputx_valid = 1'b0;\n\tassign\t@$(PREFIX)cputx_data  = 32'h0;\n\tassign\t@$(PREFIX)cputx_bytes =  2'h0;\n\tassign\t@$(PREFIX)cputx_last  =  1'b1;\n\tassign\t@$(PREFIX)cputx_abort =  1'b0;\n\t// }}}\n`endif\n\n\n\t// }}}\n@REGDEFS.H.INCLUDE=\n#ifndef\tFPGAPORT\n#define\tFPGAPORT\t@$(BASEPORT)\n#define\tUARTDBGPORT\t@$(UARTDBGPORT)\n#define\tUARTPORT\t@$(UARTPORT)\n#define\tUDP_DBGPORT\t@$(UDPDBGPORT)\n#define\tUDP_DATAPORT\t@$(DATAPORT)\n#endif\n@REGS.N=19\n@REGS.NOTE=// Meganet register definitions\n@REGS.0=   0 R_@$(DEVID)_RXCMD    @$(DEVID)RX\n@REGS.1=   1 R_@$(DEVID)_TXCMD    @$(DEVID)TX\n@REGS.2=   2 R_@$(DEVID)_MACHI    @$(DEVID)MACHI\n@REGS.3=   3 R_@$(DEVID)_MACLO    @$(DEVID)MACLO\n@REGS.4=   4 R_@$(DEVID)_IPADDR   @$(DEVID)IPADDR @$(DEVID)IP\n@REGS.5=   5 R_@$(DEVID)_RXMISS   @$(DEVID)MISS\n@REGS.6=   6 R_@$(DEVID)_RXERR    @$(DEVID)ERR\n@REGS.7=   7 R_@$(DEVID)_RXCRC    @$(DEVID)CRCER\n@REGS.8=   8 R_@$(DEVID)_DBGSEL   @$(DEVID)DBGSL\n@REGS.9=   8 R_@$(DEVID)_RXPKTS   @$(DEVID)RXPKT\n@REGS.10=  9 R_@$(DEVID)_ARPRX    @$(DEVID)ARPRX\n@REGS.11= 10 R_@$(DEVID)_ICMPRX   @$(DEVID)ICMRX\n@REGS.12= 11 R_@$(DEVID)_TXPKTS   @$(DEVID)TXPKT\n@REGS.13= 12 R_@$(DEVID)_ARPTX    @$(DEVID)ARPTX\n@REGS.14= 13 R_@$(DEVID)_ICMPTX   @$(DEVID)ICMTX\n@REGS.15= 14 R_@$(DEVID)_DATATX   @$(DEVID)DATTX\n@REGS.16= 15 R_@$(DEVID)_TXABORTS @$(DEVID)ABRTS\n@REGS.17= 16 R_@$(DEVID)_DBGRX    @$(DEVID)DBGRX\n@REGS.18= 17 R_@$(DEVID)_DBGTX    @$(DEVID)DBGTX\n\n@BDEF.INCLUDE=\n#ifndef\tUDP_DBGPORT\n#define\tUDP_DBGPORT\t@$(UDPDBGPORT)\n#define\tUDP_DATAPORT\t@$(DATAPORT)\n#endif\n@BDEF.DEFN=\n// Network stream/packet interface\n// {{{\n#ifndef\tENETSTREAM_H\n#define\tENETSTREAM_H\ntypedef struct ENETSTREAM_S {\n        unsigned        n_rxcmd, n_txcmd;\n        unsigned long   n_mac;\n\tunsigned\tn_ipaddr;\n        unsigned        n_rxmiss, n_rxerr, n_rxcrc;\n\t//\n\tunsigned\tn_rxpkt, n_rxarp, n_rxicmp;\n\tunsigned\tn_txpkt, n_txarp, n_txicmp;\n\tunsigned\tn_data, n_aborts;\n\tunsigned\tn_rxdbg, n_txdbg;\n} ENETSTREAM;\n#endif\n// }}}\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE=ENETSTREAM\n@BDEF.OSDEF=_BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((ENETSTREAM *)@$[0x%08x](REGBASE));\n\n@RTL.MAKE.GROUP=ENET\n@RTL.MAKE.SUBD=ethernet\n@RTL.MAKE.FILES= enetstream.v\n        addecrc.v addemac.v addepad.v addepreamble.v\n        rxecrc.v rxehwmac.v rxeipchk.v rxemin.v rxepacket.v rxepreambl.v\n\taxinwidth.v axincdc.v pktgate.v txespeed.v xiddr.v\n@CLOCK.NAME=@$(PREFIX)_rx_clk\n@$CLOCK.FREQUENCY=125000000\n@SIM.CLOCK=@$(PREFIX)_rx_clk\n@SIM.INCLUDE=\n#include \"netsim.h\"\n@SIM.DEFNS=\n\t\tNETSIM\t*m_@$(PREFIX);\n@SIM.INIT=\n\t\t// Network init\n\t\t// {{{\n\t\tm_@$(PREFIX) = new NETSIM(); // DBGPORT: @$(UDPDBGPORT), DATAPORT: @$(DATAPORT);\n\t\tm_@$(PREFIX)->external_mac[0] = 0xde;\n\t\tm_@$(PREFIX)->external_mac[1] = 0xad;\n\t\tm_@$(PREFIX)->external_mac[2] = 0xbe;\n\t\tm_@$(PREFIX)->external_mac[3] = 0xef;\n\t\tm_@$(PREFIX)->external_mac[4] = 0xda;\n\t\tm_@$(PREFIX)->external_mac[5] = 0xd0 | (@$(HWMAC.5) & 0x0f);\n\t\tm_@$(PREFIX)->external_ip[0] = 127;\n\t\tm_@$(PREFIX)->external_ip[1] = 0;\n\t\tm_@$(PREFIX)->external_ip[2] = 0;\n\t\tm_@$(PREFIX)->external_ip[3] = 1;\n\t\tm_@$(PREFIX)->local_mac[0] = 0x@$[%02x](HWMAC.0) & 0x0ff;\n\t\tm_@$(PREFIX)->local_mac[1] = 0x@$[%02x](HWMAC.1) & 0x0ff;\n\t\tm_@$(PREFIX)->local_mac[2] = 0x@$[%02x](HWMAC.2) & 0x0ff;\n\t\tm_@$(PREFIX)->local_mac[3] = 0x@$[%02x](HWMAC.3) & 0x0ff;\n\t\tm_@$(PREFIX)->local_mac[4] = 0x@$[%02x](HWMAC.4) & 0x0ff;\n\t\tm_@$(PREFIX)->local_mac[5] = 0x@$[%02x](HWMAC.5) & 0x0ff;\n\t\tm_@$(PREFIX)->local_ip[0] = 0x@$[%02x](IPADDR.0) & 0x0ff; // @$[%3d](IPADDR.0)\n\t\tm_@$(PREFIX)->local_ip[1] = 0x@$[%02x](IPADDR.1) & 0x0ff; // @$[%3d](IPADDR.1)\n\t\tm_@$(PREFIX)->local_ip[2] = 0x@$[%02x](IPADDR.2) & 0x0ff; // @$[%3d](IPADDR.2)\n\t\tm_@$(PREFIX)->local_ip[3] = 0x@$[%02x](IPADDR.3) & 0x0ff; // @$[%3d](IPADDR.3)\n\t\tm_@$(PREFIX)->local_ipu = 0x@$[%02x](IPADDR.0)@$[%02x](IPADDR.1)@$[%02x](IPADDR.2)@$[%02x](IPADDR.3);\n\t\t// }}}\n@SIM.TICK=\n\t\t// Simulate the network\n\t\t// {{{\n\t\t{\n\t\t\tunsigned rxtmp = (*m_@$(PREFIX))(m_core->o_net_reset_n,\n\t\t\t\t\tm_core->o_@$(PREFIX)_tx_ctl,\n\t\t\t\t\tm_core->o_@$(PREFIX)_txd);\n\n\t\t\tm_core->i_@$(PREFIX)_rx_err = 0;\n\t\t\tif (rxtmp & 0x0100) {\n\t\t\t\tm_core->i_@$(PREFIX)_rx_dv  = 1;\n\t\t\t\tm_core->i_@$(PREFIX)_rxd = rxtmp & 0x0ff;\n\t\t\t} else {\n\t\t\t\tm_core->i_@$(PREFIX)_rx_dv  = 0;\n\t\t\t\tm_core->i_@$(PREFIX)_rxd = 0x044;\n\t\t\t}\n\t\t}\n\t\t// }}}\n##\n@XDC.INSERT=\n################################################################################\n#\n# MegaNET\n# {{{\ncreate_clock -period 8.0 -name NETRX -waveform { 0.0 4.0 } -add [get_ports {i_net_rx_clk} ];\n\n## All clocks\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *afifo*/wgray_r*}] -to [ get_cells -hier -filter {NAME =~ *afifo*/wgray_cross*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *afifo*/rgray_r*}] -to [ get_cells -hier -filter {NAME =~ *afifo*/rgray_cross*}] 8.0\n\n## CLK -> NETTX\n## set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *sdrami/r_sys_reset*}] -to [ get_cells -hier -filter {NAME =~ *pre_tx_reset*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/o_net_reset*}]  -to [ get_cells -hier -filter {NAME =~*n_tx_reset*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/*afifo*}]        -to [ get_cells -hier -filter {NAME =~*u_@$(PREFIX)/*afifo*/GEN_REGISTERED_READ.o_rd_data*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *sdrami/r_sys_reset*}]    -to [ get_cells -hier -filter {NAME =~*net_core/preq_tx_reset*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/o_net_reset*}]  -to [ get_cells -hier -filter {NAME =~*net_core/q_tx_reset*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/net_core/tfrtxspd/a_req*}]  -to [ get_cells -hier -filter {NAME =~*u_@$(PREFIX)/net_core/tfrtxspd/b_pipe*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/net_core/tfrtxspd/a_data*}] -to [ get_cells -hier -filter {NAME =~*u_@$(PREFIX)/net_core/tfrtxspd/o_b_data*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/hw_mac*}]       -to [ get_cells -hier -filter {NAME =~*txmaci/r_hw*}] 8.0\n\n## NETTX -> CLK\n## set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_adc/b_reset_n*}] -to [ get_cells -hier -filter {NAME =~ *u_adc/b_last*}] 8.0\n## set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_adc/b_reset_n*}] -to [ get_cells -hier -filter {NAME =~ *u_adc/b_pipe*}] 8.0\n## set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_adc/b_reset_n*}] -to [ get_cells -hier -filter {NAME =~ *u_adc/b_req*}] 8.0\n## set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_adc/b_reset_n*}] -to [ get_cells -hier -filter {NAME =~ *u_adc/o_b_valid*}] 8.0\n# set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/tx_spd*}] -to [ get_cells -hier -filter {NAME =~ *tfrtxspd/a_data*}] 8.0\n# set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/tx_spd*}] -to [ get_cells -hier -filter {NAME =~ *net_core/o_wb_data*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/tfrtxspd/b_last*}] -to [ get_cells -hier -filter {NAME =~ *tfrtxspd/a_pipe*}] 8.0\n\n## NETTX -> NETTX_D\n# set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/txspdi/o_ck*}] -to [ get_cells -hier -filter {NAME =~ txck/ODDR*}] 2.0\n\n## NETTX -> NETRX\n\n## CLK -> NETRX\n# set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *sdrami/r_sys_reset*}]       -to [ get_cells -hier -filter {NAME =~ *net_core/pre_rx_reset*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *sdrami/r_sys_reset*}]       -to [ get_cells -hier -filter {NAME =~ *net_core/preq_rx_reset*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *sdrami/r_sys_reset*}]       -to [ get_cells -hier -filter {NAME =~ *tfrrxspd/a_ack*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *sdrami/r_sys_reset*}]       -to [ get_cells -hier -filter {NAME =~*tfrrxspd/a_pipe*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *sdrami/r_sys_reset*}]       -to [ get_cells -hier -filter {NAME =~ *tfrrxspd/a_req*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/o_net_reset_n*}]   -to [ get_cells -hier -filter {NAME =~ *n_rx_reset*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/o_net_reset_n*}]   -to [ get_cells -hier -filter {NAME =~ *q_rx_reset*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/tfrrxspd/b_last*}] -to [ get_cells -hier -filter {NAME =~ *tfrrxspd/a_pipe*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/my_ipaddr*}]       -to [ get_cells -hier -filter {NAME =~*o_no_match*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/my_ipaddr*}]       -to [ get_cells -hier -filter {NAME =~*o_match*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/my_ipaddr*}]       -to [ get_cells -hier -filter {NAME =~*rxipci/o_err*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/my_ipaddr*}]       -to [ get_cells -hier -filter {NAME =~*rxipci/o_err*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/hw_mac*}]          -to [ get_cells -hier -filter {NAME =~*rxmaci/r_hwmac*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/n_rx_reset*}]      -to [ get_cells -hier -filter {NAME =~*u_@$(PREFIX)/net_core/tfr_rxipaddr/b_last*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/n_rx_reset*}]      -to [ get_cells -hier -filter {NAME =~*u_@$(PREFIX)/net_core/tfr_rxipaddr/b_pipe*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/n_rx_reset*}]      -to [ get_cells -hier -filter {NAME =~*u_@$(PREFIX)/net_core/tfr_rxipaddr/b_req*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *tfr_rxipaddr/b_last*}]      -to [ get_cells -hier -filter {NAME =~*tfr_rxipaddr/a_pipe*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *tfr_rxipaddr/a_data*}]      -to [ get_cells -hier -filter {NAME =~*tfr_rxipaddr/o_b_data*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *tfr_rxipaddr/a_req*}]       -to [ get_cells -hier -filter {NAME =~*tfr_rxipaddr/o_b_data*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *tfr_rxipaddr/a_req*}]       -to [ get_cells -hier -filter {NAME =~*tfr_rxipaddr/b_pipe*}] 8.0\n\n# NETRX ->CLK\n#\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/net_core/tfrrxspd/a_data*}] -to [ get_cells -hier -filter {NAME =~ *net_core/tfrrxspd/o_b_data*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/net_core/n_rx_reset*}]      -to [ get_cells -hier -filter {NAME =~ *net_core/tfrrxspd/b_last*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/net_core/n_rx_reset*}]      -to [ get_cells -hier -filter {NAME =~ *net_core/tfrrxspd/b_pipe*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/net_core/n_rx_reset*}]      -to [ get_cells -hier -filter {NAME =~ *net_core/tfrrxspd/b_req*}] 8.0\n## set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/net_core/txclk_check*}]  -to [ get_cells -hier -filter {NAME =~ *net_core/net_reset_timer*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/net_core/n_rx_crcerr*}]     -to [ get_cells -hier -filter {NAME =~ *net_core/rx_crc_pipe*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/net_core/tfrrxspd/a*}]      -to [ get_cells -hier -filter {NAME =~ *net_core/tfrrxspd/b*}] 8.0\n## set_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/net_core/rxclk_check*}]  -to [ get_cells -hier -filter {NAME =~ *net_core/net_reset_timer*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/net_core/n_rx_miss*}]       -to [ get_cells -hier -filter {NAME =~ *net_core/rx_miss_pipe*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/tfr_*/a_data*}]       -to [ get_cells -hier -filter {NAME =~ *u_@$(PREFIX)/tfr*/o_b_data*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/tfr_*/a_req*}]       -to [ get_cells -hier -filter {NAME =~ *u_@$(PREFIX)/tfr*/b_pipe*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/tfr_*/b_last*}]       -to [ get_cells -hier -filter {NAME =~ *u_@$(PREFIX)/tfr*/a_pipe*}] 8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *u_@$(PREFIX)/net_core/n_rx_err*}]       -to [ get_cells -hier -filter {NAME =~ *u_@$(PREFIX)/net_core/rx_err_pipe*}] 8.0\n##\n## ARP\n## {{{\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/hw_mac*}]          -to [ get_cells -hier -filter {NAME =~*arp/M_AXIN_DATA*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/hw_mac*}]          -to [ get_cells -hier -filter {NAME =~*u_@$(PREFIX)/u_arp/M_AXIN_DATA*}] 8.0\nset_max_delay   -datapath_only -from [get_cells -hier -filter {NAME=~ *net_core/my_ipaddr*}]       -to [ get_cells -hier -filter {NAME =~*u_@$(PREFIX)/u_arp/M_AXIN_DATA*}] 8.0\n## }}}\n## ICMP\n## {{{\n## }}}\n##\n# }}}\n"
  },
  {
    "path": "auto-data/nexysv.xdc",
    "content": "### This file is a general .xdc for the Nexys Video Rev. A\r\n### To use it in a project:\r\n### - uncomment the lines corresponding to used pins\r\n### - rename the used ports (in each line, after get_ports) according to the top level signal names in the project\r\n\r\n\r\n## Clock Signal\r\nset_property -dict {PACKAGE_PIN R4 IOSTANDARD LVCMOS33} [get_ports i_clk]\r\ncreate_clock -period 10.000 -name INCLK -waveform {0.000 5.000} -add [get_ports i_clk]\r\n\r\n\r\n## FMC Transceiver clocks (Must be set to value provided by Mezzanine card, currently set to 156.25 MHz)\r\n## Note: This clock is attached to a MGTREFCLK pin\r\n#set_property -dict { PACKAGE_PIN E6 } [get_ports { GTP_CLK_N }];\r\n#set_property -dict { PACKAGE_PIN F6 } [get_ports { GTP_CLK_P }];\r\n#create_clock -add -name gtpclk0_pin -period 6.400 -waveform {0 3.200} [get_ports {GTP_CLK_P}];\r\n#set_property -dict { PACKAGE_PIN E10 } [get_ports { FMC_MGT_CLK_N }];\r\n#set_property -dict { PACKAGE_PIN F10 } [get_ports { FMC_MGT_CLK_P }];\r\n#create_clock -add -name mgtclk1_pin -period 6.400 -waveform {0 3.200} [get_ports {FMC_MGT_CLK_P}];\r\n\r\n\r\n## LEDs\r\n# set_property -dict {PACKAGE_PIN T14 IOSTANDARD LVCMOS25} [get_ports {o_led[0]}]\r\n# set_property -dict {PACKAGE_PIN T15 IOSTANDARD LVCMOS25} [get_ports {o_led[1]}]\r\n# set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS25} [get_ports {o_led[2]}]\r\n# set_property -dict {PACKAGE_PIN U16 IOSTANDARD LVCMOS25} [get_ports {o_led[3]}]\r\n# set_property -dict {PACKAGE_PIN V15 IOSTANDARD LVCMOS25} [get_ports {o_led[4]}]\r\n# set_property -dict {PACKAGE_PIN W16 IOSTANDARD LVCMOS25} [get_ports {o_led[5]}]\r\n# set_property -dict {PACKAGE_PIN W15 IOSTANDARD LVCMOS25} [get_ports {o_led[6]}]\r\n# set_property -dict {PACKAGE_PIN Y13 IOSTANDARD LVCMOS25} [get_ports {o_led[7]}]\r\n\r\n\r\n## Buttons\r\n# set_property -dict {PACKAGE_PIN B22 IOSTANDARD LVCMOS12} [get_ports i_btnc]\r\n# set_property -dict {PACKAGE_PIN D22 IOSTANDARD LVCMOS12} [get_ports i_btnd]\r\n# set_property -dict {PACKAGE_PIN C22 IOSTANDARD LVCMOS12} [get_ports i_btnl]\r\n# set_property -dict {PACKAGE_PIN D14 IOSTANDARD LVCMOS12} [get_ports i_btnr]\r\n# set_property -dict {PACKAGE_PIN F15 IOSTANDARD LVCMOS12} [get_ports i_btnu]\r\n# set_property -dict {PACKAGE_PIN G4  IOSTANDARD LVCMOS12} [get_ports i_cpu_resetn]\r\n\r\n\r\n## Switches\r\n# set_property -dict {PACKAGE_PIN E22 IOSTANDARD LVCMOS12} [get_ports {i_sw[0]}]\r\n# set_property -dict {PACKAGE_PIN F21 IOSTANDARD LVCMOS12} [get_ports {i_sw[1]}]\r\n# set_property -dict {PACKAGE_PIN G21 IOSTANDARD LVCMOS12} [get_ports {i_sw[2]}]\r\n# set_property -dict {PACKAGE_PIN G22 IOSTANDARD LVCMOS12} [get_ports {i_sw[3]}]\r\n# set_property -dict {PACKAGE_PIN H17 IOSTANDARD LVCMOS12} [get_ports {i_sw[4]}]\r\n# set_property -dict {PACKAGE_PIN J16 IOSTANDARD LVCMOS12} [get_ports {i_sw[5]}]\r\n# set_property -dict {PACKAGE_PIN K13 IOSTANDARD LVCMOS12} [get_ports {i_sw[6]}]\r\n# set_property -dict {PACKAGE_PIN M17 IOSTANDARD LVCMOS12} [get_ports {i_sw[7]}]\r\n\r\n\r\n## OLED Display\r\n# set_property -dict { PACKAGE_PIN W22   IOSTANDARD LVCMOS33 } [get_ports { o_oled_dcn      }]; #IO_L7N_T1_D10_14 Sch=oled_dc SPI select port\r\n# set_property -dict { PACKAGE_PIN U21   IOSTANDARD LVCMOS33 } [get_ports { o_oled_reset_n  }]; #IO_L4N_T0_D05_14 Sch=oled_res RESET\r\n# set_property -dict { PACKAGE_PIN W21   IOSTANDARD LVCMOS33 } [get_ports { o_oled_sck      }]; #IO_L7P_T1_D09_14 Sch=oled_sclk SPI Clk port\r\n# set_property -dict { PACKAGE_PIN Y22   IOSTANDARD LVCMOS33 } [get_ports { o_oled_mosi     }]; #IO_L9N_T1_DQS_D13_14 Sch=oled_sdin Data port\r\n# set_property -dict { PACKAGE_PIN P20   IOSTANDARD LVCMOS33 } [get_ports { o_oled_panel_en }]; #IO_0_14 Sch=oled_vbat VBAT\r\n# set_property -dict { PACKAGE_PIN V22   IOSTANDARD LVCMOS33 } [get_ports { o_oled_logic_en }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=oled_vdd VDD\r\n\r\n\r\n## HDMI in\r\n# set_property -dict { PACKAGE_PIN AA5   IOSTANDARD LVCMOS33    } [get_ports   io_hdmi_in_cec   ]\r\n# set_property -dict { PACKAGE_PIN W4    IOSTANDARD TMDS_33     } [get_ports   i_hdmi_in_clk_n  ]\r\n# set_property -dict { PACKAGE_PIN V4    IOSTANDARD TMDS_33     } [get_ports   i_hdmi_in_clk_p  ]\r\n# set_property -dict { PACKAGE_PIN AB12  IOSTANDARD LVCMOS25    } [get_ports   o_hdmi_in_hpa    ]\r\n# set_property -dict { PACKAGE_PIN Y4    IOSTANDARD LVCMOS33    } [get_ports   io_hdmi_in_scl   ]\r\n# set_property -dict { PACKAGE_PIN AB5   IOSTANDARD LVCMOS33    } [get_ports   io_hdmi_in_sda   ]\r\n# set_property -dict { PACKAGE_PIN R3    IOSTANDARD LVCMOS33    } [get_ports   o_hdmi_in_txen   ]\r\n# set_property -dict { PACKAGE_PIN AA3   IOSTANDARD TMDS_33     } [get_ports { i_hdmi_in_n[0] } ]; #IO_L9N_T1_DQS_34 Sch=hdmi_rx_n[0]\r\n# set_property -dict { PACKAGE_PIN Y3    IOSTANDARD TMDS_33     } [get_ports { i_hdmi_in_p[0] } ]; #IO_L9P_T1_DQS_34 Sch=hdmi_rx_p[0]\r\n# set_property -dict { PACKAGE_PIN Y2    IOSTANDARD TMDS_33     } [get_ports { i_hdmi_in_n[1] } ]; #IO_L4N_T0_34 Sch=hdmi_rx_n[1]\r\n# set_property -dict { PACKAGE_PIN W2    IOSTANDARD TMDS_33     } [get_ports { i_hdmi_in_p[1] } ]; #IO_L4P_T0_34 Sch=hdmi_rx_p[1]\r\n# set_property -dict { PACKAGE_PIN V2    IOSTANDARD TMDS_33     } [get_ports { i_hdmi_in_n[2] } ]; #IO_L2N_T0_34 Sch=hdmi_rx_n[2]\r\n# set_property -dict { PACKAGE_PIN U2    IOSTANDARD TMDS_33     } [get_ports { i_hdmi_in_p[2] } ]; #IO_L2P_T0_34 Sch=hdmi_rx_p[2]\r\n\r\n\r\n## HDMI out\r\n# set_property -dict { PACKAGE_PIN AA4   IOSTANDARD LVCMOS33    } [get_ports   io_hdmi_out_cec  ]\r\n# set_property -dict { PACKAGE_PIN U1    IOSTANDARD TMDS_33     } [get_ports   o_hdmi_out_clk_n ]\r\n# set_property -dict { PACKAGE_PIN T1    IOSTANDARD TMDS_33     } [get_ports   o_hdmi_out_clk_p ]\r\n# set_property -dict { PACKAGE_PIN AB13  IOSTANDARD LVCMOS25    } [get_ports   i_hdmi_out_hpd_n   ]\r\n# set_property -dict { PACKAGE_PIN U3    IOSTANDARD LVCMOS33    } [get_ports { io_hdmi_out_scl }]; #IO_L6P_T0_34 Sch=hdmi_tx_rscl\r\n# set_property -dict { PACKAGE_PIN V3    IOSTANDARD LVCMOS33    } [get_ports { io_hdmi_out_sda }]; #IO_L6N_T0_VREF_34 Sch=hdmi_tx_rsda\r\n# set_property -dict { PACKAGE_PIN Y1    IOSTANDARD TMDS_33     } [get_ports { o_hdmi_out_n[0] }]; #IO_L5N_T0_34 Sch=hdmi_tx_n[0]\r\n# set_property -dict { PACKAGE_PIN W1    IOSTANDARD TMDS_33     } [get_ports { o_hdmi_out_p[0] }]; #IO_L5P_T0_34 Sch=hdmi_tx_p[0]\r\n# set_property -dict { PACKAGE_PIN AB1   IOSTANDARD TMDS_33     } [get_ports { o_hdmi_out_n[1] }]; #IO_L7N_T1_34 Sch=hdmi_tx_n[1]\r\n# set_property -dict { PACKAGE_PIN AA1   IOSTANDARD TMDS_33     } [get_ports { o_hdmi_out_p[1] }]; #IO_L7P_T1_34 Sch=hdmi_tx_p[1]\r\n# set_property -dict { PACKAGE_PIN AB2   IOSTANDARD TMDS_33     } [get_ports { o_hdmi_out_n[2] }]; #IO_L8N_T1_34 Sch=hdmi_tx_n[2]\r\n# set_property -dict { PACKAGE_PIN AB3   IOSTANDARD TMDS_33     } [get_ports { o_hdmi_out_p[2] }]; #IO_L8P_T1_34 Sch=hdmi_tx_p[2]\r\n\r\n\r\n## Display Port\r\n#set_property -dict { PACKAGE_PIN AB10  IOSTANDARD LVDS     } [get_ports { dp_tx_aux_n }]; #IO_L8N_T1_13 Sch=dp_tx_aux_n\r\n#set_property -dict { PACKAGE_PIN AA11  IOSTANDARD LVDS     } [get_ports { dp_tx_aux_n }]; #IO_L9N_T1_DQS_13 Sch=dp_tx_aux_n\r\n#set_property -dict { PACKAGE_PIN AA9   IOSTANDARD LVDS     } [get_ports { dp_tx_aux_p }]; #IO_L8P_T1_13 Sch=dp_tx_aux_p\r\n#set_property -dict { PACKAGE_PIN AA10  IOSTANDARD LVDS     } [get_ports { dp_tx_aux_p }]; #IO_L9P_T1_DQS_13 Sch=dp_tx_aux_p\r\n#set_property -dict { PACKAGE_PIN N15   IOSTANDARD LVCMOS33 } [get_ports { dp_tx_hpd }]; #IO_25_14 Sch=dp_tx_hpd\r\n\r\n\r\n## Audio Codec\r\n#set_property -dict { PACKAGE_PIN T4    IOSTANDARD LVCMOS33 } [get_ports { ac_adc_sdata }]; #IO_L13N_T2_MRCC_34 Sch=ac_adc_sdata\r\n#set_property -dict { PACKAGE_PIN T5    IOSTANDARD LVCMOS33 } [get_ports { ac_bclk }]; #IO_L14P_T2_SRCC_34 Sch=ac_bclk\r\n#set_property -dict { PACKAGE_PIN W6    IOSTANDARD LVCMOS33 } [get_ports { ac_dac_sdata }]; #IO_L15P_T2_DQS_34 Sch=ac_dac_sdata\r\n#set_property -dict { PACKAGE_PIN U5    IOSTANDARD LVCMOS33 } [get_ports { ac_lrclk }]; #IO_L14N_T2_SRCC_34 Sch=ac_lrclk\r\n#set_property -dict { PACKAGE_PIN U6    IOSTANDARD LVCMOS33 } [get_ports { ac_mclk }]; #IO_L16P_T2_34 Sch=ac_mclk\r\n\r\n\r\n## Pmod header JA -- We'll use the bottom for GPS\r\n#set_property -dict { PACKAGE_PIN AB22  IOSTANDARD LVCMOS33 } [get_ports { ja[0] }]; #IO_L10N_T1_D15_14 Sch=ja[1]\r\n#set_property -dict { PACKAGE_PIN AB21  IOSTANDARD LVCMOS33 } [get_ports { ja[1] }]; #IO_L10P_T1_D14_14 Sch=ja[2]\r\n#set_property -dict { PACKAGE_PIN AB20  IOSTANDARD LVCMOS33 } [get_ports { ja[2] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=ja[3]\r\n#set_property -dict { PACKAGE_PIN AB18  IOSTANDARD LVCMOS33 } [get_ports { ja[3] }]; #IO_L17N_T2_A13_D29_14 Sch=ja[4]\r\n# set_property -dict {PACKAGE_PIN Y21  IOSTANDARD LVCMOS33} [get_ports i_gps_3df]\r\n# set_property -dict {PACKAGE_PIN AA21 IOSTANDARD LVCMOS33} [get_ports o_gpsu_tx]\r\n# set_property -dict {PACKAGE_PIN AA20 IOSTANDARD LVCMOS33} [get_ports i_gpsu_rx]\r\n# set_property -dict {PACKAGE_PIN AA18 IOSTANDARD LVCMOS33} [get_ports i_gps_pps]\r\n\r\n\r\n## Pmod header JB --- Reserved for the Differential PMod Challenge\r\n#set_property -dict { PACKAGE_PIN V9    IOSTANDARD LVCMOS33 } [get_ports { jb[0] }]; #IO_L21P_T3_DQS_34 Sch=jb_p[1]\r\n#set_property -dict { PACKAGE_PIN V8    IOSTANDARD LVCMOS33 } [get_ports { jb[1] }]; #IO_L21N_T3_DQS_34 Sch=jb_n[1]\r\n#set_property -dict { PACKAGE_PIN V7    IOSTANDARD LVCMOS33 } [get_ports { jb[2] }]; #IO_L19P_T3_34 Sch=jb_p[2]\r\n#set_property -dict { PACKAGE_PIN W7    IOSTANDARD LVCMOS33 } [get_ports { jb[3] }]; #IO_L19N_T3_VREF_34 Sch=jb_n[2]\r\n#set_property -dict { PACKAGE_PIN W9    IOSTANDARD LVCMOS33 } [get_ports { jb[4] }]; #IO_L24P_T3_34 Sch=jb_p[3]\r\n#set_property -dict { PACKAGE_PIN Y9    IOSTANDARD LVCMOS33 } [get_ports { jb[5] }]; #IO_L24N_T3_34 Sch=jb_n[3]\r\n#set_property -dict { PACKAGE_PIN Y8    IOSTANDARD LVCMOS33 } [get_ports { jb[6] }]; #IO_L23P_T3_34 Sch=jb_p[4]\r\n#set_property -dict { PACKAGE_PIN Y7    IOSTANDARD LVCMOS33 } [get_ports { jb[7] }]; #IO_L23N_T3_34 Sch=jb_n[4]\r\n\r\n\r\n## Pmod header JC  -- We'll use the bottom for the PModMIC\r\n#set_property -dict { PACKAGE_PIN Y6    IOSTANDARD LVCMOS33 } [get_ports { jc[0] }]; #IO_L18P_T2_34 Sch=jc_p[1]\r\n#set_property -dict { PACKAGE_PIN AA6   IOSTANDARD LVCMOS33 } [get_ports { jc[1] }]; #IO_L18N_T2_34 Sch=jc_n[1]\r\n#set_property -dict { PACKAGE_PIN AA8   IOSTANDARD LVCMOS33 } [get_ports { jc[2] }]; #IO_L22P_T3_34 Sch=jc_p[2]\r\n#set_property -dict { PACKAGE_PIN AB8   IOSTANDARD LVCMOS33 } [get_ports { jc[3] }]; #IO_L22N_T3_34 Sch=jc_n[2]\r\n# set_property -dict { PACKAGE_PIN R6    IOSTANDARD LVCMOS33 } [get_ports { o_mic_csn }]; #IO_L17P_T2_34 Sch=jc_p[3]\r\n# set_property -dict { PACKAGE_PIN T6    IOSTANDARD LVCMOS33 } [get_ports { jc[5] }]; #IO_L17N_T2_34 Sch=jc_n[3]\r\n# set_property -dict { PACKAGE_PIN AB7   IOSTANDARD LVCMOS33 } [get_ports { i_mic_din }]; #IO_L20P_T3_34 Sch=jc_p[4]\r\n# set_property -dict { PACKAGE_PIN AB6   IOSTANDARD LVCMOS33 } [get_ports { o_mic_sck }]; #IO_L20N_T3_34 Sch=jc_n[4]\r\n\r\n\r\n## XADC Header\r\n#set_property -dict { PACKAGE_PIN J14   IOSTANDARD LVCMOS33 } [get_ports { xa_p[0] }]; #IO_L3P_T0_DQS_AD1P_15 Sch=xa_p[1]\r\n#set_property -dict { PACKAGE_PIN H14   IOSTANDARD LVCMOS33 } [get_ports { xa_n[0] }]; #IO_L3N_T0_DQS_AD1N_15 Sch=xa_n[1]\r\n#set_property -dict { PACKAGE_PIN H13   IOSTANDARD LVCMOS33 } [get_ports { xa_p[1] }]; #IO_L1P_T0_AD0P_15 Sch=xa_p[2]\r\n#set_property -dict { PACKAGE_PIN G13   IOSTANDARD LVCMOS33 } [get_ports { xa_n[1] }]; #IO_L1N_T0_AD0N_15 Sch=xa_n[2]\r\n#set_property -dict { PACKAGE_PIN G15   IOSTANDARD LVCMOS33 } [get_ports { xa_p[2] }]; #IO_L2P_T0_AD8P_15 Sch=xa_p[3]\r\n#set_property -dict { PACKAGE_PIN G16   IOSTANDARD LVCMOS33 } [get_ports { xa_n[2] }]; #IO_L2N_T0_AD8N_15 Sch=xa_n[3]\r\n#set_property -dict { PACKAGE_PIN J15   IOSTANDARD LVCMOS33 } [get_ports { xa_p[3] }]; #IO_L5P_T0_AD9P_15 Sch=xa_p[4]\r\n#set_property -dict { PACKAGE_PIN H15   IOSTANDARD LVCMOS33 } [get_ports { xa_n[3] }]; #IO_L5N_T0_AD9N_15 Sch=xa_n[4]\r\n\r\n\r\n## UART\r\n# set_property -dict {PACKAGE_PIN AA19 IOSTANDARD LVCMOS33 } [get_ports o_host_uart_tx ]\r\n# set_property -dict {PACKAGE_PIN V18  IOSTANDARD LVCMOS33 } [get_ports i_host_uart_rx ]\r\n\r\n\r\n## Ethernet\r\n#set_property -dict { PACKAGE_PIN Y14   IOSTANDARD LVCMOS25 } [get_ports { eth_int_b }]; #IO_L6N_T0_VREF_13 Sch=eth_int_b\r\n# set_property -dict {PACKAGE_PIN AA16 IOSTANDARD LVCMOS25} [get_ports o_eth_mdclk]\r\n# set_property -dict {PACKAGE_PIN Y16 IOSTANDARD LVCMOS25} [get_ports io_eth_mdio]\r\n#set_property -dict { PACKAGE_PIN W14   IOSTANDARD LVCMOS25 } [get_ports { eth_pme_b }]; #IO_L6P_T0_13 Sch=eth_pme_b\r\n#set_property -dict { PACKAGE_PIN U7    IOSTANDARD LVCMOS33 } [get_ports { eth_rst_b }]; #IO_25_34 Sch=eth_rst_b\r\n#set_property -dict { PACKAGE_PIN V13   IOSTANDARD LVCMOS25 } [get_ports { eth_rxck }]; #IO_L13P_T2_MRCC_13 Sch=eth_rxck\r\n#set_property -dict { PACKAGE_PIN W10   IOSTANDARD LVCMOS25 } [get_ports { eth_rxctl }]; #IO_L10N_T1_13 Sch=eth_rxctl\r\n#set_property -dict { PACKAGE_PIN AB16  IOSTANDARD LVCMOS25 } [get_ports { eth_rxd[0] }]; #IO_L2P_T0_13 Sch=eth_rxd[0]\r\n#set_property -dict { PACKAGE_PIN AA15  IOSTANDARD LVCMOS25 } [get_ports { eth_rxd[1] }]; #IO_L4P_T0_13 Sch=eth_rxd[1]\r\n#set_property -dict { PACKAGE_PIN AB15  IOSTANDARD LVCMOS25 } [get_ports { eth_rxd[2] }]; #IO_L4N_T0_13 Sch=eth_rxd[2]\r\n#set_property -dict { PACKAGE_PIN AB11  IOSTANDARD LVCMOS25 } [get_ports { eth_rxd[3] }]; #IO_L7P_T1_13 Sch=eth_rxd[3]\r\n#set_property -dict { PACKAGE_PIN AA14  IOSTANDARD LVCMOS25 } [get_ports { eth_txck }]; #IO_L5N_T0_13 Sch=eth_txck\r\n#set_property -dict { PACKAGE_PIN V10   IOSTANDARD LVCMOS25 } [get_ports { eth_txctl }]; #IO_L10P_T1_13 Sch=eth_txctl\r\n#set_property -dict { PACKAGE_PIN Y12   IOSTANDARD LVCMOS25 } [get_ports { eth_txd[0] }]; #IO_L11N_T1_SRCC_13 Sch=eth_txd[0]\r\n#set_property -dict { PACKAGE_PIN W12   IOSTANDARD LVCMOS25 } [get_ports { eth_txd[1] }]; #IO_L12N_T1_MRCC_13 Sch=eth_txd[1]\r\n#set_property -dict { PACKAGE_PIN W11   IOSTANDARD LVCMOS25 } [get_ports { eth_txd[2] }]; #IO_L12P_T1_MRCC_13 Sch=eth_txd[2]\r\n#set_property -dict { PACKAGE_PIN Y11   IOSTANDARD LVCMOS25 } [get_ports { eth_txd[3] }]; #IO_L11P_T1_SRCC_13 Sch=eth_txd[3]\r\n\r\n\r\n## Fan PWM\r\n#set_property -dict { PACKAGE_PIN U15   IOSTANDARD LVCMOS25 } [get_ports { fan_pwm }]; #IO_L14P_T2_SRCC_13 Sch=fan_pwm\r\n\r\n\r\n## DPTI/DSPI\r\n#set_property -dict { PACKAGE_PIN Y18   IOSTANDARD LVCMOS33 } [get_ports { prog_clko  }]; #IO_L13P_T2_MRCC_14 Sch=prog_clko\r\n#set_property -dict { PACKAGE_PIN U20   IOSTANDARD LVCMOS33 } [get_ports { prog_d[0]  }]; #IO_L11P_T1_SRCC_14 Sch=prog_d0/sck\r\n#set_property -dict { PACKAGE_PIN P14   IOSTANDARD LVCMOS33 } [get_ports { prog_d[1]  }]; #IO_L19P_T3_A10_D26_14 Sch=prog_d1/mosi\r\n#set_property -dict { PACKAGE_PIN P15   IOSTANDARD LVCMOS33 } [get_ports { prog_d[2]  }]; #IO_L22P_T3_A05_D21_14 Sch=prog_d2/miso\r\n#set_property -dict { PACKAGE_PIN U17   IOSTANDARD LVCMOS33 } [get_ports { prog_d[3]  }]; #IO_L18P_T2_A12_D28_14 Sch=prog_d3/ss\r\n#set_property -dict { PACKAGE_PIN R17   IOSTANDARD LVCMOS33 } [get_ports { prog_d[4]  }]; #IO_L24N_T3_A00_D16_14 Sch=prog_d[4]\r\n#set_property -dict { PACKAGE_PIN P16   IOSTANDARD LVCMOS33 } [get_ports { prog_d[5]  }]; #IO_L24P_T3_A01_D17_14 Sch=prog_d[5]\r\n#set_property -dict { PACKAGE_PIN R18   IOSTANDARD LVCMOS33 } [get_ports { prog_d[6]  }]; #IO_L20P_T3_A08_D24_14 Sch=prog_d[6]\r\n#set_property -dict { PACKAGE_PIN N14   IOSTANDARD LVCMOS33 } [get_ports { prog_d[7]  }]; #IO_L23N_T3_A02_D18_14 Sch=prog_d[7]\r\n#set_property -dict { PACKAGE_PIN V17   IOSTANDARD LVCMOS33 } [get_ports { prog_oen   }]; #IO_L16P_T2_CSI_B_14 Sch=prog_oen\r\n#set_property -dict { PACKAGE_PIN P19   IOSTANDARD LVCMOS33 } [get_ports { prog_rdn   }]; #IO_L5P_T0_D06_14 Sch=prog_rdn\r\n#set_property -dict { PACKAGE_PIN N17   IOSTANDARD LVCMOS33 } [get_ports { prog_rxen  }]; #IO_L21P_T3_DQS_14 Sch=prog_rxen\r\n#set_property -dict { PACKAGE_PIN P17   IOSTANDARD LVCMOS33 } [get_ports { prog_siwun }]; #IO_L21N_T3_DQS_A06_D22_14 Sch=prog_siwun\r\n#set_property -dict { PACKAGE_PIN R14   IOSTANDARD LVCMOS33 } [get_ports { prog_spien }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=prog_spien\r\n#set_property -dict { PACKAGE_PIN Y19   IOSTANDARD LVCMOS33 } [get_ports { prog_txen  }]; #IO_L13N_T2_MRCC_14 Sch=prog_txen\r\n#set_property -dict { PACKAGE_PIN R19   IOSTANDARD LVCMOS33 } [get_ports { prog_wrn   }]; #IO_L5N_T0_D07_14 Sch=prog_wrn\r\n\r\n\r\n## HID port\r\n# set_property -dict {PACKAGE_PIN W17 IOSTANDARD LVCMOS33} [get_ports io_ps2_clk]\r\n# set_property -dict {PACKAGE_PIN N13 IOSTANDARD LVCMOS33} [get_ports io_ps2_data]\r\n\r\n\r\n## QSPI\r\n# set_property -dict {PACKAGE_PIN T19 IOSTANDARD LVCMOS33} [get_ports o_qspi_cs_n]\r\n# set_property -dict {PACKAGE_PIN P22 IOSTANDARD LVCMOS33} [get_ports {io_qspi_dat[0]}]\r\n# set_property -dict {PACKAGE_PIN R22 IOSTANDARD LVCMOS33} [get_ports {io_qspi_dat[1]}]\r\n# set_property -dict {PACKAGE_PIN P21 IOSTANDARD LVCMOS33} [get_ports {io_qspi_dat[2]}]\r\n# set_property -dict {PACKAGE_PIN R21 IOSTANDARD LVCMOS33} [get_ports {io_qspi_dat[3]}]\r\n#set_property -dict { PACKAGE_PIN W5    IOSTANDARD LVCMOS33 } [get_ports { scl }]; #IO_L15N_T2_DQS_34 Sch=scl\r\n\r\n\r\n## SD card\r\n#set_property -dict { PACKAGE_PIN W19   IOSTANDARD LVCMOS33 } [get_ports { o_sd_sck }]; #IO_L12P_T1_MRCC_14 Sch=sd_cclk\r\n# set_property -dict {PACKAGE_PIN T18 IOSTANDARD LVCMOS33} [get_ports i_sd_cd]\r\n#set_property -dict { PACKAGE_PIN W20   IOSTANDARD LVCMOS33 } [get_ports { io_sd_cmd }]; #IO_L12N_T1_MRCC_14 Sch=sd_cmd\r\n#set_property -dict { PACKAGE_PIN V19   IOSTANDARD LVCMOS33 } [get_ports { io_sd[0] }]; #IO_L14N_T2_SRCC_14 Sch=sd_d[0]\r\n#set_property -dict { PACKAGE_PIN T21   IOSTANDARD LVCMOS33 } [get_ports { io_sd[1] }]; #IO_L4P_T0_D04_14 Sch=sd_d[1]\r\n#set_property -dict { PACKAGE_PIN T20   IOSTANDARD LVCMOS33 } [get_ports { io_sd[2] }]; #IO_L6N_T0_D08_VREF_14 Sch=sd_d[2]\r\n#set_property -dict { PACKAGE_PIN U18   IOSTANDARD LVCMOS33 } [get_ports { io_sd[3] }]; #IO_L18N_T2_A11_D27_14 Sch=sd_d[3]\r\n# set_property -dict {PACKAGE_PIN V20 IOSTANDARD LVCMOS33} [get_ports o_sd_reset]\r\n#set_property -dict { PACKAGE_PIN V5    IOSTANDARD LVCMOS33 } [get_ports { sda }]; #IO_L16N_T2_34 Sch=sda\r\n\r\n\r\n## Voltage Adjust\r\n#set_property -dict { PACKAGE_PIN AA13  IOSTANDARD LVCMOS25 } [get_ports { set_vadj[0] }]; #IO_L3P_T0_DQS_13 Sch=set_vadj[0]\r\n#set_property -dict { PACKAGE_PIN AB17  IOSTANDARD LVCMOS25 } [get_ports { set_vadj[1] }]; #IO_L2N_T0_13 Sch=set_vadj[1]\r\n#set_property -dict { PACKAGE_PIN V14   IOSTANDARD LVCMOS25 } [get_ports { vadj_en }]; #IO_L13N_T2_MRCC_13 Sch=vadj_en\r\n\r\n\r\n## FMC\r\n#set_property -dict { PACKAGE_PIN H19   IOSTANDARD LVCMOS12 } [get_ports { fmc_clk0_m2c_n }]; #IO_L12N_T1_MRCC_15 Sch=fmc_clk0_m2c_n\r\n#set_property -dict { PACKAGE_PIN J19   IOSTANDARD LVCMOS12 } [get_ports { fmc_clk0_m2c_p }]; #IO_L12P_T1_MRCC_15 Sch=fmc_clk0_m2c_p\r\n#set_property -dict { PACKAGE_PIN C19   IOSTANDARD LVCMOS12 } [get_ports { fmc_clk1_m2c_n }]; #IO_L13N_T2_MRCC_16 Sch=fmc_clk1_m2c_n\r\n#set_property -dict { PACKAGE_PIN C18   IOSTANDARD LVCMOS12 } [get_ports { fmc_clk1_m2c_p }]; #IO_L13P_T2_MRCC_16 Sch=fmc_clk1_m2c_p\r\n#set_property -dict { PACKAGE_PIN K19   IOSTANDARD LVCMOS12 } [get_ports { fmc_la00_cc_n }]; #IO_L13N_T2_MRCC_15 Sch=fmc_la00_cc_n\r\n#set_property -dict { PACKAGE_PIN K18   IOSTANDARD LVCMOS12 } [get_ports { fmc_la00_cc_p }]; #IO_L13P_T2_MRCC_15 Sch=fmc_la00_cc_p\r\n#set_property -dict { PACKAGE_PIN J21   IOSTANDARD LVCMOS12 } [get_ports { fmc_la01_cc_n }]; #IO_L11N_T1_SRCC_15 Sch=fmc_la01_cc_n\r\n#set_property -dict { PACKAGE_PIN J20   IOSTANDARD LVCMOS12 } [get_ports { fmc_la01_cc_p }]; #IO_L11P_T1_SRCC_15 Sch=fmc_la01_cc_p\r\n#set_property -dict { PACKAGE_PIN L18   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[02] }]; #IO_L16N_T2_A27_15 Sch=fmc_la_n[02]\r\n#set_property -dict { PACKAGE_PIN M18   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[02] }]; #IO_L16P_T2_A28_15 Sch=fmc_la_p[02]\r\n#set_property -dict { PACKAGE_PIN N19   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[03] }]; #IO_L17N_T2_A25_15 Sch=fmc_la_n[03]\r\n#set_property -dict { PACKAGE_PIN N18   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[03] }]; #IO_L17P_T2_A26_15 Sch=fmc_la_p[03]\r\n#set_property -dict { PACKAGE_PIN M20   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[04] }]; #IO_L18N_T2_A23_15 Sch=fmc_la_n[04]\r\n#set_property -dict { PACKAGE_PIN N20   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[04] }]; #IO_L18P_T2_A24_15 Sch=fmc_la_p[04]\r\n#set_property -dict { PACKAGE_PIN L21   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[05] }]; #IO_L10N_T1_AD11N_15 Sch=fmc_la_n[05]\r\n#set_property -dict { PACKAGE_PIN M21   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[05] }]; #IO_L10P_T1_AD11P_15 Sch=fmc_la_p[05]\r\n#set_property -dict { PACKAGE_PIN M22   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[06] }]; #IO_L15N_T2_DQS_ADV_B_15 Sch=fmc_la_n[06]\r\n#set_property -dict { PACKAGE_PIN N22   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[06] }]; #IO_L15P_T2_DQS_15 Sch=fmc_la_p[06]\r\n#set_property -dict { PACKAGE_PIN L13   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[07] }]; #IO_L20N_T3_A19_15 Sch=fmc_la_n[07]\r\n#set_property -dict { PACKAGE_PIN M13   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[07] }]; #IO_L20P_T3_A20_15 Sch=fmc_la_p[07]\r\n#set_property -dict { PACKAGE_PIN M16   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[08] }]; #IO_L24N_T3_RS0_15 Sch=fmc_la_n[08]\r\n#set_property -dict { PACKAGE_PIN M15   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[08] }]; #IO_L24P_T3_RS1_15 Sch=fmc_la_p[08]\r\n#set_property -dict { PACKAGE_PIN G20   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[09] }]; #IO_L8N_T1_AD10N_15 Sch=fmc_la_n[09]\r\n#set_property -dict { PACKAGE_PIN H20   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[09] }]; #IO_L8P_T1_AD10P_15 Sch=fmc_la_p[09]\r\n#set_property -dict { PACKAGE_PIN K22   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[10] }]; #IO_L9N_T1_DQS_AD3N_15 Sch=fmc_la_n[10]\r\n#set_property -dict { PACKAGE_PIN K21   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[10] }]; #IO_L9P_T1_DQS_AD3P_15 Sch=fmc_la_p[10]\r\n#set_property -dict { PACKAGE_PIN L15   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[11] }]; #IO_L22N_T3_A16_15 Sch=fmc_la_n[11]\r\n#set_property -dict { PACKAGE_PIN L14   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[11] }]; #IO_L22P_T3_A17_15 Sch=fmc_la_p[11]\r\n#set_property -dict { PACKAGE_PIN L20   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[12] }]; #IO_L14N_T2_SRCC_15 Sch=fmc_la_n[12]\r\n#set_property -dict { PACKAGE_PIN L19   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[12] }]; #IO_L14P_T2_SRCC_15 Sch=fmc_la_p[12]\r\n#set_property -dict { PACKAGE_PIN J17   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[13] }]; #IO_L21N_T3_DQS_A18_15 Sch=fmc_la_n[13]\r\n#set_property -dict { PACKAGE_PIN K17   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[13] }]; #IO_L21P_T3_DQS_15 Sch=fmc_la_p[13]\r\n#set_property -dict { PACKAGE_PIN H22   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[14] }]; #IO_L7N_T1_AD2N_15 Sch=fmc_la_n[14]\r\n#set_property -dict { PACKAGE_PIN J22   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[14] }]; #IO_L7P_T1_AD2P_15 Sch=fmc_la_p[14]\r\n#set_property -dict { PACKAGE_PIN K16   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[15] }]; #IO_L23N_T3_FWE_B_15 Sch=fmc_la_n[15]\r\n#set_property -dict { PACKAGE_PIN L16   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[15] }]; #IO_L23P_T3_FOE_B_15 Sch=fmc_la_p[15]\r\n#set_property -dict { PACKAGE_PIN G18   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[16] }]; #IO_L4N_T0_15 Sch=fmc_la_n[16]\r\n#set_property -dict { PACKAGE_PIN G17   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[16] }]; #IO_L4P_T0_15 Sch=fmc_la_p[16]\r\n#set_property -dict { PACKAGE_PIN B18   IOSTANDARD LVCMOS12 } [get_ports { fmc_la17_cc_n }]; #IO_L11N_T1_SRCC_16 Sch=fmc_la17_cc_n\r\n#set_property -dict { PACKAGE_PIN B17   IOSTANDARD LVCMOS12 } [get_ports { fmc_la17_cc_p }]; #IO_L11P_T1_SRCC_16 Sch=fmc_la17_cc_p\r\n#set_property -dict { PACKAGE_PIN C17   IOSTANDARD LVCMOS12 } [get_ports { fmc_la18_cc_n }]; #IO_L12N_T1_MRCC_16 Sch=fmc_la18_cc_n\r\n#set_property -dict { PACKAGE_PIN D17   IOSTANDARD LVCMOS12 } [get_ports { fmc_la18_cc_p }]; #IO_L12P_T1_MRCC_16 Sch=fmc_la18_cc_p\r\n#set_property -dict { PACKAGE_PIN A19   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[19] }]; #IO_L17N_T2_16 Sch=fmc_la_n[19]\r\n#set_property -dict { PACKAGE_PIN A18   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[19] }]; #IO_L17P_T2_16 Sch=fmc_la_p[19]\r\n#set_property -dict { PACKAGE_PIN F20   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[20] }]; #IO_L18N_T2_16 Sch=fmc_la_n[20]\r\n#set_property -dict { PACKAGE_PIN F19   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[20] }]; #IO_L18P_T2_16 Sch=fmc_la_p[20]\r\n#set_property -dict { PACKAGE_PIN D19   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[21] }]; #IO_L14N_T2_SRCC_16 Sch=fmc_la_n[21]\r\n#set_property -dict { PACKAGE_PIN E19   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[21] }]; #IO_L14P_T2_SRCC_16 Sch=fmc_la_p[21]\r\n#set_property -dict { PACKAGE_PIN D21   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[22] }]; #IO_L23N_T3_16 Sch=fmc_la_n[22]\r\n#set_property -dict { PACKAGE_PIN E21   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[22] }]; #IO_L23P_T3_16 Sch=fmc_la_p[22]\r\n#set_property -dict { PACKAGE_PIN A21   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[23] }]; #IO_L21N_T3_DQS_16 Sch=fmc_la_n[23]\r\n#set_property -dict { PACKAGE_PIN B21   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[23] }]; #IO_L21P_T3_DQS_16 Sch=fmc_la_p[23]\r\n#set_property -dict { PACKAGE_PIN B16   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[24] }]; #IO_L7N_T1_16 Sch=fmc_la_n[24]\r\n#set_property -dict { PACKAGE_PIN B15   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[24] }]; #IO_L7P_T1_16 Sch=fmc_la_p[24]\r\n#set_property -dict { PACKAGE_PIN E17   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[25] }]; #IO_L2N_T0_16 Sch=fmc_la_n[25]\r\n#set_property -dict { PACKAGE_PIN F16   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[25] }]; #IO_L2P_T0_16 Sch=fmc_la_p[25]\r\n#set_property -dict { PACKAGE_PIN E18   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[26] }]; #IO_L15N_T2_DQS_16 Sch=fmc_la_n[26]\r\n#set_property -dict { PACKAGE_PIN F18   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[26] }]; #IO_L15P_T2_DQS_16 Sch=fmc_la_p[26]\r\n#set_property -dict { PACKAGE_PIN A20   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[27] }]; #IO_L16N_T2_16 Sch=fmc_la_n[27]\r\n#set_property -dict { PACKAGE_PIN B20   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[27] }]; #IO_L16P_T2_16 Sch=fmc_la_p[27]\r\n#set_property -dict { PACKAGE_PIN B13   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[28] }]; #IO_L8N_T1_16 Sch=fmc_la_n[28]\r\n#set_property -dict { PACKAGE_PIN C13   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[28] }]; #IO_L8P_T1_16 Sch=fmc_la_p[28]\r\n#set_property -dict { PACKAGE_PIN C15   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[29] }]; #IO_L3N_T0_DQS_16 Sch=fmc_la_n[29]\r\n#set_property -dict { PACKAGE_PIN C14   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[29] }]; #IO_L3P_T0_DQS_16 Sch=fmc_la_p[29]\r\n#set_property -dict { PACKAGE_PIN A14   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[30] }]; #IO_L10N_T1_16 Sch=fmc_la_n[30]\r\n#set_property -dict { PACKAGE_PIN A13   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[30] }]; #IO_L10P_T1_16 Sch=fmc_la_p[30]\r\n#set_property -dict { PACKAGE_PIN E14   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[31] }]; #IO_L4N_T0_16 Sch=fmc_la_n[31]\r\n#set_property -dict { PACKAGE_PIN E13   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[31] }]; #IO_L4P_T0_16 Sch=fmc_la_p[31]\r\n#set_property -dict { PACKAGE_PIN A16   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[32] }]; #IO_L9N_T1_DQS_16 Sch=fmc_la_n[32]\r\n#set_property -dict { PACKAGE_PIN A15   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[32] }]; #IO_L9P_T1_DQS_16 Sch=fmc_la_p[32]\r\n#set_property -dict { PACKAGE_PIN F14   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_n[33] }]; #IO_L1N_T0_16 Sch=fmc_la_n[33]\r\n#set_property -dict { PACKAGE_PIN F13   IOSTANDARD LVCMOS12 } [get_ports { fmc_la_p[33] }]; #IO_L1P_T0_16 Sch=fmc_la_p[33]\r\n\r\n\r\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *avgs*}]    -to [get_cells -hier -filter {NAME =~ *q_v*}] 10.0;\r\n\r\nset_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]\r\nset_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]\r\nset_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]\r\nset_property BITSTREAM.CONFIG.CCLKPIN PULLNONE [current_design]\r\nset_property CONFIG_MODE SPIx4 [current_design]\r\nset_property CFGBVS VCCO [current_design]\r\nset_property CONFIG_VOLTAGE 3.3 [current_design]\r\n"
  },
  {
    "path": "auto-data/pic.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/pic.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\t\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=buspic\n@DEVID=BUSPIC\n@NADDR=1\n@BUSP=wb32\n@ACCESS=BUSPIC_ACCESS\n@SLAVE.TYPE=SINGLE\n@SLAVE.BUS=@$(BUSP)\n@PIC.BUS= bus_int_vector\n@PIC.MAX= 15\n@INT.BUS.WIRE= w_bus_int\n@INT.BUS.PIC=  syspic\n@INT.BUS.ID=   6\n@BDEF.DEFN=\n#define BUSPIC(X) (1<<X)\n@MAIN.INSERT=\n\t//\n\t// The BUS Interrupt controller\n\t//\n\ticontrol #(15)\n\tu_@$(PREFIX) (\n\t\t.i_clk(@$(SLAVE.BUS.CLOCK.WIRE)), .i_reset(1'b0),\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t.i_brd_ints(bus_int_vector),\n\t\t.o_interrupt(w_bus_int)\n\t);\n@MAIN.ALT=\n@REGS.N=1\n@REGS.0= 0 R_PIC PIC\n@BDEF.IONAME= _@$(PREFIX)\n@BDEF.IOTYPE= unsigned\n@BDEF.OSDEF= _BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL= static volatile @$BDEF.IOTYPE *const @$BDEF.IONAME = ((@$BDEF.IOTYPE *)@$[0x%08x](REGBASE));\n@RTL.MAKE.GROUP= BUSPIC\n@RTL.MAKE.SUBD=cpu\n@RTL.MAKE.FILES=icontrol.v\n"
  },
  {
    "path": "auto-data/pwrcount.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/pwrcount.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\t\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=pwrcount\n@NADDR=1\n@ACCESS=PWRCOUNT_ACCESS\n@SLAVE.TYPE=SINGLE\n@SLAVE.BUS=wb32\n@MAIN.DEFNS=\n\treg\t[31:0]\tr_@$(PREFIX)_data;\n@MAIN.INSERT=\n\tinitial\tr_@$(PREFIX)_data = 32'h0;\n\talways @(posedge i_clk)\n\tif (r_@$(PREFIX)_data[31])\n\t\tr_@$(PREFIX)_data[30:0] <= r_@$(PREFIX)_data[30:0] + 1'b1;\n\telse\n\t\tr_@$(PREFIX)_data[31:0] <= r_@$(PREFIX)_data[31:0] + 1'b1;\n\n\tassign\t@$(SLAVE.PREFIX)_stall = 1'b0;\n\tassign\t@$(SLAVE.PREFIX)_ack   = @$(SLAVE.PREFIX)_stb;\n\tassign\t@$(SLAVE.PREFIX)_idata = r_@$(PREFIX)_data;\n@REGS.N=1\n@REGS.0= 0 R_PWRCOUNT PWRCOUNT\n@BDEF.OSVAL= static volatile unsigned *const _@$(PREFIX) = ((unsigned *)@$[0x%08x](REGBASE));\n"
  },
  {
    "path": "auto-data/rtccount.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/rtccount.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tDefine a very simple peripheral that counts fractions of a\n##\t\tsecond since startup.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2015-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=rtccount\n@DEVID=RTCCOUNT\n@ACCESS=@$(DEVID)_ACCESS\n@NADDR=1\n@CLOCK.NAME=clk\n@SLAVE.TYPE=SINGLE\n@SLAVE.BUS=wb32\n@$STEP=((1<<32) + @$(CLOCK.FREQUENCY)/2)/@$(CLOCK.FREQUENCY)\n@MAIN.DEFNS=\n\treg\t[31:0]\tr_@$(PREFIX)_data;\n@MAIN.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// RTC Counter\n\t// {{{\n\t//\n\t// Using clock @$(CLOCK.WIRE) with frequency @$(CLOCK.FREQUENCY)\n\t//\n\n\tassign\t@$(SLAVE.PREFIX)_stall = 1'b0;\n\tassign\t@$(SLAVE.PREFIX)_ack = @$(SLAVE.PREFIX)_stb;\n\n\tinitial\tr_@$(PREFIX)_data = 32'h0;\n\talways @(posedge i_clk)\n\t\tr_@$(PREFIX)_data <= r_@$(PREFIX)_data + @$(STEP);\n\tassign\t@$(SLAVE.PREFIX)_idata = r_@$(PREFIX)_data;\n\t// }}}\n@REGS.N=1\n@REGS.0= 0 R_RTCCOUNT RTCCOUNT\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE=unsigned\n@BDEF.OSDEF=_BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL= static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((unsigned *)@$[0x%08x](REGBASE));\n"
  },
  {
    "path": "auto-data/rtcdate.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/rtcdate.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\t\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=rtcdate\n@DEVID=RTCDATE\n@NADDR=1\n@ACCESS=@$(DEVID)_ACCESS\n@DEPENDS=RTC_ACCESS\n@SLAVE.TYPE=SINGLE\n@SLAVE.BUS=wb32\n@MAIN.INSERT=\n\t//\n\t// The Calendar DATE\n\t//\n\trtcdate #(\n\t\t.INITIAL_DATE(`DATESTAMP)\n\t) u_@$(PREFIX)(\n\t\t.i_clk(i_clk), .i_ppd(rtc_ppd),\n\t\t@$(SLAVE.ANSIPORTLIST)\n\t);\n@REGS.N=1\n@REGS.0= 0 R_@$(DEVID) @$(DEVID) DATE\n@BDEF.IONAME=\t_@$(PREFIX)\n@BDEF.IOTYPE=\tunsigned\n@BDEF.OSDEF=\t_BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL=\tstatic volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$BDEF.IOTYPE *)@$REGBASE);\n@RTL.MAKE.GROUP=@$(DEVID)\n@RTL.MAKE.SUBD=rtc\n@RTL.MAKE.FILES=rtcdate.v\n"
  },
  {
    "path": "auto-data/rtcgps.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/rtcgps.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\t\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=rtc\n@DEVID=RTC\n@NADDR=4\n@SLAVE.TYPE=DOUBLE\n@SLAVE.BUS=wb32\n@ACCESS=RTC_ACCESS\n@CLOCK.NAME=clk\n@CLKFREQHZ=@$(CLOCK.FREQUENCY)\n@$CLKSTEP=((1<<48)/@$(CLOCK.FREQUENCY))\n@INT.RTC.WIRE=rtc_int\n@INT.RTC.PIC=altpic\n@MAIN.DEFNS=\n\t// Definitions in support of the GPS driven RTC\n\t// This clock step is designed to match @$(CLOCK.FREQUENCY) Hz\n\tlocalparam\t[31:0]\tRTC_CLKSTEP = @$[32'h%08x](CLKSTEP);\n\twire\t@$(PREFIX)_ppd;\n\twire\t@$(PREFIX)_pps;\n@MAIN.INSERT=\n`ifdef\tGPSTRK_ACCESS\n\trtcgps\t#(\n\t\t.DEFAULT_SPEED(RTC_CLKSTEP)\n\t) u_@$(PREFIX)(\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t.o_interrupt(@$(PREFIX)_int), .o_ppd(@$(PREFIX)_ppd),\n\t\t.i_gps_valid(gps_tracking), .i_gps_pps(ck_pps),\n\t\t\t.i_gps_ckspeed(gps_step[47:16]), .o_rtc_pps(rtc_pps)\n\t);\n`else\n\trtclight #(\n\t\t.DEFAULT_SPEED(@$[32'h%x](CLKSTEP))\n\t) u_@$(PREFIX)(\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t// Can't use the ANSIPORTLIST tag, because the address widths\n\t\t// don't match\n\t\t.i_wb_cyc(@$(SLAVE.PREFIX)_cyc),\n\t\t.i_wb_stb(@$(SLAVE.PREFIX)_stb),\n\t\t.i_wb_we(@$(SLAVE.PREFIX)_we),\n\t\t.i_wb_addr({ 1'b0, @$(SLAVE.PREFIX)_addr[1:0] }),\n\t\t.i_wb_data(@$(SLAVE.PREFIX)_data),\n\t\t.i_wb_sel(@$(SLAVE.PREFIX)_sel),\n\t\t.o_wb_stall(@$(SLAVE.PREFIX)_stall),\n\t\t.o_wb_ack(@$(SLAVE.PREFIX)_ack),\n\t\t.o_wb_data(@$(SLAVE.PREFIX)_idata),\n\t\t.o_interrupt(@$(PREFIX)_int),\n\t\t.o_pps(rtc_pps),\n\t\t.o_ppd(@$(PREFIX)_ppd)\n\t);\n\n\t// Verilator lint_off UNUSED\n\twire\tunused_@$(PREFIX);\n\tassign\tunused_@$(PREFIX) = &{ 1'b0, i_gps_pps };\n\t// Verilator lint_on  UNUSED\n`endif\n@MAIN.ALT=\n`ifdef\tGPSTRK_ACCESS\n\tassign\t@$(PREFIX)_pps = ck_pps;\n`endif\n\tassign\t@$(PREFIX)_ppd = 1'b0;\n@REGS.NOTE= // RTC clock registers\n@REGS.N=4\n@REGS.0= 0 R_CLOCK\tCLOCK\n@REGS.1= 1 R_TIMER\tTIMER\n@REGS.2= 2 R_STOPWATCH\tSTOPWATCH\n@REGS.3= 3 R_CKALARM\tALARM CKALARM\n@BDEF.DEFN=\ntypedef\tstruct\tRTCLIGHT_S\t{\n\tunsigned\tr_clock, r_stopwatch, r_timer, r_alarm;\n} RTCLIGHT;\n@BDEF.IONAME=_rtc\n@BDEF.IOTYPE=RTCLIGHT\n@BDEF.OSDEF=_BOARD_HAS_RTC\n@BDEF.OSVAL=static volatile @$BDEF.IOTYPE *const @$(BDEF.IONAME) = ((@$BDEF.IOTYPE *)@$[0x%08x](REGBASE));\n#\n#\n@RTL.MAKE.GROUP=RTCGPS\n@RTL.MAKE.SUBD=rtc\n@RTL.MAKE.FILES=rtcgps.v rtcbare.v rtctimer.v rtcstopwatch.v rtcalarm.v rtclight.v\n##\n##\n@PREFIX=subseconds\n@DEVID=SUBSECONDS\n@NADDR=1\n@SLAVE.BUS=wb32\n@SLAVE.TYPE=SINGLE\n@MAIN.DEFNS=\n`ifndef\tGPSTRK_ACCESS\n\treg\t[31:0]\tr_@$(PREFIX)_data;\n`endif\n@MAIN.INSERT=\n`ifdef\tGPSTRK_ACCESS\n\tassign\t@$(SLAVE.PREFIX)_idata = gps_now[31:0];\n`else\n\talways @(posedge i_clk)\n\tif (@$(SLAVE.PREFIX)_stb && @$(SLAVE.PREFIX)_we)\n\t\tr_@$(PREFIX)_data <= @$(SLAVE.PREFIX)_data;\n\telse\n\t\tr_@$(PREFIX)_data <= r_@$(PREFIX)_data\n\t\t\t+ { 16'h0, RTC_CLKSTEP[31:16] };\n\n\tassign\t@$(SLAVE.PREFIX)_idata = r_@$(PREFIX)_data;\n`endif\n@REGS.NOTE= // A register capturing subseconds, locked to GPS if present\n@REGS.N=1\n@REGS.0= 0 R_SUBSECONDS\tSUBSECONDS\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE=unsigned\n@BDEF.OSDEF=_BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$BDEF.IOTYPE *)@$[0x%08x](REGBASE));\n"
  },
  {
    "path": "auto-data/sdio.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/sdio.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tDescribes how to connect an SDIO peripheral to a wishbone\n##\t\tbus, as used by autofpga.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=sdio\n@DEVID=SDIO\n@NAME=SDIO SD Card\n@NADDR=8\n@CRCTOKEN=1\n@$NUMIO=4\n@ACCESS=SDIO_ACCESS\n@SLAVE.TYPE=OTHER\n@SLAVE.BUS=wbflash\n@MASTER.TYPE=DMA\n@MASTER.BUS=wbwide\n@MASTER.ANSPREFIX=dma_\n## @SCOPE.TRIGGER=@$(PREFIX)_debug[31]\n## @SCOPE.DATA=@$(PREFIX)_debug\n@INT.SDCARD.WIRE= @$(PREFIX)_int\n@INT.SDCARD.PIC= syspic\n@CARD_DETECT=1'b1\n@OPT_SERDES=1'b1\n@OPT_DDR=1'b1\n@OPT_EMMC=1'b0\n@OPT_DMA=1'b1\n@OPT_1P8V=1'b0\n@TOP.IOPREFIX=sd\n@OPT_HWRESET=@$(OPT_EMMC)\n@SDIO.IORESET=\n@SDIO.CLKASSIGN=\n\tassign\to_@$(TOP.IOPREFIX)_clk = w_@$(PREFIX)_ck;\n@SDIO.DSASSIGN=\n\tassign\tw_@$(PREFIX)_ds    = 1'b0;\n@SDIO.HWRSTASSIGN=\n@SDIO.RSTDECL=\n@SDIO.DSDECL=\n@SDIO.CDETDECL= i_@$(TOP.IOPREFIX)_cd_n,\n@SDIO.CLKDECL= o_@$(TOP.IOPREFIX)_clk,\n@SDIO.IORST=\n@SDIO.IODS=\n@SDIO.IOCDET=\n\tinput\twire\t\ti_@$(TOP.IOPREFIX)_cd_n;\n@SDIO.IOCLK=\n\toutput\twire\t\to_@$(TOP.IOPREFIX)_clk;\n@TOP.PORTLIST=\n\t\t// @$(NAME)\n@$(SDIO.RSTDECL)\n@$(SDIO.CLKDECL)\n@$(SDIO.CDETDECL)\n@$(SDIO.DSDECL)\n\t\tio_@$(TOP.IOPREFIX)_cmd, io_@$(TOP.IOPREFIX)_dat\n@TOP.IODECL=\n\t// @$(NAME)\n\t// {{{\n@$(SDIO.IORST)\n@$(SDIO.IOCLK)\n@$(SDIO.IODS)\n@$(SDIO.IOCDET)\n\tinout\twire\t\tio_@$(TOP.IOPREFIX)_cmd;\n\tinout\twire\t[@$(NUMIO)-1:0]\tio_@$(TOP.IOPREFIX)_dat;\n\t// }}}\n@SDIO.TOP.DEFNS=\n\t// @$(NAME) definitions\n\t// {{{\n\twire\t\tw_@$(PREFIX)_hwreset_n, w_@$(PREFIX)_1p8v;\n\twire\t\tw_@$(PREFIX)_cfg_ddr;\n\twire\t\tw_@$(PREFIX)_cfg_ds, w_@$(PREFIX)_cfg_dscmd;\n\twire\t[4:0]\tw_@$(PREFIX)_cfg_sample_shift;\n\twire\t\tw_@$(PREFIX)_cmd_tristate;\n\twire\t\tw_@$(PREFIX)_data_tristate;\n\t\t//\n\twire\t[7:0]\tw_@$(PREFIX)_sdclk;\n\twire\t\tw_@$(PREFIX)_cmd_en;\n\twire\t[1:0]\tw_@$(PREFIX)_cmd_data;\n\twire\t\tw_@$(PREFIX)_data_en;\n\twire\t\tw_@$(PREFIX)_rx_en;\n\twire\t[31:0]\tw_@$(PREFIX)_tx_data;\n\t\t//\n\twire\t[1:0]\tw_@$(PREFIX)_cmd_strb;\n\twire\t[1:0]\tw_@$(PREFIX)_cmd_idata;\n\twire\t\tw_@$(PREFIX)_cmd_collision;\n\twire\t\tw_@$(PREFIX)_crcack,\n\t\t\tw_@$(PREFIX)_crcnak;\n\twire\t\tw_@$(PREFIX)_card_busy;\n\twire\t[1:0]\tw_@$(PREFIX)_rx_strb;\n\twire\t[15:0]\tw_@$(PREFIX)_rx_data;\n\t\t//\n\twire\t\tw_@$(PREFIX)_ac_valid;\n\twire\t[1:0]\tw_@$(PREFIX)_ac_data;\n\twire\t\tw_@$(PREFIX)_ad_valid;\n\twire\t[31:0]\tw_@$(PREFIX)_ad_data;\n\n\twire\t\tw_@$(PREFIX)_ck;\n\twire\t\tw_@$(PREFIX)_ds;\n\twire\t[31:0]\tw_@$(PREFIX)_debug;\n\t// }}}\n@TOP.DEFNS=\n@$(SDIO.TOP.DEFNS)\n@SDIO.FRONTEND=\n\tsdfrontend #(\n\t\t.OPT_SERDES(@$(OPT_SERDES)),\n\t\t.OPT_DDR(@$(OPT_DDR)),\n\t\t.NUMIO(@$(NUMIO)),\n\t\t.BUSY_CLOCKS(16),\n\t\t.OPT_CRCTOKEN(@$(CRCTOKEN))\n\t) u_@$(PREFIX)_frontend (\n\t\t// {{{\n\t\t.i_clk(s_clk), .i_hsclk(s_clk_400mhz), .i_reset(s_reset),\n\t\t// Configuration\n\t\t.i_cfg_ddr(w_@$(PREFIX)_cfg_ddr),\n\t\t.i_cfg_ds(w_@$(PREFIX)_cfg_ds),\n\t\t.i_cfg_dscmd(w_@$(PREFIX)_cfg_dscmd),\n\t\t.i_sample_shift(w_@$(PREFIX)_cfg_sample_shift),\n\t\t.i_cmd_tristate(w_@$(PREFIX)_cmd_tristate),\n\t\t.i_data_tristate(w_@$(PREFIX)_data_tristate),\n\t\t// Run-time inputs\n\t\t.i_sdclk(w_@$(PREFIX)_sdclk),\n\t\t.i_cmd_en(w_@$(PREFIX)_cmd_en),\n\t\t.i_cmd_data(w_@$(PREFIX)_cmd_data),\n\t\t.i_data_en(w_@$(PREFIX)_data_en),\n\t\t.i_rx_en(w_@$(PREFIX)_rx_en),\n\t\t.i_tx_data(w_@$(PREFIX)_tx_data),\n\t\t// Return values\n\t\t.o_cmd_strb(w_@$(PREFIX)_cmd_strb),\n\t\t.o_cmd_data(w_@$(PREFIX)_cmd_idata),\n\t\t.o_cmd_collision(w_@$(PREFIX)_cmd_collision),\n\t\t.o_crcack(w_@$(PREFIX)_crcack),\n\t\t.o_crcnak(w_@$(PREFIX)_crcnak),\n\t\t.o_data_busy(w_@$(PREFIX)_card_busy),\n\t\t.o_rx_strb( w_@$(PREFIX)_rx_strb),\n\t\t.o_rx_data( w_@$(PREFIX)_rx_data),\n\t\t//\n\t\t.MAC_VALID(w_@$(PREFIX)_ac_valid),\n\t\t.MAC_DATA( w_@$(PREFIX)_ac_data),\n\t\t.MAD_VALID(w_@$(PREFIX)_ad_valid),\n\t\t.MAD_DATA( w_@$(PREFIX)_ad_data),\n\t\t// IO ports\n\t\t.o_ck(w_@$(PREFIX)_ck),\n\t\t.i_ds(w_@$(PREFIX)_ds),\n\t\t.io_cmd(io_@$(TOP.IOPREFIX)_cmd),\n\t\t.io_dat(io_@$(TOP.IOPREFIX)_dat),\n\t\t.o_debug(w_@$(PREFIX)_debug)\n\t\t// }}}\n\t);\n@TOP.INSERT=\n@$(SDIO.FRONTEND)\n\n@$(SDIO.CLKASSIGN)\n@$(SDIO.DSASSIGN)\n@TOP.MAIN=\n\t\t// @$(NAME)\n\t\t!i_@$(TOP.IOPREFIX)_cd_n,\n\t\t//\n\t\tw_@$(PREFIX)_cfg_ddr,\n\t\tw_@$(PREFIX)_cfg_ds,\n\t\tw_@$(PREFIX)_cfg_dscmd,\n\t\tw_@$(PREFIX)_cfg_sample_shift,\n\t\tw_@$(PREFIX)_cmd_tristate,\n\t\tw_@$(PREFIX)_data_tristate,\n\t\t//\n\t\tw_@$(PREFIX)_sdclk,\n\t\tw_@$(PREFIX)_cmd_en,\n\t\tw_@$(PREFIX)_cmd_data,\n\t\tw_@$(PREFIX)_data_en,\n\t\tw_@$(PREFIX)_rx_en,\n\t\tw_@$(PREFIX)_tx_data,\n\t\t//\n\t\tw_@$(PREFIX)_cmd_strb,\n\t\tw_@$(PREFIX)_cmd_idata,\n\t\tw_@$(PREFIX)_cmd_collision,\n\t\tw_@$(PREFIX)_crcack,\n\t\tw_@$(PREFIX)_crcnak,\n\t\tw_@$(PREFIX)_card_busy,\n\t\tw_@$(PREFIX)_rx_strb,\n\t\tw_@$(PREFIX)_rx_data,\n\t\t//\n\t\tw_@$(PREFIX)_ac_valid,\n\t\tw_@$(PREFIX)_ac_data,\n\t\tw_@$(PREFIX)_ad_valid,\n\t\tw_@$(PREFIX)_ad_data,\n\t\tw_@$(PREFIX)_hwreset_n, w_@$(PREFIX)_1p8v,\n\t\tw_@$(PREFIX)_debug\n@TOP.INSERT=\n\tassign\ti_@$(PREFIX)_ds = 1'b0;\n@MAIN.PORTLIST=\n\t\t// @$(NAME)\n\t\ti_@$(PREFIX)_detect,\n\t\t//\n\t\to_@$(PREFIX)_cfg_ddr,\n\t\to_@$(PREFIX)_cfg_ds,\n\t\to_@$(PREFIX)_cfg_dscmd,\n\t\to_@$(PREFIX)_cfg_sample_shift,\n\t\to_@$(PREFIX)_cmd_tristate,\n\t\to_@$(PREFIX)_data_tristate,\n\t\t//\n\t\to_@$(PREFIX)_sdclk,\n\t\to_@$(PREFIX)_cmd_en,\n\t\to_@$(PREFIX)_cmd_data,\n\t\to_@$(PREFIX)_data_en,\n\t\to_@$(PREFIX)_rx_en,\n\t\to_@$(PREFIX)_tx_data,\n\t\t//\n\t\ti_@$(PREFIX)_cmd_strb,\n\t\ti_@$(PREFIX)_cmd_data,\n\t\ti_@$(PREFIX)_cmd_collision,\n\t\ti_@$(PREFIX)_crcack,\n\t\ti_@$(PREFIX)_crcnak,\n\t\ti_@$(PREFIX)_card_busy,\n\t\ti_@$(PREFIX)_rx_strb,\n\t\ti_@$(PREFIX)_rx_data,\n\t\t//\n\t\ti_@$(PREFIX)_ac_valid,\n\t\ti_@$(PREFIX)_ac_data,\n\t\ti_@$(PREFIX)_ad_valid,\n\t\ti_@$(PREFIX)_ad_data,\n\t\to_@$(PREFIX)_hwreset_n, o_@$(PREFIX)_1p8v,\n\t\ti_@$(PREFIX)_debug\n@MAIN.IODECL=\n\t// @$(NAME) declarations\n\t// {{{\n\tinput\twire\t\ti_@$(PREFIX)_detect;\n\t\t//\n\toutput\twire\t\to_@$(PREFIX)_cfg_ddr;\n\toutput\twire\t\to_@$(PREFIX)_cfg_ds;\n\toutput\twire\t\to_@$(PREFIX)_cfg_dscmd;\n\toutput\twire\t[4:0]\to_@$(PREFIX)_cfg_sample_shift;\n\toutput\twire\t\to_@$(PREFIX)_cmd_tristate;\n\toutput\twire\t\to_@$(PREFIX)_data_tristate;\n\t\t//\n\toutput\twire\t[7:0]\to_@$(PREFIX)_sdclk;\n\toutput\twire\t\to_@$(PREFIX)_cmd_en;\n\toutput\twire\t[1:0]\to_@$(PREFIX)_cmd_data;\n\toutput\twire\t\to_@$(PREFIX)_data_en;\n\toutput\twire\t\to_@$(PREFIX)_rx_en;\n\toutput\twire\t[31:0]\to_@$(PREFIX)_tx_data;\n\t\t//\n\tinput\twire\t[1:0]\ti_@$(PREFIX)_cmd_strb;\n\tinput\twire\t[1:0]\ti_@$(PREFIX)_cmd_data;\n\tinput\twire\t\ti_@$(PREFIX)_cmd_collision;\n\tinput\twire\t\ti_@$(PREFIX)_crcack;\n\tinput\twire\t\ti_@$(PREFIX)_crcnak;\n\tinput\twire\t\ti_@$(PREFIX)_card_busy;\n\tinput\twire\t[1:0]\ti_@$(PREFIX)_rx_strb;\n\tinput\twire\t[15:0]\ti_@$(PREFIX)_rx_data;\n\t\t//\n\tinput\twire\t\ti_@$(PREFIX)_ac_valid;\n\tinput\twire\t[1:0]\ti_@$(PREFIX)_ac_data;\n\tinput\twire\t\ti_@$(PREFIX)_ad_valid;\n\tinput\twire\t[31:0]\ti_@$(PREFIX)_ad_data;\n\toutput\twire\t\to_@$(PREFIX)_hwreset_n,\n\t\t\t\to_@$(PREFIX)_1p8v;\n\t// Verilator lint_off UNUSED\n\tinput\twire\t[31:0]\ti_@$(PREFIX)_debug;\n\t// Verilator lint_on  UNUSED\n\t// }}}\n@MAIN.DEFNS=\n\t// @$(NAME) definitions\n\t// Verilator lint_off UNUSED\n\twire\t[31:0]\tw_@$(PREFIX)_sdwb_debug;\n\twire\t\ts_@$(PREFIX)_ready,\n\t\t\tm_@$(PREFIX)_valid, m_@$(PREFIX)_last;\n\treg\t[31:0]\t@$(PREFIX)_debug;\n\twire\t[31:0]\tm_@$(PREFIX)_data;\n\t// assign\t\t@$(PREFIX)_debug = i_@$(PREFIX)_debug;\n\t// Verilator lint_on  UNUSED\n@MAIN.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// @$(NAME) handling\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t//\n\n\talways @(*)\n\tbegin\n\t\t@$(PREFIX)_debug = i_@$(PREFIX)_debug;\n\t\t@$(PREFIX)_debug = w_@$(PREFIX)_sdwb_debug;\n\tend\n\n\tsdio #(\n\t\t// {{{\n\t\t.LGFIFO(10), .NUMIO(@$(NUMIO)),\n\t\t.MW(@$(SLAVE.BUS.WIDTH)),\n\t\t.ADDRESS_WIDTH(@$(MASTER.BUS.AWID)+$clog2(@$(MASTER.BUS.WIDTH)/8)),\n\t\t.DMA_DW(@$(MASTER.BUS.WIDTH)),\n\t\t.OPT_SERDES(@$(OPT_SERDES)),\n\t\t.OPT_EMMC(@$(OPT_EMMC)),\n\t\t.OPT_DMA(@$(OPT_DMA)),\n\t\t.OPT_DDR(@$(OPT_DDR)),\n\t\t.OPT_HWRESET(@$(OPT_HWRESET)),\n\t\t.OPT_CARD_DETECT(@$(CARD_DETECT)),\n\t\t.OPT_CRCTOKEN(@$(CRCTOKEN)),\n\t\t.OPT_1P8V(@$(OPT_1P8V)),\n`ifdef\tVERILATOR\n\t\t.LGTIMEOUT(18),\n`else\n\t\t.LGTIMEOUT(26),\n`endif\n\t\t.OPT_ISTREAM(1'b0),\n\t\t.OPT_OSTREAM(1'b0)\n\t\t// }}}\n\t) u_@$(PREFIX)(\n\t\t// {{{\n\t\t.i_clk(@$(SLAVE.BUS.CLOCK.WIRE)),\n\t\t.i_reset(@$(SLAVE.BUS.CLOCK.RESET)),\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t@$(MASTER.ANSIPORTLIST),\n\t\t// (Unused) DMA Stream assignments\n\t\t// {{{\n\t\t.s_valid(1'b0),\n\t\t.s_ready(s_@$(PREFIX)_ready),\n\t\t.s_data(32'h0),\n\t\t//\n\t\t.m_valid(m_@$(PREFIX)_valid),\n\t\t.m_ready(1'b1),\n\t\t.m_data(m_@$(PREFIX)_data),\n\t\t.m_last(m_@$(PREFIX)_last),\n\t\t// }}}\n\t\t.i_card_detect(i_@$(PREFIX)_detect),\n\t\t.o_hwreset_n(o_@$(PREFIX)_hwreset_n),\n\t\t.o_1p8v(o_@$(PREFIX)_1p8v),\n\t\t.o_int(@$(PREFIX)_int),\n\t\t//\n\t\t.o_cfg_ddr(o_@$(PREFIX)_cfg_ddr),\n\t\t.o_cfg_ds(o_@$(PREFIX)_cfg_ds),\n\t\t.o_cfg_dscmd(o_@$(PREFIX)_cfg_dscmd),\n\t\t.o_cfg_sample_shift(o_@$(PREFIX)_cfg_sample_shift),\n\t\t.o_cmd_tristate(o_@$(PREFIX)_cmd_tristate),\n\t\t.o_data_tristate(o_@$(PREFIX)_data_tristate),\n\t\t//\n\t\t.o_sdclk(   o_@$(PREFIX)_sdclk),\n\t\t.o_cmd_en(  o_@$(PREFIX)_cmd_en),\n\t\t.o_cmd_data(o_@$(PREFIX)_cmd_data),\n\t\t.o_data_en( o_@$(PREFIX)_data_en),\n\t\t.o_rx_en(   o_@$(PREFIX)_rx_en),\n\t\t.o_tx_data( o_@$(PREFIX)_tx_data),\n\t\t//\n\t\t.i_cmd_strb( i_@$(PREFIX)_cmd_strb),\n\t\t.i_cmd_data( i_@$(PREFIX)_cmd_data),\n\t\t.i_cmd_collision( i_@$(PREFIX)_cmd_collision),\n\t\t.i_crcack( i_@$(PREFIX)_crcack),\n\t\t.i_crcnak( i_@$(PREFIX)_crcnak),\n\t\t.i_card_busy(i_@$(PREFIX)_card_busy),\n\t\t.i_rx_strb(  i_@$(PREFIX)_rx_strb),\n\t\t.i_rx_data(  i_@$(PREFIX)_rx_data),\n\t\t//\n\t\t.S_AC_VALID(i_@$(PREFIX)_ac_valid),\n\t\t.S_AC_DATA( i_@$(PREFIX)_ac_data),\n\t\t.S_AD_VALID(i_@$(PREFIX)_ad_valid),\n\t\t.S_AD_DATA( i_@$(PREFIX)_ad_data),\n\t\t//\n\t\t.o_debug(w_@$(PREFIX)_sdwb_debug)\n\t\t// }}}\n\t);\n\n\t// }}}\n@MAIN.ALT=\n@REGS.N=5\n@REGS.NOTE= // @$(NAME) addresses\n@REGS.0= 0 R_@$(DEVID)_CTRL  \tSDCARD\n@REGS.1= 1 R_@$(DEVID)_DATA \tSDDATA\n@REGS.2= 2 R_@$(DEVID)_FIFOA\tSDFIFOA, SDFIF0, SDFIFA\n@REGS.3= 3 R_@$(DEVID)_FIFOB\tSDFIFOB, SDFIF1, SDFIFB\n@REGS.4= 4 R_@$(DEVID)_PHY\tSDPHY\n@BDEF.DEFN=\n////////////////////////////////////////////////////////////////////////////////\n//\n// @$(NAME) constants\n// {{{\n////////////////////////////////////////////////////////////////////////////////\n//\n//\n\n// These will be defined in sdiodrv.h for the SDIO controller\nstruct @$(DEVID)_S;\n// }}}\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE=struct @$(DEVID)_S\n@BDEF.OSDEF=_BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$(BDEF.IOTYPE) *)@$[0x%08x](REGBASE));\n@SIM.CLOCK=clk\n@SIM.INCLUDE=\n#include \"sdiosim.h\"\n@SIM.DEFNS=\n\tSDIOSIM\t\t*m_@$(PREFIX);\n@SIM.FILE=\"sdcard.img\"\n@SIM.INIT=\n#ifdef\t@$(ACCESS)\n\t\tm_@$(PREFIX) = new SDIOSIM(@$(SIM.FILE));\n\t\tm_core->i_sdio_detect = 1;\n\t\tm_core->i_@$(PREFIX)_crcack = 0;\n\t\tm_core->i_@$(PREFIX)_crcnak = 0;\n#endif\n@SIM.TICK=\n#ifdef\t@$(ACCESS)\n\t\t{ unsigned\ttmp, tmp_async;\n\t\tm_@$(PREFIX)->apply(\n\t\t\t(unsigned)m_core->o_@$(PREFIX)_sdclk,\n\t\t\t(unsigned)m_core->o_@$(PREFIX)_cfg_ddr,\n\t\t\t(unsigned)m_core->o_@$(PREFIX)_cmd_en,\n\t\t\t(unsigned)m_core->o_@$(PREFIX)_cmd_data,\n\t\t\t(unsigned)m_core->o_@$(PREFIX)_data_en,\n\t\t\t(unsigned)m_core->o_@$(PREFIX)_rx_en,\n\t\t\t(unsigned)m_core->o_@$(PREFIX)_tx_data,\n\t\t\ttmp, tmp_async,\n\t\t\tm_core->i_@$(PREFIX)_ad_data);\n\t\tm_core->i_@$(PREFIX)_cmd_strb = (tmp >> 30) & 3;\n\t\tm_core->i_@$(PREFIX)_cmd_data = (tmp >> 28) & 3;\n\t\tm_core->i_@$(PREFIX)_rx_strb  = (tmp >> 24) & 3;\n\t\tm_core->i_@$(PREFIX)_rx_data  =  tmp & 0x0ffff;\n\t\tm_core->i_@$(PREFIX)_ac_valid = (tmp_async & 2) ? 1:0;\n\t\tm_core->i_@$(PREFIX)_ad_valid =  tmp_async & 1;\n\t\tm_core->i_@$(PREFIX)_detect = 1;\n\t\tm_core->i_@$(PREFIX)_card_busy = m_@$(PREFIX)->card_busy() ? 1:0;\n\t\tm_core->i_@$(PREFIX)_crcack = m_@$(PREFIX)->crctoken();\n\t\tm_core->i_@$(PREFIX)_crcnak = (m_core->i_@$(PREFIX)_crcack & 2)?1:0;\n\t\tm_core->i_@$(PREFIX)_crcack &= 1;\n\n\t\tif (!m_core->o_@$(PREFIX)_cfg_dscmd) {\n\t\t\tm_core->i_@$(PREFIX)_ac_valid = 0;\n\t\t\tm_core->i_@$(PREFIX)_ac_data = 0;\n\t\t} if (!m_core->o_@$(PREFIX)_cfg_ds) {\n\t\t\tm_core->i_@$(PREFIX)_ad_valid = 0;\n\t\t\tm_core->i_@$(PREFIX)_ad_data = 0;\n\t\t} }\n#endif\n@RTL.MAKE.GROUP= SDIO\n@RTL.MAKE.SUBD=sdspi\n@RTL.MAKE.FILES= sdio.v sdfrontend.v sdckgen.v sdwb.v sdtxframe.v sdrxframe.v sdcmd.v sddma.v sddma_mm2s.v sddma_rxgears.v sdfifo.v sddma_txgears.v sddma_s2mm.v xsdddr.v xsdserdes8x.v\n@XDC.SERDES=\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ u_@$(PREFIX)_frontend/GEN_WIDE_IO.r_debug*}] -to [get_cells -hier -filter {NAME=~ u_@$(PREFIX)_frontend/GEN_WIDE_IO.cmd_serdes/u_oserdes*}] 4.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ u_@$(PREFIX)_frontend/GEN_WIDE_IO.r_debug*}] -to [get_cells -hier -filter {NAME=~ u_@$(PREFIX)_frontend/GEN_WIDE_IO.GEN_WIDE_DATIO*.io_serdes/u_oserdes*}] 4.0\n@XDC.INSERT=\nset_property -dict { PULLTYPE PULLUP } [get_ports io_@$(TOP.IOPREFIX)_cmd]\n@$(XDC.SERDES)\n"
  },
  {
    "path": "auto-data/sdspi.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/sdspi.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tDescribes how to connect an SD-SPI peripheral to a wishbone\n##\t\tbus, as used by autofpga.  Note how the description requires\n##\tboth a description of what needs to take place in a top level file, as\n##\twell as in the main\n##\n##\tAn interesting consequence of this description is that upgrading to a\n##\tproper SDIO device would involve no more than swapping this file for an\n##\tsdio.c peripheral description file.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=sdcard\n@DEVID=SDSPI\n@NADDR=4\n@ACCESS=SDSPI_ACCESS\n@SLAVE.TYPE=OTHER\n@SLAVE.BUS=wb32\n@BUS.NAME=wb\n@INT.SDCARD.WIRE= @$(PREFIX)_int\n@INT.SDCARD.PIC= buspic syspic\n@IOPREFIX=@$(PREFIX)\n@TOP.PORTLIST=\n\t\t// SD Card\n\t\to_@$(IOPREFIX)_clk, io_@$(IOPREFIX)_cmd, io_@$(IOPREFIX)_dat, i_@$(IOPREFIX)_cd_n\n@TOP.IODECL=\n\t// SD Card\n\t// {{{\n\toutput\twire\t\to_@$(IOPREFIX)_clk;\n\tinout\twire\t\tio_@$(IOPREFIX)_cmd;\n\tinout\twire\t[3:0]\tio_@$(IOPREFIX)_dat;\n\tinput\twire\t\ti_@$(IOPREFIX)_cd_n;\n\t// }}}\n@TOP.DEFNS=\n\t// SD Card definitions\n\t// {{{\n\twire\t\tw_@$(IOPREFIX)_cmd;\n\twire\t[3:0]\tw_@$(IOPREFIX)_data;\n\n\twire\t\ti_@$(IOPREFIX)_cmd;\n\twire\t[3:0]\ti_@$(IOPREFIX)_data;\n\t// }}}\n@TOP.MAIN=\n\t\t// SD Card\n\t\to_@$(IOPREFIX)_clk, w_@$(IOPREFIX)_cmd, w_@$(IOPREFIX)_data, i_@$(IOPREFIX)_data, !i_@$(IOPREFIX)_cd_n\n@TOP.INSERT=\n\t//////////////////////////////////////////////////////////////////////\n\t//\n\t// SD Card SPI Controller\n\t// {{{\n\t//////////////////////////////////////////////////////////////////////\n\t//\n\t//\n\n\t// Wires for setting up the SD Card Controller\n\t// {{{\n\t// This is how we'd set up for SDIO\n\t// assign io_@$(PREFIX)_cmd = w_@$(PREFIX)_cmd ? 1'bz:1'b0;\t// MOSI\n\t// assign io_@$(PREFIX)[0] = w_@$(PREFIX)_data[0]? 1'bz:1'b0;\t// MISO\n\t// assign io_@$(PREFIX)[1] = w_@$(PREFIX)_data[1]? 1'bz:1'b0;\n\t// assign io_@$(PREFIX)[2] = w_@$(PREFIX)_data[2]? 1'bz:1'b0;\n\t// assign io_@$(PREFIX)[3] = w_@$(PREFIX)_data[3]? 1'bz:1'b0;\t// CS_n\n\t// }}}\n\tIOBUF @$(PREFIX)_cmd_bf(.T(1'b0),.O(i_@$(IOPREFIX)_cmd),.I(w_@$(IOPREFIX)_cmd),.IO(io_@$(IOPREFIX)_cmd));// MISO\n\tIOBUF @$(PREFIX)_dat0_bf(.T(1'b1),.O(i_@$(IOPREFIX)_data[0]),.I(1'b1),.IO(io_@$(IOPREFIX)_dat[0]));// MISO\n\tIOBUF @$(PREFIX)_dat1_bf(.T(1'b1),.O(i_@$(IOPREFIX)_data[1]),.I(1'b1),.IO(io_@$(IOPREFIX)_dat[1]));\n\tIOBUF @$(PREFIX)_dat2_bf(.T(1'b1),.O(i_@$(IOPREFIX)_data[2]),.I(1'b1),.IO(io_@$(IOPREFIX)_dat[2]));\n\n\t// Implement an open-drain output\n\tIOBUF @$(PREFIX)_dat3_bf(.T(w_@$(IOPREFIX)_data[3]),.O(i_@$(IOPREFIX)_data[3]),.I(1'b0),.IO(io_@$(IOPREFIX)_dat[3]));\n\t// }}}\n@MAIN.PORTLIST=\n\t\t// The SD-Card wires\n\t\to_@$(PREFIX)_clk, o_@$(PREFIX)_cmd, o_@$(PREFIX)_data, i_@$(PREFIX)_data, i_@$(PREFIX)_detect\n@MAIN.IODECL=\n\t// SD-Card declarations\n\t// {{{\n\toutput\twire\t\to_@$(PREFIX)_clk, o_@$(PREFIX)_cmd;\n\toutput\twire\t[3:0]\to_@$(PREFIX)_data;\n\t// verilator lint_off UNUSED\n\tinput\twire\t\ti_@$(PREFIX)_cmd;\n\tinput\twire\t[3:0]\ti_@$(PREFIX)_data;\n\t// verilator lint_on  UNUSED\n\tinput\twire\t\ti_@$(PREFIX)_detect;\n\t// }}}\n@MAIN.DEFNS=\n\t// SD SPI definitions\n\t// Verilator lint_off UNUSED\n\twire\t[31:0]\t@$(PREFIX)_debug;\n\t// Verilator lint_on  UNUSED\n\twire\t\tw_@$(PREFIX)_cs_n, w_@$(PREFIX)_mosi, w_@$(PREFIX)_miso;\n@MAIN.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// SD Card SPI handling\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t//\n\n\tsdspi #(\n\t\t// {{{\n\t\t.OPT_CARD_DETECT(1'b1),\n\t\t.OPT_LITTLE_ENDIAN(1'b0),\n\t\t.OPT_SPI_ARBITRATION(1'b0)\n\t\t// }}}\n\t) u_@$(PREFIX)(\n\t\t// {{{\n\t\t.i_clk(@$(SLAVE.BUS.CLOCK.WIRE)),\n\t\t.i_sd_reset(@$(SLAVE.BUS.CLOCK.RESET)),\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t.o_cs_n(w_@$(PREFIX)_cs_n),\n\t\t.o_sck(o_@$(PREFIX)_clk),\n\t\t.o_mosi(w_@$(PREFIX)_mosi),\n\t\t.i_miso(w_@$(PREFIX)_miso),\n\t\t.i_card_detect(i_@$(PREFIX)_detect),\n\t\t.o_int(@$(PREFIX)_int),\n\t\t.i_bus_grant(1'b1),\n\t\t.o_debug(@$(PREFIX)_debug)\n\t\t// }}}\n\t);\n\n\tassign\tw_@$(PREFIX)_miso = i_@$(PREFIX)_data[0];\n\tassign\to_@$(PREFIX)_data = { w_@$(PREFIX)_cs_n, 3'b111 };\n\tassign\to_@$(PREFIX)_cmd  = w_@$(PREFIX)_mosi;\n\t// }}}\n@MAIN.ALT=\n\tassign\to_@$(PREFIX)_clk   = 1'b1;\n\tassign\to_@$(PREFIX)_cmd   = 1'b1;\n\tassign\to_@$(PREFIX)_data  = 4'hf;\n@REGS.N=4\n@REGS.NOTE= // SD-SPI addresses\n@REGS.0= 0 R_@$(DEVID)_CTRL  \tSDCARD\n@REGS.1= 1 R_@$(DEVID)_DATA \tSDDATA\n@REGS.2= 2 R_@$(DEVID)_FIFOA\tSDFIFOA, SDFIF0, SDFIFA\n@REGS.3= 3 R_@$(DEVID)_FIFOB\tSDFIFOB, SDFIF1, SDFIFB\n@BDEF.DEFN=\n////////////////////////////////////////////////////////////////////////////////\n//\n// SD SPI constants\n// {{{\n////////////////////////////////////////////////////////////////////////////////\n//\n//\n\n#ifndef\t@$(DEVID)_H\n#define @$(DEVID)_H\n\nstruct @$(DEVID)_S;\n\n#endif\t// @$(DEVID)_H\n// }}}\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE=struct @$(DEVID)_S\n@BDEF.OSDEF=_BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$(BDEF.IOTYPE) *)@$[0x%08x](REGBASE));\n@SIM.CLOCK=clk\n@SIM.INCLUDE=\n#include \"sdspisim.h\"\n@SIM.DEFNS=\n#ifdef\tSDSPI_ACCESS\n\tSDSPISIM\tm_@$(PREFIX);\n#endif // @$(ACCESS)\n@SIM.INIT=\n#ifdef\t@$(ACCESS)\n\t\tm_@$(PREFIX).debug(false);\n#endif\t// @$(ACCESS)\n@SIM.METHODS=\n#ifdef\t@$(ACCESS)\n\tvoid\tsetsdcard(const char *fn) {\n\t\tm_@$(PREFIX).load(fn);\n\t}\n#endif // @$(ACCESS)\n@SIM.TICK=\n\t\t// SD Card simulation\n\t\t// {{{\n#ifdef\t@$(ACCESS)\n\t\tm_core->i_@$(PREFIX)_data = m_@$(PREFIX)(\n\t\t\t\t(m_core->o_@$(PREFIX)_data&8)?1:0,\n\t\t\t\tm_core->o_@$(PREFIX)_clk,\n\t\t\t\tm_core->o_@$(PREFIX)_cmd);\n\t\tm_core->i_@$(PREFIX)_data &= 1;\n\t\tm_core->i_@$(PREFIX)_data |= (m_core->o_@$(PREFIX)_data&0x0e);\n\t\tm_core->i_@$(PREFIX)_detect = 1;\n#endif\t// @$(ACCESS)\n\t\t// }}}\n@SIM.DEFINES=\n////////////////////////////////////////////////////////////////////////////////\n//\n// SD SPI Defines\n// {{{\n////////////////////////////////////////////////////////////////////////////////\n//\n//\n\n#ifndef\tVVAR\n#ifdef\tROOT_VERILATOR\n\n#include \"Vmain___024root.h\"\n#define\tVVAR(A)\trootp->main__DOT_ ## A\n\n#elif\tdefined(NEW_VERILATOR)\n#define\tVVAR(A)\tmain__DOT_ ## A\n#else\n#define\tVVAR(A)\tv__DOT_ ## A\n#endif\n#endif\n\n#define\tsd_cmd_busy\tVVAR(_@$(PREFIX)i__DOT__r_cmd_busy)\n#define\tsd_clk\t\tVVAR(_@$(PREFIX)i__DOT__r_sdspi_clk)\n#define\tsd_cmd_state\tVVAR(_@$(PREFIX)i__DOT__r_cmd_state)\n#define\tsd_rsp_state\tVVAR(_@$(PREFIX)i__DOT__r_rsp_state)\n#define\tsd_ll_cmd_stb\tVVAR(_@$(PREFIX)__DOT__ll_cmd_stb)\n#define\tsd_ll_cmd_dat\tVVAR(_@$(PREFIX)__DOT__ll_cmd_dat)\n#define\tsd_ll_z_counter\tVVAR(_@$(PREFIX)__DOT__lowlevel__DOT__r_z_counter)\n#define\tsd_ll_clk_counter\tVVAR(_@$(PREFIX)__DOT__lowlevel__DOT__r_clk_counter)\n#define\tsd_ll_idle\tVVAR(_@$(PREFIX)__DOT__lowlevel__DOT__r_idle)\n#define\tsd_ll_state\tVVAR(_@$(PREFIX)__DOT__lowlevel__DOT__r_state)\n#define\tsd_ll_byte\tVVAR(_@$(PREFIX)__DOT__lowlevel__DOT__r_byte)\n#define\tsd_ll_ireg\tVVAR(_@$(PREFIX)__DOT__lowlevel__DOT__r_ireg)\n#define\tsd_ll_out_stb\tVVAR(_@$(PREFIX)__DOT__ll_out_stb)\n#define\tsd_ll_out_dat\tVVAR(_@$(PREFIX)__DOT__ll_out_dat)\n#define\tsd_lgblklen\tVVAR(_@$(PREFIX)__DOT__r_lgblklen)\n#define\tsd_fifo_rd_crc\tVVAR(_@$(PREFIX)__DOT__fifo_rd_crc_reg)\n#define\tsd_cmd_crc\tVVAR(_@$(PREFIX)__DOT__r_cmd_crc)\n#define\tsd_cmd_crc_cnt\tVVAR(_@$(PREFIX)__DOT__r_cmd_crc_cnt)\n#define\tsd_fifo_rd_crc_stb\tVVAR(_@$(PREFIX)__DOT__fifo_rd_crc_stb)\n#define\tll_fifo_pkt_state\tVVAR(_@$(PREFIX)__DOT__ll_fifo_pkt_state)\n#define\tsd_have_data_response_token\tVVAR(_@$(PREFIX)__DOT__r_have_data_response_token)\n#define\tsd_fifo_wr_crc\t\tVVAR(_@$(PREFIX)__DOT__fifo_wr_crc_reg)\n#define\tsd_fifo_wr_crc_stb\tVVAR(_@$(PREFIX)__DOT__fifo_wr_crc_stb,)\n#define\tsd_ll_fifo_wr_state\tVVAR(_@$(PREFIX)__DOT__ll_fifo_wr_state,)\n#define\tsd_ll_fifo_wr_complete\tVVAR(_@$(PREFIX)__DOT__ll_fifo_wr_complete)\n#define\tsd_use_fifo\tVVAR(_@$(PREFIX)__DOT__r_use_fifo)\n#define\tsd_fifo_wr\tVVAR(_@$(PREFIX)__DOT__r_fifo_wr)\n\n@SIM.DEBUG=\n\t\t\t/*\n\t\t\tprintf(\" SDSPI[%d,%d(%d),(%d)]\",\n\t\t\t\tm_core->sd_cmd_busy,\n\t\t\t\tm_core->sd_clk,\n\t\t\t\tm_core->sd_cmd_state,\n\t\t\t\tm_core->sd_rsp_state);\n\t\t\tprintf(\" LL[%d,%2x->CK=%d/%2x,%s,ST=%2d,TX=%2x,RX=%2x->%d,%2x] \",\n\t\t\t\tm_core->sd_ll_cmd_stb,\n\t\t\t\tm_core->sd_ll_cmd_dat,\n\t\t\t\tm_core->sd_ll_z_counter,\n\t\t\t\t// (m_core->sd_ll_clk_counter==0)?1:0,\n\t\t\t\tm_core->sd_ll_clk_counter,\n\t\t\t\t(m_core->sd_ll_idle)?\"IDLE\":\"    \",\n\t\t\t\tm_core->sd_ll_state,\n\t\t\t\tm_core->sd_ll_byte,\n\t\t\t\tm_core->sd_ll_ireg,\n\t\t\t\tm_core->sd_ll_out_stb,\n\t\t\t\tm_core->sd_ll_out_dat\n\t\t\t\t);\n\t\t\tprintf(\" CRC=%02x/%2d\",\n\t\t\t\tm_core->sd_cmd_crc,\n\t\t\t\tm_core->sd_cmd_crc_cnt);\n\t\t\tprintf(\" SPI(%d,%d,%d/%d,%d)->?\",\n\t\t\t\tm_core->o_sf_cs_n,\n\t\t\t\tm_core->o_sd_cs_n,\n\t\t\t\tm_core->o_spi_sck,\n\t\t\t\tm_core->@$(VERILATOR_PREFIX)__DOT__sdcard_sck,\n\t\t\t\tm_core->o_spi_mosi);\n\n\t\t\tprintf(\" CK=%d,LN=%d\",\n\t\t\t\tm_core->sd_clk,\n\t\t\t\tm_core->sd_lgblklen);\n\n\n\t\t\tif (m_core->sd_use_fifo){\n\t\t\t\tprintf(\" FIFO\");\n\t\t\t\tif (m_core->sd_fifo_wr)\n\t\t\t\t\tprintf(\"-WR(%04x,%d,%d,%d)\",\n\t\t\t\t\t\tm_core->sd_fifo_rd_crc,\n\t\t\t\t\t\tm_core->sd_fifo_rd_crc_stb,\n\t\t\t\t\t\tm_core->sd_ll_fifo_pkt_state,\n\t\t\t\t\t\tm_core->sd_have_data_response_token);\n\t\t\t\telse\n\t\t\t\t\tprintf(\"-RD(%04x,%d,%d,%d)\",\n\t\t\t\t\t\tm_core->sd_fifo_wr_crc,\n\t\t\t\t\t\tm_core->sd_fifo_wr_crc_stb,\n\t\t\t\t\t\tm_core->sd_ll_fifo_wr_state,\n\t\t\t\t\t\tm_core->sd_ll_fifo_wr_complete\n\t\t\t\t\t\t);\n\t\t\t}\n\t\t\t*/\n##\n@RTL.MAKE.GROUP= SDSPI\n@RTL.MAKE.SUBD=sdspi\n@RTL.MAKE.FILES= sdspi.v llsdspi.v spicmd.v spirxdata.v spitxdata.v\n"
  },
  {
    "path": "auto-data/spio.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/spio.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tTo describe how to interact with the special purpose device\n##\t\tcontroller (spio) for the Nexys Video Board (SW, BTN, LEDs)\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=spio\n@DEVID=SPIO\n@NADDR=1\n@SLAVE.TYPE=SINGLE\n@SLAVE.BUS=wb32\n@ACCESS=@$(DEVID)_ACCESS\n@INT.SPIO.WIRE=@$(PREFIX)_int\n@INT.SPIO.PIC=buspic\n@NLED=8\n@NBTN=5\n@NSW=8\n@TOP.DEFNS=\n\twire\t[@$(NLED)-1:0]\tw_led;\n@TOP.INSERT=\n\tassign\to_led = { w_led[@$(NLED)-1:3],\n\t\t\t(w_led[2] || !syncd_stable[3]),\n\t\t\t(w_led[1] || !clocks_locked),\n\t\t\t(w_led[0] || s_reset) };\n@TOP.MAIN=\n\t\ti_sw, i_btnc, i_btnd, i_btnl, i_btnr, i_btnu, w_led\n@MAIN.PORTLIST=\n\t\t// SPIO interface\n\t\ti_sw, i_btnc, i_btnd, i_btnl, i_btnr, i_btnu, o_led\n@MAIN.IODECL=\n\t// @$(DEVID) interface\n\tinput\twire\t[@$(NSW)-1:0]\ti_sw;\n\tinput\twire\t\ti_btnc, i_btnd, i_btnl, i_btnr, i_btnu;\n\toutput\twire\t[@$(NLED)-1:0]\to_led;\n@MAIN.DEFNS=\n\twire\t[@$(NBTN)-1:0]\tw_btn;\n\twire\t[@$(NLED)-1:0]\tw_led;\n@MAIN.INSERT=\n\t//\n\t// Special purpose I/O driver (buttons, LEDs, and switches)\n\t//\n\tassign\tw_btn = { i_btnc, i_btnd, i_btnl, i_btnr, i_btnu };\n\n\tspio #(\n\t\t.NBTN(@$(NBTN)), .NLEDS(@$(NLED)), .NSW(@$(NSW))\n\t) u_@$(PREFIX) (\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t.i_sw(i_sw), .i_btn(w_btn), .o_led(w_led),\n\t\t.o_int(@$(PREFIX)_int)\n\t);\n\n\tassign\to_led = w_led;\n\n@MAIN.ALT=\n\tassign\tw_btn = 0;\n\tassign\to_led = 0;\n@REGS.N=1\n@REGS.0= 0 R_@$(DEVID) @$(DEVID)\n@BDEF.DEFN=\n#define\tSPIO_BTNC\t0x01000\n#define\tSPIO_BTND\t0x00800\n#define\tSPIO_BTNL\t0x00400\n#define\tSPIO_BTNR\t0x00200\n#define\tSPIO_BTNU\t0x00100\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE=unsigned\n@BDEF.OSDEF= _BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL= static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$(BDEF.IOTYPE) *)@$[0x%08x](REGBASE));\n"
  },
  {
    "path": "auto-data/vadj33.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/vadj33.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tSet the IO ports to 3.3Volts\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=vadj33\n@DEVID=VADJ\n@ACCESS=@$(DEVID)_ACCESS\n@TOP.PORTLIST=\n\t\t// @$(DEVID) ports\n\t\to_vadj_en, o_vadj\n@TOP.IODECL=\n\t// @$(DEVID) wires\n\toutput\twire\t\to_vadj_en;\n\toutput\twire [1:0]\to_vadj;\n@TOP.DEFNS=\n\treg\t[4:0]\t@$(PREFIX)_vadj_counter;\n@TOP.INSERT=\n\tassign\to_vadj = 2'b11;\n\tinitial\t@$(PREFIX)_vadj_counter = 0;\n\talways @(posedge i_clk_buffered)\n\tif (!@$(PREFIX)_vadj_counter[4])\n\t\t@$(PREFIX)_vadj_counter[4] <= @$(PREFIX)_vadj_counter[4] + 1;\n\tassign\to_vadj_en = @$(PREFIX)_vadj_counter[4];\n"
  },
  {
    "path": "auto-data/version.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/version.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\t\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=version\n@DEVID=VERSION\n@ACCESS=VERSION_ACCESS\n@NADDR=1\n@SLAVE.TYPE=SINGLE\n@SLAVE.BUS=wb32\n@MAIN.INCLUDE=\n`include \"builddate.v\"\n@MAIN.INSERT=\n\tassign\t@$(SLAVE.PREFIX)_idata = `DATESTAMP;\n\tassign\t@$(SLAVE.PREFIX)_ack = @$(SLAVE.PREFIX)_stb;\n\tassign\t@$(SLAVE.PREFIX)_stall = 1'b0;\n@REGS.N=1\n@REGS.0= 0 R_@$(DEVID) @$(DEVID)\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE=unsigned\n@BDEF.OSDEF=_BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$(BDEF.IOTYPE) *)@$[0x%08x](REGBASE));\n##\n##\n##\n@PREFIX=buildtime\n@DEVID=BUILDTIME\n@NADDR=1\n@SLAVE.TYPE=SINGLE\n@SLAVE.BUS=wb32\n@MAIN.DEFNS=\n// BUILDTIME doesnt need to include builddate.v a second time\n// `include \"builddate.v\"\n@MAIN.INSERT=\n\tassign\t@$(SLAVE.PREFIX)_idata = `BUILDTIME;\n\tassign\t@$(SLAVE.PREFIX)_ack = @$(SLAVE.PREFIX)_stb;\n\tassign\t@$(SLAVE.PREFIX)_stall = 1'b0;\n@REGS.N=1\n@REGS.0= 0 R_@$(DEVID) @$(DEVID) BUILDTIME\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE=unsigned\n@BDEF.OSDEF=_BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$(BDEF.IOTYPE) *)@$[0x%08x](REGBASE));\n"
  },
  {
    "path": "auto-data/wboledbw.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/wboledbw.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tTo describe how to interact with an OLED device driver, in order\n##\t\tto drive an OLED display.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=oled\n@NADDR=4\n@DEVID=OLEDBW\n@ACCESS=@$(DEVID)_ACCESS\n@SLAVE.TYPE=DOUBLE\n@SLAVE.BUS=wb32\n@MASTER.TYPE=CPU\n@MASTER.BUS=wbwide\n@MASTER.PREFIX=@$(MASTER.BUS.NAME)_@$(PREFIX)m\n@MASTER.ANSPREFIX=pf_\n@INT.OLED.WIRE=oled_int\n@INT.OLED.PIC=syspic\n@MAIN.PORTLIST=\n\t\t// OLED control interface (roughly SPI)\n\t\to_oled_sck, o_oled_mosi, o_oled_dcn\n@MAIN.IODECL=\n\t// OLEDBW interface\n\toutput\twire\t\to_oled_sck, o_oled_mosi, o_oled_dcn;\n@MAIN.DEFNS=\n\t// OLEDBW\n\t// {{{\n\t// Verilator lint_off UNUSED\n\twire\t[1:0]\tw_oled_csn;\n\twire\t\tign_@$(PREFIX)_valid, ign_@$(PREFIX)_last,\n\t\t\tign_@$(PREFIX)_id;\n\twire\t[7:0]\tign_@$(PREFIX)_data;\n\twire\t[31:0]\t@$(PREFIX)_debug;\n\t// Verilator lint_on  UNUSED\n\t// }}}\n@MAIN.INSERT=\n\tspicpu #(\n\t\t// {{{\n\t\t.ADDRESS_WIDTH(@$(MASTER.BUS.AWID)),\n\t\t.DATA_WIDTH(@$(MASTER.BUS.WIDTH)),\n\t\t.NCE(2),\n\t\t.OPT_MANUAL(1'b1), .OPT_LITTLE_ENDIAN(1'b0),\n\t\t.OPT_START_HALTED(1'b1), .OPT_SHARED_MISO(1'b1)\n\t\t// }}}\n\t) u_@$(PREFIX) (\n\t\t// {{{\n\t\t.i_clk(@$(SLAVE.BUS.CLOCK.WIRE)), .i_reset(@$(SLAVE.BUS.CLOCK.RESET)),\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t@$(MASTER.ANSIPORTLIST),\n\t\t.o_spi_csn(w_oled_csn), .o_spi_sck(o_oled_sck),\n\t\t.o_spi_mosi(o_oled_mosi), .i_spi_miso(1'b0),\n\t\t.M_AXIS_TVALID(ign_@$(PREFIX)_valid),\n\t\t.M_AXIS_TREADY(1'b1),\n\t\t.M_AXIS_TDATA( ign_@$(PREFIX)_data),\n\t\t.M_AXIS_TLAST( ign_@$(PREFIX)_last),\n\t\t.M_AXIS_TID(   ign_@$(PREFIX)_id),\n\t\t//\n\t\t.o_interrupt(oled_int),\n\t\t.i_sync_signal(rtc_pps),\n\t\t.o_debug(@$(PREFIX)_debug)\n\t\t// }}}\n\t);\n\n\tassign\to_oled_dcn = w_oled_csn[0];\n@MAIN.ALT=\n\tassign\to_oled_sck     = 1'b1;\n\tassign\to_oled_mosi    = 1'b1;\n\tassign\to_oled_dcn     = 1'b1;\n\n@REGS.N=4\n@REGS.0= 0 R_OLED\t\tOLED\n@REGS.1= 1 R_OLED_OV\t\tOLEDOV\n@REGS.2= 2 R_OLED_ADDR\t\tOLEDADDR\n@REGS.3= 3 R_OLED_CLK\t\tOLEDCLK\n@BDEF.DEFN=\ntypedef\tstruct OLEDBW_S {\n\tunsigned\to_cmd, o_override, o_addr, o_clk;\n} OLEDBW;\n\n@BDEF.IONAME=_oled\n@BDEF.IOTYPE=OLEDBW\n@BDEF.OSDEF= _BOARD_HAS_OLEDBW\n@BDEF.OSVAL= static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$(BDEF.IOTYPE) *)@$(REGBASE));\n@RTL.MAKE.GROUP=WBSPI\n@RTL.MAKE.SUBD=wbspi\n@RTL.MAKE.FILES=spicpu.v\n"
  },
  {
    "path": "auto-data/wbpmic.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/wbpmic.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tTo describe the interface of a very simple ADC (PModMIC3) for\n##\t\tautogen to work with.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=pmic\n@NADDR=\t2\n@SLAVE.TYPE=\tOTHER\n@SLAVE.BUS=wb32\n@ACCESS= MICROPHONE_ACCESS\n@$SAMPLERATE=48000\n@$CLKSPERSAMPLE.EXPR=@$CLKFREQHZ/@$.SAMPLERATE\n@UARTSETUP.FORMAT=20'h%08x\n@INT.MIC.WIRE=pmic_int\n@INT.MIC.PIC=syspic\n@MAIN.PORTLIST=\n\t\t// The PMic3 microphone wires\n\t\to_mic_csn, o_mic_sck, i_mic_din\n@MAIN.IODECL=\n\toutput\twire\t\to_mic_csn, o_mic_sck;\n\tinput\twire\t\ti_mic_din;\n@MAIN.INSERT=\n\twbmic #(.DEFAULT_RELOAD(@$.CLKSPERSAMPLE))\n\t\tmicrophone(i_clk, 1'b0,\n\t\t\t@$(SLAVE.PORTLIST),\n\t\t\to_mic_csn, o_mic_sck, i_mic_din, pmic_int);\n@MAIN.ALT=\n\tassign\to_mic_csn    = 1'b1;\n\tassign\to_mic_sck    = 1'b1;\n@REGS.NOTE = // WB-Microphone registers\n@REGS.N = 2\n@REGS.0 = 0 R_MIC_DATA\t\t MICD\n@REGS.1 = 1 R_MIC_CTRL\t\t MICC\n@BDEF.DEFN =\n#define WBMIC_ENABLE\t0\n#define WBMIC_DISABLE\t(1<<20)\n#define WBMIC_NONEMPTY\t0\n#define WBMIC_HALFINT\t(1<<22)\n#define WBMIC_RESET\t(1<<24)\n\ntypedef struct  WBMIC_S {\n\tunsigned\tm_data;\n\tunsigned\tm_setup;\n} WBMIC;\n@BDEF.IONAME= io_wbmic\n@BDEF.IOTYPE= WBMIC\n@BDEF.OSDEF=\t_BOARD_HAS_WBMIC\n@BDEF.OSVAL=static volatile @$.BDEF.IOTYPE *const _wbmic = ((@$.BDEF.IOTYPE *)@$(REGBASE));\n"
  },
  {
    "path": "auto-data/wbscopc.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/wbscopc.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tA generic scope description, from which other internal wbscopes\n##\t\tmay depend upon\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=scopc\n@DEVID=SCOPC\n@ACCESS=@$(DEVID)_SCOPC\n@CORE=wbscopc\n@REGS.NOTE=// @$(PREFIX) compressed scope\n@RTL.MAKE.GROUP=SCOPC\n@RTL.MAKE.FILES=wbscopc.v\n@TRIGGER=@$(TARGET)_debug[31]\n@DEBUG=@$(TARGET)_debug[30:0]\n@INCLUDEFILE=wbscope.txt\n"
  },
  {
    "path": "auto-data/wbscope.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/wbscope.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tA generic scope description, from which other internal wbscopes\n##\t\tmay depend upon\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=scope\n@DEVID=SCOPE\n@NADDR= 2\n@ACCESS=@$(DEVID)_SCOPE\n@SLAVE.TYPE=OTHER\n@SLAVE.BUS=wb32\n@$LOG_CAPTURE_SIZE=12\n@DATA_CLOCK=i_clk\n@CAPTURECE=1'b1\n@SYNCHRONOUS=1\n@CORE=wbscope\n@TRIGGER=@$(TARGET)_dbg_trigger\n@DEBUG=@$(TARGET)_debug\n@$DEFHOLDOFF= (1<<(@$(LOG_CAPTURE_SIZE)-1))-4\n@MAIN.DEFNS=\n\t// Remove this scope tag via inheritance when/if you connect the\n\t// scope interrupt\n\t//\n\t// Verilator lint_off UNUSED\n\twire\t@$(PREFIX)_int;\n\t// Verilator lint_on  UNUSED\n@MAIN.INSERT=\n\t@$(CORE) #(\n\t\t// {{{\n\t\t.LGMEM(@$(LOG_CAPTURE_SIZE)),\n\t\t.SYNCHRONOUS(@$(SYNCHRONOUS)),\n\t\t.DEFAULT_HOLDOFF(@$(DEFHOLDOFF))\n\t\t// }}}\n\t) u_@$(PREFIX) (\n\t\t// {{{\n\t\t.i_data_clk(@$(DATA_CLOCK)), .i_ce(@$(CAPTURECE)),\n\t\t.i_trigger(@$(TRIGGER)), .i_data(@$(DEBUG)),\n\t\t.i_wb_clk(@$(SLAVE.BUS.CLOCK.WIRE)),\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t.o_interrupt(@$(PREFIX)_int)\n\t\t// }}}\n\t);\n@MAIN.ALT=\n@REGS.NOTE=// @$(PREFIX) scope\n@REGS.N=2\n@REGS.0=0 R_@$(DEVID)  @$(DEVID)\n@REGS.1=1 R_@$(DEVID)D @$(DEVID)D\n@RTL.MAKE.GROUP=SCOPE\n@RTL.MAKE.SUBD=wbscope\n@RTL.MAKE.FILES=@$(CORE).v\n@BDEF.DEFN=\n#ifndef\tWBSCOPE_H\n#define\tWBSCOPE_H\n\n#define\tWBSCOPE_NO_RESET\t0x80000000u\n#define\tWBSCOPE_STOPPED\t\t0x40000000u\n#define\tWBSCOPE_TRIGGERED\t0x20000000u\n#define\tWBSCOPE_PRIMED\t\t0x10000000u\n#define\tWBSCOPE_TRIGGER\t\t(WBSCOPE_NO_RESET|0x08000000u)\n#define\tWBSCOPE_MANUAL\t\t(WBSCOPE_TRIGGER)\n#define\tWBSCOPE_DISABLE\t\t0x04000000u\n\ntypedef\tstruct\tWBSCOPE_S {\n\tvolatile unsigned s_ctrl, s_data;\n} WBSCOPE;\n#endif\n@BDEF.IONAME=_@$(PREFIX)\n@BDEF.IOTYPE=WBSCOPE\n@BDEF.OSDEF=_BOARD_HAS_@$(DEVID)\n@BDEF.OSVAL=static volatile @$(BDEF.IOTYPE) *const @$(BDEF.IONAME) = ((@$(BDEF.IOTYPE) *)@$[0x%08x](REGBASE));\n"
  },
  {
    "path": "auto-data/wbuarbiter.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/wbuarbiter.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tConnect the debugging bus to the rest of the system.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=wbu_arbiter\n@MASTER.BUS=wbwide\n@MASTER.TYPE=ARBITER\n@SLAVE.BUS=wbu\n@SLAVE.TYPE=OTHER\n@ERROR.WIRE=@$(SLAVE.PREFIX)_err\n## @$NADDR=(1<<@$(MASTER.BUS.AWID))\n@IANSI=i_\n@OANSI=o_\n@SLAVE.ANSPREFIX=s\n@MASTER.ANSPREFIX=w\n@MAIN.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// WBUBUS \"wbu_arbiter\" master->slave connection\n\t// {{{\n\n\twbupsz #(\n\t\t// {{{\n\t\t// Slave bus address width : @$(SLAVE.BUS.AWID)\n\t\t// Slave address width     : @$(SLAVE.AWID)\n\t\t// Master bus address width: @$(MASTER.BUS.AWID)\n\t\t.ADDRESS_WIDTH(@$(MASTER.BUS.AWID)+$clog2(@$(MASTER.BUS.WIDTH)/8)),\n\t\t.SMALL_DW(@$(SLAVE.BUS.WIDTH)),\n\t\t.WIDE_DW(@$(MASTER.BUS.WIDTH)),\n\t\t.OPT_LITTLE_ENDIAN(1'b0)\n\t\t// }}}\n\t) u_@$(SLAVE.BUS.NAME)_@$(MASTER.BUS.NAME)_downsz (\n\t\t// {{{\n\t\t.i_clk(@$(MASTER.BUS.CLOCK.WIRE)),\n\t\t.i_reset(@$(MASTER.BUS.CLOCK.RESET)),\n\t\t@$(SLAVE.ANSIPORTLIST),\n\t\t@$(MASTER.ANSIPORTLIST)\n\t\t// }}}\n\t);\n\n\t// }}}\n@RTL.MAKE.GROUP=UPSZ\n@RTL.MAKE.SUBD=\n@RTL.MAKE.FILES=wbupsz.v\n"
  },
  {
    "path": "auto-data/wbuart.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/wbuart.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tTo describe a UART for autogen to work with.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n# The prefix is used to create a series of bus data lines for interaction with\n# the bus.  In this case, these will be uart_sel, uart_stall, uart_ack, and\n# uart_data.\n@PREFIX=uart\n# The number of addressable registers this peripheral has on the wishbone bus.\n# Set this to zero to have no bus presence.\n@NADDR=\t4\n# The type of peripheral.  This can either:\n#\tNOBUS\tDoesn't reply on the bus\n#\tSINGLE, for a peripheral that only has one address, and whose result\n#\t\tis available on every clock.  In the future, these may be\n#\t\tgathered together into a singleio.v file.\n#\tDOUBLE, for a peripheral that takes one clock to access before its\n#\t\tvalue is available on its output.  This might be true for a\n#\t\tperipheral that has several single-clocked registers within it,\n#\t\twhich then selects from among these registers in one clock\n#\t\tcycle.  In the future, these may be gathered together into a\n#\t\tdoubleio.v file.\n#\tMEMORY\n#\tOTHER (the default), for a peripheral that may take *many* clocks to\n#\t\trespond to a bus transaction, ... one that uses its stall\n#\t\tline of a necessity.\n@SLAVE.TYPE=\tOTHER\n@SLAVE.BUS=wb32\n@ACCESS= CONSOLE_ACCESS\n@$BAUDRATE=1000000\n@$UARTSETUP.EXPR=@$CLKFREQHZ/@$.BAUDRATE\n@UARTSETUP.FORMAT=31'h%08x\n@$SIM.UARTSETUP.EXPR=@$UARTSETUP\n@SIM.UARTSETUP.FORMAT=0x%08x\n@SIM.PORTOFFSET=1\n@INT.INTLIST  = @$(PREFIX)rx_int @$(PREFIX)tx_int @$(PREFIX)rxf_int\n@INT.INTLIST += @$(PREFIX)txf_int\n@INT.UARTRX.WIRE=@$(PREFIX)rx_int\n@INT.UARTTX.WIRE=@$(PREFIX)tx_int\n@INT.UARTRXF.WIRE=@$(PREFIX)rxf_int\n@INT.UARTTXF.WIRE=@$(PREFIX)txf_int\n@INT.UARTRX.PIC=altpic\n@INT.UARTTX.PIC=altpic\n@INT.UARTRXF.PIC=syspic\n@INT.UARTTXF.PIC=syspic\n@CTS=i_@$(PREFIX)_cts_n\n@RTS=o_@$(PREFIX)_rts_n\n@MAIN.PORTLIST=\n\t\t// The UART console\n\t\ti_@$(PREFIX)_rx, o_@$(PREFIX)_tx, @$CTS, @$RTS\n@MAIN.IODECL=\n\tinput\twire\t\ti_@$(PREFIX)_rx, @$CTS;\n\toutput\twire\t\to_@$(PREFIX)_tx, @$RTS;\n@MAIN.INSERT=\n\twbuart #(\n\t\t.INITIAL_SETUP(@$.UARTSETUP)\n\t) u_@$(PREFIX)_uart(\n\t\ti_clk, 1'b0,\n\t\t@$(SLAVE.PORTLIST),\n\t\ti_@$(PREFIX)_rx, o_@$(PREFIX)_tx, @$CTS, @$RTS,\n\t\t@$(PREFIX)rx_int, @$(PREFIX)tx_int,\n\t\t@$(PREFIX)rxf_int, @$(PREFIX)txf_int\n\t);\n@MAIN.ALT=\n\tassign\to_@$(PREFIX)_tx    = 1'b1;\n\tassign\t@$RTS = 1'b0;\n@REGS.NOTE = // WBUART registers\n@REGS.N = 4\n@REGS.0 = 0 R_UART_SETUP\t USETUP\n@REGS.1 = 1 R_UART_FIFO\t\t UFIFO\n@REGS.2 = 2 R_UART_UARTRX\t RX\n@REGS.3 = 3 R_UART_UARTTX\t TX\n\n@BDEF.DEFN =\n#ifndef\tWBUART_H\n#define\tWBUART_H\n\n#define UART_PARITY_NONE        0\n#define UART_HWFLOW_OFF         0x40000000\n#define UART_PARITY_ODD         0x04000000\n#define UART_PARITY_EVEN        0x05000000\n#define UART_PARITY_SPACE       0x06000000\n#define UART_PARITY_MARK        0x07000000\n#define UART_STOP_ONEBIT        0\n#define UART_STOP_TWOBITS       0x08000000\n#define UART_DATA_8BITS         0\n#define UART_DATA_7BITS         0x10000000\n#define UART_DATA_6BITS         0x20000000\n#define UART_DATA_5BITS         0x30000000\n#define UART_RX_BREAK           0x0800\n#define UART_RX_FRAMEERR        0x0400\n#define UART_RX_PARITYERR       0x0200\n#define UART_RX_NOTREADY        0x0100\n#define UART_RX_ERR             (-256)\n#define UART_TX_BUSY            0x0100\n#define UART_TX_BREAK           0x0200\n\ntypedef struct  WBUART_S {\n\tunsigned\tu_setup;\n\tunsigned\tu_fifo;\n\tunsigned\tu_rx, u_tx;\n} WBUART;\n\n#endif\t// WBUART_H\n\n@BDEF.IONAME= _@$PREFIX\n@BDEF.IOTYPE= WBUART\n@BDEF.OSDEF=\t_BOARD_HAS_WBUART\n@BDEF.OSVAL=static volatile WBUART *const @$BDEF.IONAME = ((WBUART *)@$[0x%08x](REGBASE));\n@RTL.MAKE.GROUP=WBUART\n@RTL.MAKE.FILES= wbuart.v ufifo.v rxuart.v txuart.v\n@SIM.INCLUDE=\n#include \"uartsim.h\"\n@SIM.DEFNS=\n#ifdef\t@$(ACCESS)\n\tUARTSIM\t*m_@$(PREFIX);\n#endif // @$(ACCESS)\n@SIM.INIT=\n#ifdef\t@$(ACCESS)\n\t\tm_@$(PREFIX) = new UARTSIM(FPGAPORT+@$(SIM.PORTOFFSET),@$(SIM.UARTSETUP));\n\t\tm_core->@$CTS = 0; // The sim doesnt use flow control\n#endif // @$(ACCESS)\n@SIM.CLOCK=@$(SLAVE.BUS.CLOCK)\n@SIM.TICK=\n#ifdef\t@$(ACCESS)\n\t\tm_core->i_@$(PREFIX)_rx = (*m_@$(PREFIX))(m_core->o_@$(PREFIX)_tx);\n#else\n\t\tm_core->i_@$(PREFIX)_rx = 1;\n#endif // @$(ACCESS)\n\n"
  },
  {
    "path": "auto-data/wbubus.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/wbubus.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tTo describe what needs to be done to make the UART to Wishbone\n##\t\texternal bus master a part of the main .v and toplevel.v files.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\n@PREFIX=wbu\n@ACCESS=WBUBUS_MASTER\n@MASTER.TYPE=HOST\n@MASTER.BUS=wbu\n@BUS.NAME=wbu\n@BUS.CLOCK=clk\n@BUS.WIDTH=32\n@$BAUDRATE=1000000\n@CLOCK.NAME=clk\n@$SETUP=@$(CLOCK.FREQUENCY) / @$BAUDRATE\n@SETUP.FORMAT=24'h%x\n@$BUS_ADDRESS_WIDTH=@$(MASTER.BUS.AWID)\n@BP=@$(MASTER.PREFIX)\n# @TOP.PORTLIST=\n#\t\t// UART/host to wishbone interface\n#\t\ti_host_uart_rx, o_host_uart_tx\n# @TOP.IODECL=\n#\t// UART/host to wishbone interface\n#\tinput\twire\t\ti_host_uart_rx;\n#\toutput\twire\t\to_host_uart_tx;\n# @TOP.MAIN=\n#\t\t// External USB-UART bus control\n#\t\ti_host_uart_rx, o_host_uart_tx\n@MAIN.PORTLIST=\n\t\t// UART/host to wishbone interface\n\t\ti_host_uart_rx, o_host_uart_tx\n@MAIN.IODECL=\n\tinput\twire\t\ti_host_uart_rx;\n\toutput\twire\t\to_host_uart_tx;\n@MAIN.DEFNS=\n\t//\n\t//\n\t// UART interface\n\t//\n\t//\n\tlocalparam [23:0] BUSUART = @$SETUP;\t// @$BAUDRATE baud\n\t//\n\twire\tw_ck_uart, w_uart_tx;\n\twire\t\trx_host_stb;\n\twire\t[7:0]\trx_host_data;\n\twire\t\ttx_host_stb;\n\twire\t[7:0]\ttx_host_data;\n\twire\t\ttx_host_busy;\n\t//\n\t// Definitions for the WB-UART converter.  We really only need one\n\t// (more) non-bus wire--one to use to select if we are interacting\n\t// with the ZipCPU or not.\n\twire\t\twbu_zip_sel;\n\twire\t[0:0]\twbubus_dbg;\n`ifndef\tINCLUDE_ZIPCPU\n\t//\n\t// The bus-console depends upon the zip_dbg wires.  If there is no\n\t// ZipCPU defining them, we'll need to define them here anyway.\n\t//\n\twire\t\tzip_dbg_stall, zip_dbg_ack;\n\twire\t[31:0]\tzip_dbg_data;\n`endif\n@$ZIP_ADDRESS_BIT=@$BUS_ADDRESS_WIDTH-1\n@$ZIP_ADDRESS=(1<<(@$THIS.ZIP_ADDRESS_BIT+2))\n@ZIP_ADDRESS.FORMAT= 0x%08x\n@$ZIP_DBGDATA=4+@$.ZIP_ADDRESS\n@ZIP_DBGDATA.FORMAT= 0x%08x\n@MAIN.INSERT=\n\t// The Host USB interface, to be used by the WB-UART bus\n\trxuartlite\t#(BUSUART) rcv(s_clk, i_host_uart_rx,\n\t\t\t\trx_host_stb, rx_host_data);\n\ttxuartlite\t#(BUSUART) txv(s_clk, tx_host_stb, tx_host_data,\n\t\t\t\to_host_uart_tx, tx_host_busy);\n\n`ifdef\tINCLUDE_ZIPCPU\n\t// assign\twbu_zip_sel   = wbu_addr[@$.ZIP_ADDRESS_BIT];\n`else\n\tassign\twbu_zip_sel   = 1'b0;\n\tassign\tzip_dbg_ack   = 1'b0;\n\tassign\tzip_dbg_stall = 1'b0;\n\tassign\tzip_dbg_data  = 0;\n`endif\n`ifndef\tBUSPIC_ACCESS\n\twire\tw_bus_int;\n\tassign\tw_bus_int = 1'b0;\n`endif\n\twire\t[31:0]\twbu_tmp_addr;\n\twbubus\tgenbus(i_clk, i_host_rx_stb, i_host_rx_data,\n\t\t\t@$(BP)_cyc, @$(BP)_stb, @$(BP)_we, @$(PREFIX)_tmp_addr, @$(BP)_data,\n\t\t\t@$(BP)_stall, @$(BP)_ack, @$(BP)_idata, @$(BP)_err,\n\t\t\tw_bus_int,\n\t\t\to_host_tx_stb, o_host_tx_data, i_host_tx_busy,\n\t\t\twbubus_dbg[0]);\n\tassign\twbu_sel = 4'hf;\n\tassign\twbu_addr = wbu_tmp_addr[(@$BUS_ADDRESS_WIDTH-1):0];\n@REGDEFS.H.DEFNS=\n#define\tR_ZIPCTRL\t@$.ZIP_ADDRESS\n#define\tR_ZIPDATA\t@$.ZIP_DBGDATA\n#\nSIM.INIT=\n\t\tm_core->i_host_uart_rx = 1;\nSIM.CLOCK=clk\nSIM.TICK=\n\t\tm_core->i_host_uart_rx = (*m_dbgbus)(m_core->o_host_uart_tx);\n@RTL.MAKE.GROUP=\n@RTL.MAKE.SUBD=wbubus\n@RTL.MAKE.FILES= wbconsole.v wbubus.v wbucompactlines.v wbucompress.v\n\twbuconsole.v wbudecompress.v wbudeword.v wbuexec.v wbufifo.v\n\twbuidleint.v wbuinput.v wbuoutput.v wbureadcw.v wbusixchar.v wbutohex.v\n"
  },
  {
    "path": "auto-data/zipcpu.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/zipcpu.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tTo describe what needs to be done to make the ZipCPU a part\n##\t\tof a main .v file.  This Wishbone Master description\n##\tillustrates how some of how a wishbone bus master might be integrated\n##\tinto the automatic FPGA designer.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2015-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n##\n## Define @SYSPIC so that other peripherals needing to be on the ZipSystem's\n## PIC know the name of the PIC we are using.  Note that this is a global.\n## }}}\n@PREFIX=zip\n@SIM.CLOCK=clk\n@ACCESS=INCLUDE_ZIPCPU\n@DBGBUS=wbu\n@MASTER.TYPE=CPU\n@MASTER.BUS=wbwide\n@MASTER.BUS.OPT_DBLBUFFER=1'b0\n@SCOPE.TRIGGER=zip_trigger\n@SCOPE.DATA=zip_debug\n@CPURESET=i_cpu_reset\n@$RESET_ADDRESS=@$(flash.REGBASE)+(6<<20)\n@INT.ZIP.WIRE=zip_cpu_int\n@INT.ZIP.BUS=buspic\n@CACHABLE.FILE=iscachable.v\n@LGICACHE=12\n@LGDCACHE=12\n@TOP.PORTLIST=\n# \t\t// A reset wire for the ZipCPU\n# \t\ti_cpu_resetn\n@TOP.IODECL=\n#\t// A reset wire for the ZipCPU\n#\tinput\twire\t\ti_cpu_resetn;\n@TOP.DEFNS=\n\t// Verilator lint_off UNUSED\n\twire\t\tign_cpu_stall, ign_cpu_ack;\n\twire\t[31:0]\tign_cpu_idata;\n\t// Verilator lint_on  UNUSED\n@TOP.MAIN=\n\t\t// Simulation bus control for the CPU\n\t\t1'b0, 1'b0, 1'b0, 7'h0, 32'h0,\n\t\tign_cpu_stall, ign_cpu_ack, ign_cpu_idata,\n\t\t// Reset wire for the ZipCPU\n\t\ts_reset\n@MAIN.PORTLIST=\n\t\t// Veri1ator only interface\n\t\tcpu_sim_cyc,\n\t\tcpu_sim_stb,\n\t\tcpu_sim_we,\n\t\tcpu_sim_addr,\n\t\tcpu_sim_data,\n\t\tcpu_sim_stall,\n\t\tcpu_sim_ack,\n\t\tcpu_sim_idata,\n`ifdef\tVERILATOR\n\t\tcpu_prof_stb,\n\t\tcpu_prof_addr,\n\t\tcpu_prof_ticks,\n`endif\n\t\t@$(CPURESET)\n@MAIN.IODECL=\n\tinput\twire\t\tcpu_sim_cyc, cpu_sim_stb;\n\tinput\twire\t\tcpu_sim_we;\n\tinput\twire\t[6:0]\tcpu_sim_addr;\n\tinput\twire\t[31:0]\tcpu_sim_data;\n\t//\n\toutput\twire\t\tcpu_sim_stall, cpu_sim_ack;\n\toutput\twire\t[31:0]\tcpu_sim_idata;\n\t//\n`ifdef\tVERILATOR\n\toutput\twire\t\tcpu_prof_stb;\n\toutput\twire\t[@$(MASTER.BUS.AWID)+$clog2(@$(MASTER.BUS.WIDTH)/8)-1:0]\tcpu_prof_addr;\n\toutput\twire [31:0]\tcpu_prof_ticks;\n`endif\n\tinput\twire\t\t@$(CPURESET);\n@MAIN.PARAM=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// Variables/definitions/parameters used by the ZipCPU bus master\n\t// {{{\n\t//\n\t// A 32-bit address indicating where the ZipCPU should start running\n\t// from\n`ifdef\tBKROM_ACCESS\n\tlocalparam\tRESET_ADDRESS = @$(/bkrom.BASE);\n`else\n`ifdef\tFLASH_ACCESS\n\tlocalparam\tRESET_ADDRESS = @$(RESET_ADDRESS);\n`else\n\tlocalparam\tRESET_ADDRESS = @$(/bkram.BASE);\n`endif\t// FLASH_ACCESS\n`endif\t// BKROM_ACCESS\n\t//\n\t// The number of valid bits on the bus\n\tlocalparam\tZIP_ADDRESS_WIDTH = @$(MASTER.BUS.AWID); // Zip-CPU address width\n\t//\n\t// Number of ZipCPU interrupts\n\tlocalparam\tZIP_INTS = 16;\n\t//\n\t// ZIP_START_HALTED\n\t//\n\t// A boolean, indicating whether or not the ZipCPU be halted on startup?\n`ifdef\tBKROM_ACCESS\n\tlocalparam\tZIP_START_HALTED=1'b0;\n`else\n\tlocalparam\tZIP_START_HALTED=1'b1;\n`endif\n\t// }}}\n@MAIN.DEFNS=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// ZipSystem/ZipCPU connection definitions\n\t// {{{\n`ifndef\tVERILATOR\n\twire\t\tcpu_prof_stb;\n\twire\t[@$(MASTER.BUS.AWID)+$clog2(@$(MASTER.BUS.WIDTH)/8)-1:0]\tcpu_prof_addr;\n\twire [31:0]\tcpu_prof_ticks;\n`endif\n\t// All we define here is a set of scope wires\n\t// Verilator lint_off UNUSED\n\twire\t\traw_cpu_dbg_stall, raw_cpu_dbg_ack;\n\twire\t[31:0]\tzip_debug;\n\twire\t\tzip_trigger;\n\t// Verilator lint_on  UNUSED\n\twire\t[ZIP_INTS-1:0] zip_int_vector;\n\t// }}}\n@MAIN.INSERT=\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// The ZipCPU/ZipSystem BUS master\n\t// {{{\n\t//\n\tassign\tzip_int_vector = { alt_int_vector[14:8], sys_int_vector[14:6] };\n\tzipsystem #(\n\t\t// {{{\n\t\t.RESET_ADDRESS(RESET_ADDRESS),\n\t\t.ADDRESS_WIDTH(ZIP_ADDRESS_WIDTH + $clog2(@$(MASTER.BUS.WIDTH)/8)),\n\t\t.BUS_WIDTH(@$(MASTER.BUS.WIDTH)),\n\t\t.OPT_LGICACHE(@$(LGICACHE)),\n\t\t.OPT_LGDCACHE(@$(LGDCACHE)),\n\t\t.START_HALTED(ZIP_START_HALTED),\n\t\t.RESET_DURATION(20),\n\t\t.OPT_PIPELINED(1),\n`ifdef\tVERILATOR\n\t\t.OPT_PROFILER(1'b1),\n`else\n\t\t.OPT_PROFILER(1'b0),\n`endif\n`ifdef\tZIPSCOPE_SCOPE\n\t\t.OPT_TRACE_PORT(1'b1),\n`else\n\t\t.OPT_TRACE_PORT(1'b0),\n`endif\n\t\t.OPT_DISTRIBUTED_REGS(1),\n\t\t.EXTERNAL_INTERRUPTS(ZIP_INTS)\n\t\t// }}}\n\t) swic(\n\t\t// {{{\n\t\t.i_clk(i_clk), .i_reset(i_reset || @$(CPURESET)),\n\t\t\t// Zipsys wishbone interface\n\t\t\t@$(MASTER.ANSIPORTLIST),\n\t\t\t.i_ext_int(zip_int_vector), .o_ext_int(zip_cpu_int),\n\t\t\t// Debug wishbone interface\n\t\t\t.i_dbg_cyc(@$(SLAVE.PREFIX)_cyc || cpu_sim_cyc),\n\t\t\t.i_dbg_stb(cpu_sim_cyc ? cpu_sim_stb : @$(SLAVE.PREFIX)_stb),\n\t\t\t.i_dbg_we( cpu_sim_cyc ? cpu_sim_we  : @$(SLAVE.PREFIX)_we),\n\t\t\t.i_dbg_addr(cpu_sim_cyc? cpu_sim_addr : @$(SLAVE.PREFIX)_addr[6:0]),\n\t\t\t.i_dbg_data (cpu_sim_cyc? cpu_sim_data : @$(SLAVE.PREFIX)_data),\n\t\t\t.i_dbg_sel  (cpu_sim_cyc? 4'hf : @$(SLAVE.PREFIX)_sel),\n\t\t\t.o_dbg_stall(raw_cpu_dbg_stall),\n\t\t\t.o_dbg_ack  (raw_cpu_dbg_ack),\n\t\t\t.o_dbg_data (@$(SLAVE.PREFIX)_idata),\n\t\t\t//\n\t\t\t.o_cpu_debug(zip_debug),\n\t\t\t.o_prof_stb(cpu_prof_stb),\n\t\t\t.o_prof_addr(cpu_prof_addr),\n\t\t\t.o_prof_ticks(cpu_prof_ticks)\n\t\t// }}}\n\t);\n\tassign\tzip_trigger = zip_debug[31];\n\n\tassign\t@$(SLAVE.PREFIX)_stall =  cpu_sim_cyc || raw_cpu_dbg_stall;\n\tassign\t@$(SLAVE.PREFIX)_ack   = !cpu_sim_cyc && raw_cpu_dbg_ack;\n\tassign\tcpu_sim_stall = !cpu_sim_cyc || raw_cpu_dbg_stall;\n\tassign\tcpu_sim_ack   =  cpu_sim_cyc && raw_cpu_dbg_ack;\n\tassign\tcpu_sim_idata = @$(SLAVE.PREFIX)_idata;\n\n\t// Keep Verilator happy\n\t// {{{\n\t// Verilator lint_off UNUSED\n\twire\t@$(PREFIX)_unused;\n\tassign\t@$(PREFIX)_unused = &{ 1'b0,\n\t\t\talt_int_vector[7:0], sys_int_vector[5:0]};\n\t// Verilator lint_on  UNUSED\n\t// }}}\n\t// }}}\n@BDEF.INCLUDE=\n////////////////////////////////////////////////////////////////////////////////\n//\n// ZipCPU defines and macros\n// {{{\n#include <design.h>\n\n#define\t_HAVE_ZIPSYS\n#define\tPIC\t_zip->z_pic\n\n#ifdef\tINCLUDE_ZIPCPU\n#ifdef INCLUDE_DMA_CONTROLLER\n#define\t_HAVE_ZIPSYS_DMA\n#endif\t// INCLUDE_DMA_CONTROLLER\n#ifdef INCLUDE_ACCOUNTING_COUNTERS\n#define\t_HAVE_ZIPSYS_PERFORMANCE_COUNTERS\n#endif\t// INCLUDE_ACCOUNTING_COUNTERS\n#endif // INCLUDE_ZIPCPU\n// }}}\n@REGDEFS.H.INSERT=\n////////////////////////////////////////////////////////////////////////////////\n//\n// ZipCPU register definitions\n// {{{\n\n#define\tCPU_GO\t\t0x0000\n#define\tCPU_HALT\t0x0001\n#define\tCPU_STALL\t0x0002\n#define\tCPU_STEP\t0x0004\n#define\tCPU_RESET\t0x0008\n#define\tCPU_CLRCACHE\t0x0010\n// (Reserved)\t\t0x00e0\n#define\tCPU_SLEEPING\t0x0100\n#define\tCPU_GIE\t\t0x0200\n#define\tCPU_INT\t\t0x0400\n#define\tCPU_BREAK\t0x0800\n#define\tCPU_EXINT\t0xfffff000\n//\n#define\tCPU_sR0\t\t0x0020\n#define\tCPU_sSP\t\t0x002d\n#define\tCPU_sCC\t\t0x002e\n#define\tCPU_sPC\t\t0x002f\n#define\tCPU_uR0\t\t0x0030\n#define\tCPU_uSP\t\t0x003d\n#define\tCPU_uCC\t\t0x003e\n#define\tCPU_uPC\t\t0x003f\n\n#ifdef\tBKROM_ACCESS\n#define\tRESET_ADDRESS\t@$[0x%08x](bkrom.REGBASE)\n#else\n#ifdef\tFLASH_ACCESS\n#define\tRESET_ADDRESS\t@$[0x%08x](RESET_ADDRESS)\n#else\n#define\tRESET_ADDRESS\t@$[0x%08x](bkram.REGBASE)\n#endif\t// FLASH_ACCESS\n#endif\t// BKROM_ACCESS\n// }}}\n@SIM.CLOCK=clk\n@SIM.INCLUDE=\n#include \"zipelf.h\"\n\n@SIM.DEFINES=\n////////////////////////////////////////////////////////////////////////////////\n//\n// ZipCPU simulation defines\n// {{{\n#ifndef\tVVAR\n#ifdef\tROOT_VERILATOR\n\n#include \"Vmain___024root.h\"\n#define\tVVAR(A)\trootp->main__DOT_ ## A\n\n#elif\tdefined(NEW_VERILATOR)\n#define\tVVAR(A)\tmain__DOT_ ## A\n#else\n#define\tVVAR(A)\tv__DOT_ ## A\n#endif\n#endif\n\n#define\tOPT_PIPELINED\n#define\tCPUVAR(A)\tVVAR(_swic__DOT__thecpu__DOT__core__DOT_ ## A)\n\n#define\tcpu_break \tVVAR(_swic__DOT__cpu_break)\n// }}}\n@SIM.DEFNS=\n\tint\tm_cpu_bombed;\n@SIM.INIT=\n\t\tm_cpu_bombed = 0;\n@SIM.SETRESET=\n\t\tm_core->i_cpu_reset = 1;\n@SIM.CLRRESET=\n\t\tm_core->i_cpu_reset = 0;\n@SIM.METHODS=\n#ifdef\t@$(ACCESS)\n\t// ZipCPU Access functions\n\t// {{{\n\tvoid\tloadelf(const char *elfname) {\n\t\t// {{{\n\t\tELFSECTION\t**secpp, *secp;\n\t\tuint32_t\tentry;\n\n\t\telfread(elfname, entry, secpp);\n\n\t\tfor(int s=0; secpp[s]->m_len; s++) {\n\t\t\tbool\tsuccessful_load;\n\t\t\tsecp = secpp[s];\n\n\t\t\tsuccessful_load = load(secp->m_start,\n\t\t\t\tsecp->m_data, secp->m_len);\n\n\t\t\tif (!successful_load) {\n\t\t\t\tprintf(\"Could not load section \"\n\t\t\t\t\t\"from %08x to %08x--no such address\\n\",\n\t\t\t\t\tsecp->m_start,\n\t\t\t\t\tsecp->m_start+secp->m_len);\n\t\t\t}\n\t\t} free(secpp);\n\t}\n\t// }}}\n\n\tvoid\tcpu_dbg_write(const uint32_t addr, const uint32_t data) {\n\t\t// {{{\n\t\t// printf(\"CPU-DBG-WRITE(@0x%08x, 0x%08x);\\n\", addr, data);\n\t\tm_core->cpu_sim_cyc   = 1;\n\t\tm_core->cpu_sim_stb   = 1;\n\t\tm_core->cpu_sim_we    = 1;\n\t\tm_core->cpu_sim_addr  = addr >> 2;\n\t\tm_core->cpu_sim_data  = data;\n\n\t\tdo {\n\t\t\ttick_clk();\n\t\t} while(m_core->cpu_sim_stall);\n\n\t\tm_core->cpu_sim_stb = 0;\n\n\t\twhile(!m_core->cpu_sim_ack)\n\t\t\ttick_clk();\n\n\t\tm_core->cpu_sim_cyc  = 0;\n\t\tm_core->cpu_sim_we   = 0;\n\t\tm_core->cpu_sim_addr = 0;\n\t\tm_core->cpu_sim_data = 0;\n\n\t\ttick_clk();\n\t}\n\t// }}}\n\n\tuint32_t cpu_dbg_read(const uint32_t addr) {\n\t\t// {{{\n\t\tunsigned\tresult;\n\n\t\t// printf(\"CPU-DBG-WRITE(@0x%08x, 0x%08x);\\n\", addr, data);\n\t\tm_core->cpu_sim_cyc   = 1;\n\t\tm_core->cpu_sim_stb   = 1;\n\t\tm_core->cpu_sim_we    = 0;\n\t\tm_core->cpu_sim_addr  = addr >> 2;\n\t\tm_core->cpu_sim_data  = 0;\n\n\t\tdo {\n\t\t\ttick_clk();\n\t\t} while(m_core->cpu_sim_stall);\n\n\t\tm_core->cpu_sim_stb = 0;\n\n\t\twhile(!m_core->cpu_sim_ack)\n\t\t\ttick_clk();\n\n\t\tresult = m_core->cpu_sim_idata;\n\n\t\tm_core->cpu_sim_cyc  = 0;\n\t\tm_core->cpu_sim_we   = 0;\n\t\tm_core->cpu_sim_addr = 0;\n\t\tm_core->cpu_sim_data = 0;\n\n\t\ttick_clk();\n\n\t\treturn result;\n\t}\n\t// }}}\n\n\t// }}}\n#endif // @$(ACCESS)\n@SIM.TICK=\n#ifdef\t@$(ACCESS)\n\t\t// ZipCPU Sim instruction support\n\t\t// {{{\n\t\tif (m_cpu_bombed) {\n\t\t\tif (m_cpu_bombed++ > 12)\n\t\t\t\tm_done = true;\n\t\t} else if (m_core->cpu_break) {\n\t\t\tprintf(\"\\n\\nBOMB : CPU BREAK RECEIVED\\n\");\n\t\t\tm_cpu_bombed++;\n\t\t}\n\t\t// }}}\n#endif\t// @$(ACCESS)\n\n##\n##\n##\n@RTL.MAKE.GROUP=ZIPCPU\n@RTL.MAKE.FILES= zipsystem.v zipcore.v zipwb.v cpuops.v pfcache.v pipemem.v\n\t\tdblfetch.v pffifo.v pfcache.v idecode.v wbpriarbiter.v\n\t\tzipsystem.v zipcounter.v zipjiffies.v ziptimer.v icontrol.v\n\t\twbwatchdog.v busdelay.v\n\t\tzipdma_ctrl.v zipdma_fsm.v zipdma_mm2s.v zipdma_rxgears.v\n\t\tzipdma_s2mm.v zipdma_txgears.v zipdma.v\n@RTL.MAKE.SUBD=cpu\n##\n################################################################################\n##\n## ZipCPU debug port\n## {{{\n## (was once @PREFIX=zip_dbg)\n@SLAVE.TYPE=OTHER\n@SLAVE.BUS=wbu\n@SLAVE.ANSPREFIX=dbg_\n@SLAVE.ORDER=1000000\n@NADDR=128\n@REGS.N=52\n@REGS.NOTE=// ZipCPU control/debug registers\n@REGS.0=0   R_ZIPCTRL   CPU ZIPCTRL\n@REGS.1=32    R_ZIPREGS   ZIPREGS\n@REGS.2=32    R_ZIPS0     SR0\n@REGS.3=33    R_ZIPS1     SR1\n@REGS.4=34    R_ZIPS2     SR2\n@REGS.5=35    R_ZIPS3     SR3\n@REGS.6=36    R_ZIPS4     SR4\n@REGS.7=37    R_ZIPS5     SR5\n@REGS.8=38    R_ZIPS6     SR6\n@REGS.9=39    R_ZIPS7     SR7\n@REGS.10=40   R_ZIPS8     SR8\n@REGS.11=41   R_ZIPS9     SR9\n@REGS.12=42  R_ZIPS10    SR10\n@REGS.13=43  R_ZIPS11    SR11\n@REGS.14=44  R_ZIPS12    SR12\n@REGS.15=45  R_ZIPSSP    SSP SR13\n@REGS.16=46  R_ZIPCC     ZIPCC CC SCC SR14\n@REGS.17=47  R_ZIPPC     ZIPPC PC SPC SR15\n@REGS.18=48  R_ZIPUSER   ZIPUSER\n@REGS.19=48  R_ZIPU0     UR0\n@REGS.20=49  R_ZIPU1     UR1\n@REGS.21=50  R_ZIPU2     UR2\n@REGS.22=51  R_ZIPU3     UR3\n@REGS.23=52  R_ZIPU4     UR4\n@REGS.24=53  R_ZIPU5     UR5\n@REGS.25=54  R_ZIPU6     UR6\n@REGS.26=55  R_ZIPU7     UR7\n@REGS.27=56  R_ZIPU8     UR8\n@REGS.28=57  R_ZIPU9     UR9\n@REGS.29=58  R_ZIPU10    SR10\n@REGS.30=59  R_ZIPU11    SR11\n@REGS.31=60  R_ZIPU12    SR12\n@REGS.32=61  R_ZIPUSP    USP UR13\n@REGS.33=62  R_ZIPUCC    ZIPUCC UCC\n@REGS.34=63  R_ZIPUPC    ZIPUPC UPC\n@REGS.35=64  R_ZIPSYSTEM ZIPSYSTEM ZIPSYS\n@REGS.35=64  R_ZIPPIC    ZIPPIC CPUPIC\n@REGS.36=65  R_ZIPWATCHDOG ZIPWATCHDOG\n@REGS.37=66  R_ZIPBUSDOG  BUSDOG\n@REGS.38=67  R_ZIPAPIC    ZIPAPIC ALTPIC\n@REGS.39=68  R_ZIPTIMERA  ZIPTMA ZIPTIMERA\n@REGS.40=69  R_ZIPTIMERB  ZIPTMB ZIPTIMERB\n@REGS.41=70  R_ZIPTIMERC  ZIPTMC ZIPTIMERC\n@REGS.42=71  R_ZIPJIFFIES ZIPJIFF\n@REGS.43=72  R_ZIPMTASK   ZIPMTASK\n@REGS.44=73  R_ZIPMSTALL  ZIPMSTALL\n@REGS.45=74  R_ZIPMPSTAL  ZIPMPSTAL\n@REGS.46=75  R_ZIPMINSN   ZIPMINSN\n@REGS.47=76  R_ZIPUTASK   ZIPUTASK\n@REGS.48=77  R_ZIPUSTALL  ZIPUSTALL\n@REGS.49=78  R_ZIPUPSTAL  ZIPUPSTAL\n@REGS.50=79  R_ZIPUINSN   ZIPUINSN\n@REGS.51=80  R_ZIPUDMAC   ZIPDMAC\n##\n##\n## }}}\n"
  },
  {
    "path": "auto-data/zipmaster.txt",
    "content": "################################################################################\n##\n## Filename:\tauto-data/zipmaster.txt\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tTo describe what needs to be done to make the ZipCPU a part\n##\t\tof a main .v file.  This Wishbone Master description\n##\tillustrates how some of how a wishbone bus master might be integrated\n##\tinto the automatic FPGA designer.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n##\n## Define @SYSPIC so that other peripherals needing to be on the ZipSystem's\n## PIC know the name of the PIC we are using.  Note that this is a global.\n## }}}\n@SYSPIC= syspic\n@PREFIX=zip\n@INCLUDEFILE=zipcpu.txt\n@MASTER.BUS=wbwide\n################################################################################\n##\n## Interrupt definitions\n## {{{\n################################################################################\n@PREFIX=syspic\n@PIC.BUS= sys_int_vector\n@PIC.MAX=15\n@BDEF.DEFN=\n#define\tSYSPIC(A)\t(1<<(A))\n@PREFIX=zip_dmac\n@INT.DMAC.WIRE=\n@INT.DMAC.PIC= syspic\n@INT.DMAC.ID=0\n##\n####\n##\n@PREFIX=zip_jiffies\n@INT.JIFFIES.WIRE=\n@INT.JIFFIES.PIC= syspic\n@INT.JIFFIES.ID=1\n##\n####\n##\n@PREFIX=zip_tmc\n@INT.TMC.WIRE=\n@INT.TMC.PIC= syspic\n@INT.TMC.ID=2\n##\n####\n##\n@PREFIX=zip_tmb\n@INT.TMB.WIRE=\n@INT.TMB.PIC= syspic\n@INT.TMB.ID=3\n##\n####\n##\n@PREFIX=TMA\n@INT.TMA.WIRE=\n@INT.TMA.PIC= syspic\n@INT.TMA.ID=4\n##\n####\n##\n@PREFIX=alt\n@INT.ALT.WIRE=\n@INT.ALT.PIC= syspic\n@INT.ALT.ID=5\n##\n####\n##\n##\n@PREFIX=altpic\n@PIC.BUS= alt_int_vector\n@PIC.MAX=15\n@BDEF.DEFN=\n#define\tALTPIC(A)\t(1<<(A))\n#\n# @PIC.ASSIGNED= UIC UOC UPC UTC MIC MOC MPC MTC\n#\n@PREFIX=zip_alt_uic\n@INT.UIC.WIRE=\n@INT.UIC.PIC=altpic\n@INT.UIC.ID=0\n##\n@PREFIX=zip_alt_uoc\n@INT.UOC.WIRE=\n@INT.UOC.PIC=altpic\n@INT.UOC.ID=1\n##\n@PREFIX=zip_alt_upc\n@INT.UPC.WIRE=\n@INT.UPC.PIC=altpic\n@INT.UPC.ID=2\n##\n@PREFIX=zip_alt_utc\n@INT.UTC.WIRE=\n@INT.UTC.PIC=altpic\n@INT.UTC.ID=3\n##\n@PREFIX=zip_alt_mic\n@INT.MIC.WIRE=\n@INT.MIC.PIC=altpic\n@INT.MIC.ID=4\n##\n@PREFIX=zip_alt_moc\n@INT.MOC.WIRE=\n@INT.MOC.PIC=altpic\n@INT.MOC.ID=5\n##\n@PREFIX=zip_alt_mpc\n@INT.MPC.WIRE=\n@INT.MPC.PIC=altpic\n@INT.MPC.ID=6\n##\n@PREFIX=zip_alt_mtc\n@INT.MTC.WIRE=\n@INT.MTC.PIC=altpic\n@INT.MTC.ID=7\n##\n## }}}\n################################################################################\n"
  },
  {
    "path": "demo-out/board.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\t../demo-out/board.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Computer Generated: This file is computer generated by AUTOFPGA. DO NOT EDIT.\n// DO NOT EDIT THIS FILE!\n//\n// CmdLine:\t./autofpga -d -o ../demo-out -I ../auto-data allclocks.txt bkram.txt buserr.txt clkcheck.txt crossbus.txt ddr3.txt edidslvscope.txt edid.txt exconsole.txt flashcfg.txt flash.txt global.txt gpio.txt gps.txt hdmi.txt i2ccpu.txt i2cdma.txt i2saudio.txt icape.txt meganet.txt mdio.txt pic.txt pwrcount.txt rtcdate.txt rtcgps.txt spio.txt sdio.txt vadj33.txt version.txt wboledbw.txt wbpmic.txt wbuarbiter.txt wbubus.txt zipcpu.txt zipmaster.txt\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tBOARD_H\n#define\tBOARD_H\n\n// And, so that we can know what is and isn't defined\n// from within our main.v file, let's include:\n#include <design.h>\n\n#include <stdint.h>\n\n\n#ifndef\tUDP_DBGPORT\n#define\tUDP_DBGPORT\t6784\n#define\tUDP_DATAPORT\t6785\n#endif\n\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// ZipCPU defines and macros\n// {{{\n#include <design.h>\n\n#define\t_HAVE_ZIPSYS\n#define\tPIC\t_zip->z_pic\n\n#ifdef\tINCLUDE_ZIPCPU\n#ifdef INCLUDE_DMA_CONTROLLER\n#define\t_HAVE_ZIPSYS_DMA\n#endif\t// INCLUDE_DMA_CONTROLLER\n#ifdef INCLUDE_ACCOUNTING_COUNTERS\n#define\t_HAVE_ZIPSYS_PERFORMANCE_COUNTERS\n#endif\t// INCLUDE_ACCOUNTING_COUNTERS\n#endif // INCLUDE_ZIPCPU\n// }}}\n\n\n#define\tSYSPIC(A)\t(1<<(A))\n\n\n#define\tALTPIC(A)\t(1<<(A))\n\n\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// I2C CPU data structures\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t//\n#ifndef\tI2CCPU_H\n#define\tI2CCPU_H\n\n#define\tI2CC_WAITING\t0x00800000\t// True if waiting for synch signal\n#define\tI2CC_HALT\t0x00400000\t// Halt request\n#define\tI2CC_ABORT\t0x00200000\t// Abort\n#define\tI2CC_ERROR\t0x00100000\n#define\tI2CC_HARDHALT\t0x00080000\n#define\tI2CC_SCL\t0x00000200\n#define\tI2CC_SDA\t0x00000100\n#define I2CC_STOPPED\tI2CC_HARDHALT\n#define I2CC_FAULT\t(I2CC_ERROR | I2CC_ABORT)\n#define I2CC_CLEAR\t(I2CC_FAULT | I2CC_HALT)\n\n// For the manual port\n#define\tI2CC_MANSCL\t0x00008000\n#define\tI2CC_MANSDA\t0x00004000\n#define\tI2CC_MANUAL\t0x00000800\n#define\tI2CC_TVALID\t0x00000200\n#define\tI2CC_TLAST\t0x00000100\n\ntypedef\tstruct\tI2CCPU_S {\n\tvolatile unsigned\tic_control,\n\t\t\t\tic_override,\n\t\t\t\tic_address,\n\t\t\t\tic_clkcount;\n} I2CCPU;\n\n#endif\t// I2CCPU_H\n\t// }}}\n\n\n\n\n#ifndef\tWBUART_H\n#define\tWBUART_H\n\n#define UART_PARITY_NONE        0\n#define UART_HWFLOW_OFF         0x40000000\n#define UART_PARITY_ODD         0x04000000\n#define UART_PARITY_EVEN        0x05000000\n#define UART_PARITY_SPACE       0x06000000\n#define UART_PARITY_MARK        0x07000000\n#define UART_STOP_ONEBIT        0\n#define UART_STOP_TWOBITS       0x08000000\n#define UART_DATA_8BITS         0\n#define UART_DATA_7BITS         0x10000000\n#define UART_DATA_6BITS         0x20000000\n#define UART_DATA_5BITS         0x30000000\n#define UART_RX_BREAK           0x0800\n#define UART_RX_FRAMEERR        0x0400\n#define UART_RX_PARITYERR       0x0200\n#define UART_RX_NOTREADY        0x0100\n#define UART_RX_ERR             (-256)\n#define UART_TX_BUSY            0x0100\n#define UART_TX_BREAK           0x0200\n\ntypedef struct  WBUART_S {\n\tunsigned\tu_setup;\n\tunsigned\tu_fifo;\n\tunsigned\tu_rx, u_tx;\n} WBUART;\n\n#endif\t// WBUART_H\n\n\n\n#ifndef VIDPIPE_H\n#define VIDPIPE_H\n\n#define\tVIDPIPE_RESET\t0x000001\n#define\tVIDPIPE_RXPLLCK\t0x000002\n#define\tVIDPIPE_LOCALCK\t0x000000\n#define\tVIDPIPE_RXCLOCK\t0x000020\n#define\tVIDPIPE_LCLSRC\t0x000000\n#define\tVIDPIPE_RXSRC\t0x000040\n#define\tVIDPIPE_RXSYNCD\t0x010000\n#define\tVIDPIPE_OVLYERR\t0x020000\n\n#define\tVIDCMAP_BW\t0x000000\n#define\tVIDCMAP_2GRAY\t0x000100\n#define\tVIDCMAP_4CMAP\t0x000200\n#define\tVIDCMAP_8CMAP\t0x000300\n#define\tVIDCMAP_8CLR\t0x000400\n#define\tVIDCMAP_16CLR\t0x000500\n#define\tVIDCMAP_24CLR\t0x000600\n#define\tVIDCMAP_32CLR\t0x000700\n\ntypedef struct __attribute__((packed)) VIDMODE_S {\n\tuint16_t\tm_height,     m_width;\n\tuint16_t\tm_vporch,     m_hporch;\n\tuint16_t\tm_vsync,      m_hsync;\n\tuint16_t\tm_raw_height, m_raw_width;\n} VIDMODE;\n\ntypedef struct __attribute__((packed)) VIDPIPE_S {\n\tuint32_t\tv_control, v_hdmifreq, v_sifreq, v_pxfreq;\n\tVIDMODE\t\tv_in, v_src;\n\tconst char\t*v_overlay;\n\tuint16_t\tv_ovheight, v_ovwidth;\n\tuint16_t\tv_ovypos,  v_ovhpos;\n\tunsigned\tv_fps;\n\tuint32_t\tv_capture;\n\tconst char\t*v_capbase;\n\tuint32_t\tv_capwords, v_capposn, v_capsize;\n\tunsigned\tv_ovwords;\n\tunsigned\tv_unused2[2];\n\tunsigned\tv_syncword;\n\tuint32_t\tv_unused[512-25];\n\tuint32_t\tv_clrmap[256];\n} VIDPIPE;\n\n#endif // VIDPIPE_H\n\n\n#ifndef\tWBSCOPE_H\n#define\tWBSCOPE_H\n\n#define\tWBSCOPE_NO_RESET\t0x80000000u\n#define\tWBSCOPE_STOPPED\t\t0x40000000u\n#define\tWBSCOPE_TRIGGERED\t0x20000000u\n#define\tWBSCOPE_PRIMED\t\t0x10000000u\n#define\tWBSCOPE_TRIGGER\t\t(WBSCOPE_NO_RESET|0x08000000u)\n#define\tWBSCOPE_MANUAL\t\t(WBSCOPE_TRIGGER)\n#define\tWBSCOPE_DISABLE\t\t0x04000000u\n\ntypedef\tstruct\tWBSCOPE_S {\n\tvolatile unsigned s_ctrl, s_data;\n} WBSCOPE;\n#endif\n\n\n// Offsets for the ICAPE2 interface\n#define\tCFG_CRC\t\t0\n#define\tCFG_FAR\t\t1\n#define\tCFG_FDRI\t2\n#define\tCFG_FDRO\t3\n#define\tCFG_CMD\t\t4\n#define\tCFG_CTL0\t5\n#define\tCFG_MASK\t6\n#define\tCFG_STAT\t7\n#define\tCFG_LOUT\t8\n#define\tCFG_COR0\t9\n#define\tCFG_MFWR\t10\n#define\tCFG_CBC\t\t11\n#define\tCFG_IDCODE\t12\n#define\tCFG_AXSS\t13\n#define\tCFG_COR1\t14\n#define\tCFG_WBSTAR\t16\n#define\tCFG_TIMER\t17\n#define\tCFG_BOOTSTS\t22\n#define\tCFG_CTL1\t24\n#define\tCFG_BSPI\t31\n\n\n\n\ntypedef\tstruct\tDDR3_PHY_S {\n\tunsigned\tph_something;\n} DDR3_PHY;\n\n\n\n#ifndef\tI2CDMA_H\n#define\tI2CDMA_H\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// I2C DMA data structures\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t//\n\ntypedef struct  I2CDMA_S        {\n\tunsigned\tid_control, id_current, id_base, id_memlen;\n} I2CDMA;\n\n#endif\t// I2CDMA_H\n\t// }}}\n\n\ntypedef\tstruct\tGPSTB_S\t{\n\tunsigned\ttb_maxcount, tb_jump;\n\tunsigned long\ttb_err, tb_count, tb_step;\n} GPSTB;\n\n\n// Network stream/packet interface\n// {{{\n#ifndef\tENETSTREAM_H\n#define\tENETSTREAM_H\ntypedef struct ENETSTREAM_S {\n        unsigned        n_rxcmd, n_txcmd;\n        unsigned long   n_mac;\n\tunsigned\tn_ipaddr;\n        unsigned        n_rxmiss, n_rxerr, n_rxcrc;\n\t//\n\tunsigned\tn_rxpkt, n_rxarp, n_rxicmp;\n\tunsigned\tn_txpkt, n_txarp, n_txicmp;\n\tunsigned\tn_data, n_aborts;\n\tunsigned\tn_rxdbg, n_txdbg;\n} ENETSTREAM;\n#endif\n// }}}\n\n\ntypedef\tstruct\tRTCLIGHT_S\t{\n\tunsigned\tr_clock, r_stopwatch, r_timer, r_alarm;\n} RTCLIGHT;\n\n\n#define\tSPIO_BTNC\t0x01000\n#define\tSPIO_BTND\t0x00800\n#define\tSPIO_BTNL\t0x00400\n#define\tSPIO_BTNR\t0x00200\n#define\tSPIO_BTNU\t0x00100\n\n\n//\n// GPIO input wires\n//\n#define\tGPIO_HDMIRX_CEC\t\t0x000010000\n#define\tGPIO_HDMITX_CEC\t\t0x000020000\n#define\tGPIO_SD_DETECTED\t0x000080000\n#define\tGPIO_HDMITX_DETECT\t0x000100000\n#define\tGPIO_GPS_3DF\t\t0x000200000\n#define\tGPIO_SYSCLK_LOCKED\t0x000400000\n#define\tGPIO_VIDCLK_LOCKED\t0x000800000\n//\n// GPIO output wires\n//\n#define\tGPIO_SET(WIRE)\t(((WIRE)<<16)|(WIRE))\n#define\tGPIO_CLR(WIRE)\t ((WIRE)<<16)\n//\n#define\tGPIO_HDMIRX_CEC_SET\t0x000010001\n#define\tGPIO_HDMIRX_CEC_CLR\t0x000010000\n#define\tGPIO_HDMITX_CEC_SET\t0x000020002\n#define\tGPIO_HDMITX_CEC_CLR\t0x000020000\n//\n#define\tGPIO_HDMIRX_TXEN\t0x000000004\n#define\tGPIO_HDMIRX_HPA\t\t0x000000008\n#define\tGPIO_SD_RESET\t\t0x000000010\n#define\tGPIO_OLED_RESET\t\t0x000000020\n#define\tGPIO_OLED_PANELEN\t0x000000040\n#define\tGPIO_OLED_LOGICEN\t0x000000080\n#define\tGPIO_TRACE\t\t0x000000100\n#define\tGPIO_TESTHALT\t\t0x000000200\n//\n#define\tGPIO_EDID_SCL_SET\tGPIO_SET(GPIO_EDID_SCL)\n#define\tGPIO_EDID_SCL_CLR\tGPIO_CLR(GPIO_EDID_SCL)\n#define\tGPIO_EDID_SDA_SET\tGPIO_SET(GPIO_EDID_SDA)\n#define\tGPIO_EDID_SDA_CLR\tGPIO_CLR(GPIO_EDID_SDA)\n#define\tGPIO_HDMIRX_HPA_SET\tGPIO_SET(GPIO_HDMIRX_HPA)\n#define\tGPIO_HDMIRX_HPA_CLR\tGPIO_CLR(GPIO_HDMIRX_HPA)\n#define\tGPIO_SD_RESET_SET\tGPIO_SET(GPIO_SD_RESET)\n#define\tGPIO_SD_RESET_CLR\tGPIO_CLR(GPIO_SD_RESET)\n#define\tGPIO_HDMIRX_TXEN_SET\tGPIO_SET(GPIO_HDMIRX_TXEN)\n#define\tGPIO_HDMIRX_TXEN_CLR\tGPIO_CLR(GPIO_HDMIRX_TXEN)\n#define\tOLED_RESET\t\tGPIO_SET(GPIO_OLED_RESET)\n#define\tOLED_RUN\t\tGPIO_CLR(GPIO_OLED_RESET)\n#define\tOLED_PANELEN\t\tGPIO_SET(GPIO_OLED_PANELEN)\n#define\tOLED_PANELDIS\t\tGPIO_CLR(GPIO_OLED_PANELEN)\n#define\tOLED_LOGICEN\t\tGPIO_SET(GPIO_OLED_LOGICEN)\n#define\tOLED_LOGICDIS\t\tGPIO_CLR(GPIO_OLED_LOGICEN)\n#define\tGPIO_TRACE_SET\t\tGPIO_SET(GPIO_TRACE)\n#define\tGPIO_TRACE_CLR\t\tGPIO_CLR(GPIO_TRACE)\n#define\tGPIO_HALT_SET\t\tGPIO_SET(GPIO_TESTHALT)\n#define\tGPIO_HALT_CLR\t\tGPIO_CLR(GPIO_TESTHALT)\n\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// SDIO SD Card constants\n// {{{\n////////////////////////////////////////////////////////////////////////////////\n//\n//\n\n// These will be defined in sdiodrv.h for the SDIO controller\nstruct SDIO_S;\n// }}}\n\n\n#define BUSPIC(X) (1<<X)\n\n\ntypedef\tstruct\tGPSTRACKER_S\t{\n\tunsigned\tg_alpha, g_beta, g_gamma, g_step;\n} GPSTRACKER;\n\n\n//\n// The Ethernet MDIO interface\n//\n#define MDIO_BMCR\t0x00\n#define MDIO_BMSR\t0x01\n#define MDIO_PHYIDR1\t0x02\t// PHY ID Register #1\n#define MDIO_PHYIDR2\t0x03\t// PHY ID Register #2\n#define MDIO_ANAR\t0x04\t// Autonegotiation advertisement\n#define MDIO_ANLPAR\t0x05\t// Autonegotiation link partner ability\n#define MDIO_ANER\t0x06\t// Autonegotiation expansion\n#define MDIO_ANNPTR\t0x07\t// Autonegotiation next page\n#define MDIO_ANNPRR\t0x08\t// Autonegotiation link partner next page\n#define MDIO_GBCR\t0x09\t// 1GBase-T Control\n#define MDIO_GBSR\t0x0a\t// 1GBase-T Status\n#define MDIO_MACR\t0x0d\t// MMD Access control\n#define MDIO_MAADR\t0x0e\t// MMD Access register/data\n#define MDIO_GBESR\t0x0f\n#define MDIO_PHYCR\t0x10\n#define MDIO_PHYSR\t0x11\n#define MDIO_INER\t0x12\n#define MDIO_INSR\t0x13\n#define MDIO_LDPSR\t0x1b\n#define MDIO_EPAGSR\t0x1e\n#define MDIO_PAGSEL\t0x1f\n\n#define XMDIO_PC1R\t0x00\n#define XMDIO_PS1R\t0x01\n#define XMDIO_EEECR\t0x14\n#define XMDIO_EEEWER\t0x10\n// #define XMDIO_EEEAR\t0x\n// #define XMDIO_EEELPAR\t0x18\n#define XMDIO_LACR\t0x1a\n#define XMDIO_LCR\t0x1c\n// #define XMDIO_ACCR\t0x1b\n\ntypedef struct ENETMDIO_S {\n\tunsigned\te_v[32][32];\n} ENETMDIO;\n\n\n\ntypedef\tstruct OLEDBW_S {\n\tunsigned\to_cmd, o_override, o_addr, o_clk;\n} OLEDBW;\n\n\n\n#define WBMIC_ENABLE\t0\n#define WBMIC_DISABLE\t(1<<20)\n#define WBMIC_NONEMPTY\t0\n#define WBMIC_HALFINT\t(1<<22)\n#define WBMIC_RESET\t(1<<24)\n\ntypedef struct  WBMIC_S {\n\tunsigned\tm_data;\n\tunsigned\tm_setup;\n} WBMIC;\n\n\n#ifdef\tFLASH_ACCESS\n#define\t_BOARD_HAS_FLASH\nextern int _flash[1];\n#endif\t// FLASH_ACCESS\n#ifdef\tI2CCPU_ACCESS\n#define\t_BOARD_HAS_I2CCPU\nstatic volatile I2CCPU *const _i2c=((I2CCPU *)0x08001420);\n#endif\t// I2CCPU_ACCESS\n#define\t_BOARD_HAS_BUSERR\nstatic volatile unsigned *const _buserr = ((unsigned *)0x08001488);\n#define\t_BOARD_HAS_SUBSECONDS\nstatic volatile unsigned *const _subseconds = ((unsigned *)0x080014a4);\n#ifdef\tADCCLK\nstatic volatile unsigned *const _adcclk = ((unsigned *)0x08001480);\n#endif\t// ADCCLK\n#ifdef\tFLASHCFG_ACCESS\n#define\t_BOARD_HAS_FLASHCFG\nstatic volatile unsigned * const _flashcfg = ((unsigned *)(0x08000400));\n#endif\t// FLASHCFG_ACCESS\n#ifdef\tEDID_ACCESS\n#define\t_BOARD_HAS_EDID\nstatic volatile I2CCPU *const _edid = ((I2CCPU *)0x08001400);\n#endif\t// EDID_ACCESS\n#ifdef\tGPSUART_ACCESS\n#define\t_BOARD_HAS_GPS_UART\nstatic volatile WBUART *const _gpsu = ((WBUART *)(0x08000a00));\n#endif\t// GPSUART_ACCESS\n#ifdef\tVIDPIPE_ACCESS\n#define\t_BOARD_HAS_VIDPIPE\nstatic volatile VIDPIPE *const _hdmi = ((VIDPIPE *)0x08002000);\n#endif\t// VIDPIPE_ACCESS\nstatic volatile char *const _edidslv = ((char *)0x08001500);\n#ifdef\tEDIDSLVSCOPE_SCOPC\n#define\t_BOARD_HAS_EDIDSLVSCOPE\nstatic volatile WBSCOPE *const _edidslvscope = ((WBSCOPE *)0x08000600);\n#endif\t// EDIDSLVSCOPE_SCOPC\n#ifdef\tCFG_ACCESS\n#define\t_BOARD_HAS_ICAPETWO\nstatic volatile unsigned *const _icape = ((unsigned *)0x08000c00);\n#endif\t// CFG_ACCESS\n#ifdef\tTXCLK\nstatic volatile unsigned *const _txclk = ((unsigned *)0x080014a8);\n#endif\t// TXCLK\n#ifdef\tRXETH0CK\nstatic volatile unsigned *const _rxeth0ck = ((unsigned *)0x0800149c);\n#endif\t// RXETH0CK\n#ifdef\tBKRAM_ACCESS\n#define\t_BOARD_HAS_BKRAM\nextern char\t_bkram[0x00100000];\n#endif\t// BKRAM_ACCESS\n#ifdef\tSDRAM_ACCESS\n#define\t_BOARD_HAS_SDRAM\nextern char\t_ddr3[0x40000000];\n#endif\t// SDRAM_ACCESS\n#ifdef\tDDR3_PHY_ACCESS\n#define\t_BOARD_HAS_DDR3_PHY\nstatic volatile DDR3_PHY *const _ddr3_phy = ((DDR3_PHY *)0x08001000);\n#endif\t// DDR3_PHY_ACCESS\n#ifdef\tI2CDMA_ACCESS\n#define\t_BOARD_HAS_I2CDMA\nstatic volatile I2CDMA *const _i2cdma=((I2CDMA *)0x08001430);\n#endif\t// I2CDMA_ACCESS\n#ifdef\tPWRCOUNT_ACCESS\nstatic volatile unsigned *const _pwrcount = ((unsigned *)0x08001494);\n#endif\t// PWRCOUNT_ACCESS\nstatic volatile GPSTB *const _gpstb = ((GPSTB *)0x08001460);\n#define\t_BOARD_HAS_PXPLL\nstatic volatile unsigned *const _pxclk=((unsigned *)0x08001200);\n#ifdef\tMEGANET_ACCESS\n#define\t_BOARD_HAS_MEGANET\nstatic volatile ENETSTREAM *const _net = ((ENETSTREAM *)0x08000e00);\n#endif\t// MEGANET_ACCESS\n#ifdef\tRTCDATE_ACCESS\n#define\t_BOARD_HAS_RTCDATE\nstatic volatile unsigned *const _rtcdate = ((unsigned *)134223000);\n#endif\t// RTCDATE_ACCESS\n#ifdef\tRTC_ACCESS\n#define\t_BOARD_HAS_RTC\nstatic volatile RTCLIGHT *const _rtc = ((RTCLIGHT *)0x08001450);\n#endif\t// RTC_ACCESS\n#ifdef\tSPIO_ACCESS\n#define\t_BOARD_HAS_SPIO\nstatic volatile unsigned *const _spio = ((unsigned *)0x080014a0);\n#endif\t// SPIO_ACCESS\n#ifdef\tGPIO_ACCESS\n#define\t_BOARD_HAS_GPIO\nstatic volatile unsigned *const _gpio = ((unsigned *)0x08001490);\n#endif\t// GPIO_ACCESS\n#ifdef\tSDIO_ACCESS\n#define\t_BOARD_HAS_SDIO\nstatic volatile struct SDIO_S *const _sdio = ((struct SDIO_S *)0x00800000);\n#endif\t// SDIO_ACCESS\n#ifdef\tBUSPIC_ACCESS\n#define\t_BOARD_HAS_BUSPIC\nstatic volatile unsigned *const _buspic = ((unsigned *)0x0800148c);\n#endif\t// BUSPIC_ACCESS\n#ifdef\tGPSTRK_ACCESS\nstatic volatile GPSTRACKER *const _gps = ((GPSTRACKER *)0x08001410);\n#endif\t// GPSTRK_ACCESS\n#ifdef\tNETCTRL_ACCESS\n#define\t_BOARD_HAS_NETMDIO\nstatic volatile ENETMDIO *const _mdio = ((ENETMDIO *)0x08003000);\n#endif\t// NETCTRL_ACCESS\n#define\t_BOARD_HAS_BUILDTIME\nstatic volatile unsigned *const _buildtime = ((unsigned *)0x08001484);\n#ifdef\tVERSION_ACCESS\n#define\t_BOARD_HAS_VERSION\nstatic volatile unsigned *const _version = ((unsigned *)0x080014ac);\n#endif\t// VERSION_ACCESS\n#ifdef\tOLEDBW_ACCESS\n#define\t_BOARD_HAS_OLEDBW\nstatic volatile OLEDBW *const _oled = ((OLEDBW *)134222912);\n#endif\t// OLEDBW_ACCESS\n#ifdef\tMICROPHONE_ACCESS\n#define\t_BOARD_HAS_WBMIC\nstatic volatile WBMIC *const _wbmic = ((WBMIC *)134219776);\n#endif\t// MICROPHONE_ACCESS\n//\n// Interrupt assignments (3 PICs)\n//\n// PIC: syspic\n#define\tSYSPIC_DMAC\tSYSPIC(0)\n#define\tSYSPIC_JIFFIES\tSYSPIC(1)\n#define\tSYSPIC_TMC\tSYSPIC(2)\n#define\tSYSPIC_TMB\tSYSPIC(3)\n#define\tSYSPIC_TMA\tSYSPIC(4)\n#define\tSYSPIC_ALT\tSYSPIC(5)\n#define\tSYSPIC_BUS\tSYSPIC(6)\n#define\tSYSPIC_I2C\tSYSPIC(7)\n#define\tSYSPIC_EDID\tSYSPIC(8)\n#define\tSYSPIC_VIDFRAME\tSYSPIC(9)\n#define\tSYSPIC_GPIO\tSYSPIC(10)\n#define\tSYSPIC_SDCARD\tSYSPIC(11)\n#define\tSYSPIC_PPS\tSYSPIC(12)\n#define\tSYSPIC_OLED\tSYSPIC(13)\n#define\tSYSPIC_MIC\tSYSPIC(14)\n// PIC: altpic\n#define\tALTPIC_UIC\tALTPIC(0)\n#define\tALTPIC_UOC\tALTPIC(1)\n#define\tALTPIC_UPC\tALTPIC(2)\n#define\tALTPIC_UTC\tALTPIC(3)\n#define\tALTPIC_MIC\tALTPIC(4)\n#define\tALTPIC_MOC\tALTPIC(5)\n#define\tALTPIC_MPC\tALTPIC(6)\n#define\tALTPIC_MTC\tALTPIC(7)\n#define\tALTPIC_GPSRX\tALTPIC(8)\n#define\tALTPIC_GPSTX\tALTPIC(9)\n#define\tALTPIC_GPSRXF\tALTPIC(10)\n#define\tALTPIC_GPSTXF\tALTPIC(11)\n#define\tALTPIC_EDIDSLVSCOPE\tALTPIC(12)\n#define\tALTPIC_RTC\tALTPIC(13)\n// PIC: buspic\n#define\tBUSPIC_SPIO\tBUSPIC(0)\n#define\tSYSINT_GPSRXF\tALTINT(@$(INT.GPSRXF.syspic.ID))\n#define\tSYSINT_GPSTXF\tALTINT(11)\n#define\tSYSINT_GPSRX\tALTINT(8)\n#define\tSYSINT_GPSTX\tALTINT(9)\n\n\n#define\tSYSINT_PPS\tSYSINT(12)\n\n\n#endif\t// BOARD_H\n"
  },
  {
    "path": "demo-out/board.ld",
    "content": "/*******************************************************************************\n*\n* Filename:\t../demo-out/board.ld\n*\n* Project:\tVideoZip, a ZipCPU SoC supporting video functionality\n*\n* DO NOT EDIT THIS FILE!\n* Computer Generated: This file is computer generated by AUTOFPGA. DO NOT EDIT.\n* DO NOT EDIT THIS FILE!\n*\n* CmdLine:\t./autofpga ./autofpga -o ../demo-out -I ../auto-data global.txt clock.txt bkram.txt flash.txt zipmaster.txt wbubus.txt dlyarbiter.txt gps.txt icape.txt mdio.txt spio.txt wboledbw.txt rtcdate.txt hdmi.txt clkcounter.txt gpio.txt pwrcount.txt wbpmic.txt version.txt buserr.txt pic.txt rtcgps.txt wbmouse.txt sdspi.txt\n*\n* Creator:\tDan Gisselquist, Ph.D.\n*\t\tGisselquist Technology, LLC\n*\n/*******************************************************************************\n*\n* Copyright (C) 2017-2018, Gisselquist Technology, LLC\n*\n* This program is free software (firmware): you can redistribute it and/or\n* modify it under the terms of  the GNU General Public License as published\n* by the Free Software Foundation, either version 3 of the License, or (at\n* your option) any later version.\n*\n* This program is distributed in the hope that it will be useful, but WITHOUT\n* ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n* for more details.\n*\n* You should have received a copy of the GNU General Public License along\n* with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n* target there if the PDF file isn't present.)  If not, see\n* <http://www.gnu.org/licenses/> for a copy.\n*\n* License:\tGPL, v3, as defined and found on www.gnu.org,\n*\t\thttp://www.gnu.org/licenses/gpl.html\n*\n*\n/*******************************************************************************\n*\n*\n*/\nENTRY(_start)\n\nMEMORY\n{\n\t/* To be listed here, a slave must be of type MEMORY.  If the slave\n\t* has a defined name in its @LD.NAME tag, it will be listed here\n\t* under that name.  The permissions are given by the @LD.PERM tag.\n\t* If no permission tag exists, a permission of 'r' will be assumed.\n\t*/\n\t   bkram(wx) : ORIGIN = 0x00c00000, LENGTH = 0x00100000\n\t   flash(rx) : ORIGIN = 0x01000000, LENGTH = 0x01000000\n}\n\n/* For each defined memory peripheral, we also define a pointer to that\n* memory.  The name of this pointer is given by the @LD.NAME tag within\n* the memory peripheral's configuration\n*/\n_bkram    = ORIGIN(bkram);\n_flash    = ORIGIN(flash);\n\nSECTIONS\n{\n\t.rocode 32'h01400000 : ALIGN(4) {\n\t\t_boot_address = .;\n\t\t*(.start) *(.boot)\n\t} > flash\n\n\t_kernel_image_start = . ;\n\t_kernel_image_end = . ;\n\t_ram_image_start = . ;\n\t.ramcode : ALIGN_WITH_INPUT {\n\t\t*(.kernel)\n\t\t*(.text.startup)\n\t\t*(.text)\n\t\t*(.rodata) *(.strings)\n\t\t*(.data) *(COMMON)\n\t\t}> bkram AT> flash\n\t_ram_image_end = . ;\n\t.bss : ALIGN_WITH_INPUT {\n\t\t*(.bss)\n\t\t_bss_image_end = . ;\n\t\t}> bkram\n\t_top_of_heap = .;\n}\n\n\n"
  },
  {
    "path": "demo-out/build.xdc",
    "content": ""
  },
  {
    "path": "demo-out/iscachable.v",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\t../demo-out/iscachable.v\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Computer Generated: This file is computer generated by AUTOFPGA. DO NOT EDIT.\n// DO NOT EDIT THIS FILE!\n//\n// CmdLine:\t./autofpga -d -o ../demo-out -I ../auto-data allclocks.txt bkram.txt buserr.txt clkcheck.txt crossbus.txt ddr3.txt edidslvscope.txt edid.txt exconsole.txt flashcfg.txt flash.txt global.txt gpio.txt gps.txt hdmi.txt i2ccpu.txt i2cdma.txt i2saudio.txt icape.txt meganet.txt mdio.txt pic.txt pwrcount.txt rtcdate.txt rtcgps.txt spio.txt sdio.txt vadj33.txt version.txt wboledbw.txt wbpmic.txt wbuarbiter.txt wbubus.txt zipcpu.txt zipmaster.txt\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n`default_nettype none\n//\nmodule iscachable(\n\t\t// {{{\n\t\tinput\twire\t[31-1:0]\ti_addr,\n\t\toutput\treg\t\t\to_cachable\n\t\t// }}}\n\t);\n\n\talways @(*)\n\tbegin\n\t\to_cachable = 1'b0;\n\t\t// Bus master: wbwide\n\t\t// Bus master: wbflash\n\t\t// flash\n\t\tif ((i_addr[30:0] & 31'h79000000) == 31'h01000000)\n\t\t\to_cachable = 1'b1;\n\t\t// Bus master: wb32\n\t\t// Bus master: wb32_dio\n\t\t// Bus master: wb32_sio\n\t\t// bkram\n\t\tif ((i_addr[30:0] & 31'h78000000) == 31'h10000000)\n\t\t\to_cachable = 1'b1;\n\t\t// ddr3\n\t\tif ((i_addr[30:0] & 31'h40000000) == 31'h40000000)\n\t\t\to_cachable = 1'b1;\n\tend\n\nendmodule\n"
  },
  {
    "path": "demo-out/main.v",
    "content": "`timescale\t1ps / 1ps\n////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\t../demo-out/main.v\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Computer Generated: This file is computer generated by AUTOFPGA. DO NOT EDIT.\n// DO NOT EDIT THIS FILE!\n//\n// CmdLine:\t./autofpga -d -o ../demo-out -I ../auto-data allclocks.txt bkram.txt buserr.txt clkcheck.txt crossbus.txt ddr3.txt edidslvscope.txt edid.txt exconsole.txt flashcfg.txt flash.txt global.txt gpio.txt gps.txt hdmi.txt i2ccpu.txt i2cdma.txt i2saudio.txt icape.txt meganet.txt mdio.txt pic.txt pwrcount.txt rtcdate.txt rtcgps.txt spio.txt sdio.txt vadj33.txt version.txt wboledbw.txt wbpmic.txt wbuarbiter.txt wbubus.txt zipcpu.txt zipmaster.txt\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n`default_nettype\tnone\n////////////////////////////////////////////////////////////////////////////////\n//\n// Macro defines\n// {{{\n//\n//\n// Here is a list of defines which may be used, post auto-design\n// (not post-build), to turn particular peripherals (and bus masters)\n// on and off.  In particular, to turn off support for a particular\n// design component, just comment out its respective `define below.\n//\n// These lines are taken from the respective @ACCESS tags for each of our\n// components.  If a component doesn't have an @ACCESS tag, it will not\n// be listed here.\n//\n// First, the independent access fields for any bus masters\n`define\tEXBUS_MASTER\n`define\tALLCLOCKS_PRESENT\n`define\tVADJ_ACCESS\n// And then for the independent peripherals\n`define\tFLASH_ACCESS\n`define\tI2CCPU_ACCESS\n`define\tEDID_ACCESS\n`define\tGPSUART_ACCESS\n`define\tVIDPIPE_ACCESS\n`define\tEDIDSLVSCOPE_SCOPC\n`define\tCFG_ACCESS\n`define\tBKRAM_ACCESS\n`define\tSDRAM_ACCESS\n`define\tDDR3_PHY_ACCESS\n`define\tI2CDMA_ACCESS\n`define\tPWRCOUNT_ACCESS\n`define\tMEGANET_ACCESS\n`define\tRTC_ACCESS\n`define\tSPIO_ACCESS\n`define\tGPIO_ACCESS\n`define\tSDIO_ACCESS\n`define\tBUSPIC_ACCESS\n`define\tGPSTRK_ACCESS\n`define\tNETCTRL_ACCESS\n`define\tVERSION_ACCESS\n`define\tOLEDBW_ACCESS\n`define\tMICROPHONE_ACCESS\n`define\tINCLUDE_ZIPCPU\n//\n//\n// The list of those things that have @DEPENDS tags\n//\n//\n//\n// Dependencies\n// Any core with both an @ACCESS and a @DEPENDS tag will show up here.\n// The @DEPENDS tag will turn into a series of ifdef's, with the @ACCESS\n// being defined only if all of the ifdef's are true//\n// Deplist for @$(PREFIX)=rtcdate\n`ifdef\tRTC_ACCESS\n`define\tRTCDATE_ACCESS\n`endif\t// RTC_ACCESS\n// Deplist for @$(PREFIX)=flashcfg\n`ifdef\tFLASH_ACCESS\n`define\tFLASHCFG_ACCESS\n`endif\t// FLASH_ACCESS\n// Deplist for @$(PREFIX)=txclk\n`ifdef\tALLCLOCKS_PRESENT\n`define\tTXCLK\n`endif\t// ALLCLOCKS_PRESENT\n// Deplist for @$(PREFIX)=adcclk\n`ifdef\tALLCLOCKS_PRESENT\n`define\tADCCLK\n`endif\t// ALLCLOCKS_PRESENT\n// Deplist for @$(PREFIX)=i2saudio\n// Deplist for @$(PREFIX)=rxeth0ck\n`ifdef\tMEGANET_ACCESS\n`define\tRXETH0CK\n`endif\t// MEGANET_ACCESS\n// Deplist for @$(PREFIX)=i2saudio\n//\n// The following macros have unmet dependencies.  They are listed\n// here for reference, but their dependencies cannot be met.\n// Unmet Dependency list for @$(PREFIX)=i2saudio\n`ifdef\tARBITRARY_CLOCK_GENERATOR_ACCESS // This value is unknown\n`define\tI2SAUDIO\n`endif\n\n//\n// End of dependency list\n//\n//\n// }}}\n////////////////////////////////////////////////////////////////////////////////\n//\n// Any include files\n// {{{\n// These are drawn from anything with a MAIN.INCLUDE definition.\n`include \"builddate.v\"\n// }}}\n//\n// Finally, we define our main module itself.  We start with the list of\n// I/O ports, or wires, passed into (or out of) the main function.\n//\n// These fields are copied verbatim from the respective I/O port lists,\n// from the fields given by @MAIN.PORTLIST\n//\nmodule\tmain(i_clk, i_reset,\n\t// {{{\n\t\t// The Universal QSPI Flash\n\t\to_flash_cs_n, o_flash_sck, o_flash_dat, i_flash_dat, o_flash_mod,\n\t\t\ti_i2c_sda, i_i2c_scl,\n\t\t\to_i2c_sda, o_i2c_scl,\n\t\t// UART/host to wishbone interface\n\t\ti_wbu_uart_rx, o_wbu_uart_tx,\n\t\t\ti_edid_sda, i_edid_scl,\n\t\t\to_edid_sda, o_edid_scl,\n\t\t// The GPS-UART\n\t\ti_gpsu_rx, o_gpsu_tx,\n\t\t// HDMI control ports\n`ifndef\tVERILATOR\n\t\ti_hdmiclk,\n`endif\n\t\ti_pixclk,\n\t\ti_hdmi_red, i_hdmi_grn, i_hdmi_blu,\n\t\to_hdmi_red, o_hdmi_grn, o_hdmi_blu,\n\t\to_hdmi_iodelay, i_hdmi_iodelay,\n\t\to_pix_reset_n, i_pxpll_locked, o_hdmirx_reset_n,\n\t\to_pxclk_cksel,\n\t\t// EDID RX definitions\n\t\ti_edidslv_scl, i_edidslv_sda,\n\t\to_edidslv_scl, o_edidslv_sda,\n\t\t// DDR3 Controller Interface\n\t\ti_ddr3_iserdes_data, i_ddr3_iserdes_dqs,\n\t\ti_ddr3_iserdes_bitslip_reference,\n\t\ti_ddr3_idelayctrl_rdy,\n\t\to_ddr3_cmd,\n\t\to_ddr3_dqs_tri_control, o_ddr3_dq_tri_control,\n\t\to_ddr3_toggle_dqs, o_ddr3_data, o_ddr3_dm,\n\t\to_ddr3_odelay_data_cntvaluein, o_ddr3_odelay_dqs_cntvaluein,\n\t\to_ddr3_idelay_data_cntvaluein, o_ddr3_idelay_dqs_cntvaluein,\n\t\to_ddr3_odelay_data_ld, o_ddr3_odelay_dqs_ld,\n\t\to_ddr3_idelay_data_ld, o_ddr3_idelay_dqs_ld,\n\t\to_ddr3_bitslip,\n\t\to_ddr3_leveling_calib,\n\t\to_ddr3_reset,\n\t\to_i2s_lrclk, o_i2s_bclk, o_i2s_mclk, o_i2s_dac, i_i2s_adc,\n\t\to_pxclk_cyc, o_pxclk_stb, o_pxclk_we,\n\t\to_pxclk_addr, o_pxclk_data, o_pxclk_sel,\n\t\ti_pxclk_stall, i_pxclk_ack, i_pxclk_idata,\n                // Ethernet control (packets) lines\n                o_net_reset_n,\n                // eth_int_b    // Interrupt, leave floating\n                // eth_pme_b    // Power management event, leave floating\n                i_net_rx_clk, i_net_rx_dv, i_net_rx_err, i_net_rxd,\n                o_net_tx_clk, o_net_tx_ctl, o_net_txd,\n\t\t// SPIO interface\n\t\ti_sw, i_btnc, i_btnd, i_btnl, i_btnr, i_btnu, o_led,\n\t\t// GPIO ports\n`ifdef\tVERILATOR\n\t\to_trace, o_halt,\n`endif\n\t\ti_gpio, o_gpio,\n\t\t// SDIO SD Card\n\t\ti_sdio_detect,\n\t\t//\n\t\to_sdio_cfg_ddr,\n\t\to_sdio_cfg_ds,\n\t\to_sdio_cfg_dscmd,\n\t\to_sdio_cfg_sample_shift,\n\t\to_sdio_cmd_tristate,\n\t\to_sdio_data_tristate,\n\t\t//\n\t\to_sdio_sdclk,\n\t\to_sdio_cmd_en,\n\t\to_sdio_cmd_data,\n\t\to_sdio_data_en,\n\t\to_sdio_rx_en,\n\t\to_sdio_tx_data,\n\t\t//\n\t\ti_sdio_cmd_strb,\n\t\ti_sdio_cmd_data,\n\t\ti_sdio_cmd_collision,\n\t\ti_sdio_crcack,\n\t\ti_sdio_crcnak,\n\t\ti_sdio_card_busy,\n\t\ti_sdio_rx_strb,\n\t\ti_sdio_rx_data,\n\t\t//\n\t\ti_sdio_ac_valid,\n\t\ti_sdio_ac_data,\n\t\ti_sdio_ad_valid,\n\t\ti_sdio_ad_data,\n\t\to_sdio_hwreset_n, o_sdio_1p8v,\n\t\ti_sdio_debug,\n\t\t// Extra clocks\n\t\ti_clk_125mhz,\n\t\t// The GPS 1PPS signal port\n\t\ti_gps_pps,\n\t\t// The ethernet MDIO wires\n\t\to_mdclk, o_mdio, o_mdwe, i_mdio,\n\t\t// OLED control interface (roughly SPI)\n\t\to_oled_sck, o_oled_mosi, o_oled_dcn,\n\t\t// The PMic3 microphone wires\n\t\to_mic_csn, o_mic_sck, i_mic_din,\n\t\t// Veri1ator only interface\n\t\tcpu_sim_cyc,\n\t\tcpu_sim_stb,\n\t\tcpu_sim_we,\n\t\tcpu_sim_addr,\n\t\tcpu_sim_data,\n\t\tcpu_sim_stall,\n\t\tcpu_sim_ack,\n\t\tcpu_sim_idata,\n`ifdef\tVERILATOR\n\t\tcpu_prof_stb,\n\t\tcpu_prof_addr,\n\t\tcpu_prof_ticks,\n`endif\n\t\ti_cpu_reset\n\t// }}}\n\t);\n////////////////////////////////////////////////////////////////////////////////\n//\n// Any parameter definitions\n// {{{\n// These are drawn from anything with a MAIN.PARAM definition.\n// As they aren't connected to the toplevel at all, it would\n// be best to use localparam over parameter, but here we don't\n// check\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// EXBUS parameters\n\t// {{{\n\t// Baudrate :   1000000\n\t// Clock    : 100000000\n\tlocalparam [23:0] BUSUART = 24'h64;\t//   1000000 baud\n\tlocalparam\tDBGBUSBITS = $clog2(BUSUART);\n\t// }}}\n\tlocalparam\tICAPE_LGDIV=3;\n\tlocalparam real SDRAMCONTROLLER_CLK_PERIOD = 10_000,  //ps, clock period of the controller interface\n\t\tDDR3_CLK_PERIOD = 2_500; //ps, clock period of the DDR3 RAM device (must be 1/4 of the CONTROLLER_CLK_PERIOD) \n\tlocalparam SDRAMROW_BITS = 14,  // width of row address\n\t\tSDRAMCOL_BITS = 10,  // width of column address\n\t\tSDRAMBA_BITS  =  3,  // width of bank address\n\t\tSDRAMDQ_BITS  =  8,  // Size of one octet\n\t\tSDRAMBYTE_LANES = 2, //8 lanes of DQ\n\t\tSDRAMAUX_WIDTH = 4, //width of aux line (must be >= 4) \n\t\tSDRAMSERDES_RATIO = $rtoi(SDRAMCONTROLLER_CLK_PERIOD/DDR3_CLK_PERIOD),\n\t\t//4 is the width of a single ddr3 command {cs_n, ras_n, cas_n, we_n} plus 3 (ck_en, odt, reset_n) plus bank bits plus row bits\n\t\tSDRAMCMD_LEN = 4 + 3 + SDRAMBA_BITS + SDRAMROW_BITS;\n\n\n\tparameter\t[15:0]\tUDP_DBGPORT  = 6784;\n\n\tlocalparam\t[47:0]\tDEF_HWMAC  = 48'h82_33_48_02_e1_c8;\n\tlocalparam\t[31:0]\tDEF_IPADDR = { 8'd192, 8'd168, 8'd15, 8'd29 };\n\tlocalparam [31:0] GPSCLOCK_DEFAULT_STEP = 32'haabcc771;\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// Variables/definitions/parameters used by the ZipCPU bus master\n\t// {{{\n\t//\n\t// A 32-bit address indicating where the ZipCPU should start running\n\t// from\n`ifdef\tBKROM_ACCESS\n\tlocalparam\tRESET_ADDRESS = @$(/bkrom.BASE);\n`else\n`ifdef\tFLASH_ACCESS\n\tlocalparam\tRESET_ADDRESS = 23068672;\n`else\n\tlocalparam\tRESET_ADDRESS = 268435456;\n`endif\t// FLASH_ACCESS\n`endif\t// BKROM_ACCESS\n\t//\n\t// The number of valid bits on the bus\n\tlocalparam\tZIP_ADDRESS_WIDTH = 27; // Zip-CPU address width\n\t//\n\t// Number of ZipCPU interrupts\n\tlocalparam\tZIP_INTS = 16;\n\t//\n\t// ZIP_START_HALTED\n\t//\n\t// A boolean, indicating whether or not the ZipCPU be halted on startup?\n`ifdef\tBKROM_ACCESS\n\tlocalparam\tZIP_START_HALTED=1'b0;\n`else\n\tlocalparam\tZIP_START_HALTED=1'b1;\n`endif\n\t// }}}\n// }}}\n////////////////////////////////////////////////////////////////////////////////\n//\n// Port declarations\n// {{{\n// The next step is to declare all of the various ports that were just\n// listed above.\n//\n// The following declarations are taken from the values of the various\n// @MAIN.IODECL keys.\n//\n\tinput\twire\t\ti_clk;\n\t// verilator lint_off UNUSED\n\tinput\twire\t\ti_reset;\n\t// verilator lint_on UNUSED\n\t// The Universal QSPI flash\n\toutput\twire\t\to_flash_cs_n, o_flash_sck;\n\toutput\twire\t[3:0]\to_flash_dat;\n\tinput\twire\t[3:0]\ti_flash_dat;\n\toutput\twire\t[1:0]\to_flash_mod;\n\t// I2C Port declarations\n\t// {{{\n\tinput\twire\ti_i2c_sda, i_i2c_scl;\n\toutput\twire\to_i2c_sda, o_i2c_scl;\n\t// }}}\n\tinput\twire\t\ti_wbu_uart_rx;\n\toutput\twire\t\to_wbu_uart_tx;\n\t// I2C Port declarations\n\t// {{{\n\tinput\twire\ti_edid_sda, i_edid_scl;\n\toutput\twire\to_edid_sda, o_edid_scl;\n\t// }}}\n\tinput\twire\t\ti_gpsu_rx;\n\toutput\twire\t\to_gpsu_tx;\n\t// hdmi declarations\n\t// {{{\n`ifndef\tVERILATOR\n\tinput\twire\t\ti_hdmiclk;\n`endif\n\tinput\twire\t\ti_pixclk;\n\tinput\twire\t[9:0]\ti_hdmi_red, i_hdmi_grn, i_hdmi_blu;\n\toutput\twire\t[9:0]\to_hdmi_red, o_hdmi_grn, o_hdmi_blu;\n\toutput\twire\t[14:0]\to_hdmi_iodelay;\n\tinput\twire\t[14:0]\ti_hdmi_iodelay;\n\toutput\twire\t\to_pix_reset_n, o_hdmirx_reset_n;\n\tinput\twire\t\ti_pxpll_locked;\n\toutput\twire\t[1:0]\to_pxclk_cksel;\n\t// }}}\n\t// EDID RX definitions\n\tinput\twire\ti_edidslv_scl, i_edidslv_sda;\n\toutput\twire\to_edidslv_scl, o_edidslv_sda;\n\t// DDR3 Controller I/O declarations\n\t// {{{\n\tinput\twire\t[SDRAMDQ_BITS*SDRAMBYTE_LANES*8-1:0] i_ddr3_iserdes_data;\n\tinput wire    [SDRAMBYTE_LANES*8-1:0] i_ddr3_iserdes_dqs;\n\tinput wire    [SDRAMBYTE_LANES*8-1:0] i_ddr3_iserdes_bitslip_reference;\n\tinput wire    i_ddr3_idelayctrl_rdy;\n\toutput wire    [SDRAMCMD_LEN*SDRAMSERDES_RATIO-1:0] o_ddr3_cmd;\n\toutput wire    o_ddr3_dqs_tri_control, o_ddr3_dq_tri_control;\n\toutput wire    o_ddr3_toggle_dqs;\n\toutput wire    [SDRAMDQ_BITS*SDRAMBYTE_LANES*8-1:0] o_ddr3_data;\n\toutput wire    [(SDRAMDQ_BITS*SDRAMBYTE_LANES*8)/8-1:0] o_ddr3_dm;\n\toutput wire    [4:0] o_ddr3_odelay_data_cntvaluein, o_ddr3_odelay_dqs_cntvaluein;\n\toutput wire    [4:0] o_ddr3_idelay_data_cntvaluein, o_ddr3_idelay_dqs_cntvaluein;\n\toutput wire    [SDRAMBYTE_LANES-1:0] o_ddr3_odelay_data_ld, o_ddr3_odelay_dqs_ld;\n\toutput wire    [SDRAMBYTE_LANES-1:0] o_ddr3_idelay_data_ld, o_ddr3_idelay_dqs_ld;\n\toutput wire    [SDRAMBYTE_LANES-1:0] o_ddr3_bitslip;\n\toutput wire    o_ddr3_leveling_calib;\n\toutput wire    o_ddr3_reset;\n\t// }}}\n\toutput\twire\to_i2s_lrclk, o_i2s_bclk, o_i2s_mclk, o_i2s_dac;\n\tinput\twire\ti_i2s_adc;\n\toutput\twire\to_pxclk_cyc, o_pxclk_stb, o_pxclk_we;\n\toutput\twire\t[6:0]\to_pxclk_addr;\n\toutput\twire\t[31:0]\to_pxclk_data;\n\toutput\twire\t[3:0]\to_pxclk_sel;\n\tinput\twire\t\ti_pxclk_stall, i_pxclk_ack;\n\tinput\twire\t[31:0]\ti_pxclk_idata;\n        // Ethernet (RGMII) control\n\t// {{{\n\t// Verilator lint_off SYNCASYNCNET\n        output  wire            o_net_reset_n;\n\t// Verilator lint_on  SYNCASYNCNET\n        input   wire            i_net_rx_clk, i_net_rx_dv, i_net_rx_err;\n        input   wire    [7:0]   i_net_rxd;\n        output  wire    [1:0]   o_net_tx_clk;\n        output  wire            o_net_tx_ctl;\n        output  wire    [7:0]   o_net_txd;\n\t// }}}\n\t// SPIO interface\n\tinput\twire\t[8-1:0]\ti_sw;\n\tinput\twire\t\ti_btnc, i_btnd, i_btnl, i_btnr, i_btnu;\n\toutput\twire\t[8-1:0]\to_led;\n\tlocalparam\tNGPI = 8, NGPO=10;\n\t// GPIO ports\n`ifdef\tVERILATOR\n\toutput\twire\t\t\to_trace;\n\toutput\twire\t\t\to_halt;\n`endif\n\tinput\t\t[(NGPI-1):0]\ti_gpio;\n\toutput\twire\t[(NGPO-1):0]\to_gpio;\n\t// SDIO SD Card declarations\n\t// {{{\n\tinput\twire\t\ti_sdio_detect;\n\t\t//\n\toutput\twire\t\to_sdio_cfg_ddr;\n\toutput\twire\t\to_sdio_cfg_ds;\n\toutput\twire\t\to_sdio_cfg_dscmd;\n\toutput\twire\t[4:0]\to_sdio_cfg_sample_shift;\n\toutput\twire\t\to_sdio_cmd_tristate;\n\toutput\twire\t\to_sdio_data_tristate;\n\t\t//\n\toutput\twire\t[7:0]\to_sdio_sdclk;\n\toutput\twire\t\to_sdio_cmd_en;\n\toutput\twire\t[1:0]\to_sdio_cmd_data;\n\toutput\twire\t\to_sdio_data_en;\n\toutput\twire\t\to_sdio_rx_en;\n\toutput\twire\t[31:0]\to_sdio_tx_data;\n\t\t//\n\tinput\twire\t[1:0]\ti_sdio_cmd_strb;\n\tinput\twire\t[1:0]\ti_sdio_cmd_data;\n\tinput\twire\t\ti_sdio_cmd_collision;\n\tinput\twire\t\ti_sdio_crcack;\n\tinput\twire\t\ti_sdio_crcnak;\n\tinput\twire\t\ti_sdio_card_busy;\n\tinput\twire\t[1:0]\ti_sdio_rx_strb;\n\tinput\twire\t[15:0]\ti_sdio_rx_data;\n\t\t//\n\tinput\twire\t\ti_sdio_ac_valid;\n\tinput\twire\t[1:0]\ti_sdio_ac_data;\n\tinput\twire\t\ti_sdio_ad_valid;\n\tinput\twire\t[31:0]\ti_sdio_ad_data;\n\toutput\twire\t\to_sdio_hwreset_n,\n\t\t\t\to_sdio_1p8v;\n\t// Verilator lint_off UNUSED\n\tinput\twire\t[31:0]\ti_sdio_debug;\n\t// Verilator lint_on  UNUSED\n\t// }}}\n\t// Extra clocks\n\t// Verilator lint_off UNUSED\n\tinput\twire\t\ti_clk_125mhz;\n\t// Verilator lint_on  UNUSED\n\t//The GPS Clock\n\tinput\twire\t\ti_gps_pps;\n\t// Ethernet control (MDIO)\n\toutput\twire\t\to_mdclk, o_mdio, o_mdwe;\n\tinput\twire\t\ti_mdio;\n\t// OLEDBW interface\n\toutput\twire\t\to_oled_sck, o_oled_mosi, o_oled_dcn;\n\toutput\twire\t\to_mic_csn, o_mic_sck;\n\tinput\twire\t\ti_mic_din;\n\tinput\twire\t\tcpu_sim_cyc, cpu_sim_stb;\n\tinput\twire\t\tcpu_sim_we;\n\tinput\twire\t[6:0]\tcpu_sim_addr;\n\tinput\twire\t[31:0]\tcpu_sim_data;\n\t//\n\toutput\twire\t\tcpu_sim_stall, cpu_sim_ack;\n\toutput\twire\t[31:0]\tcpu_sim_idata;\n\t//\n`ifdef\tVERILATOR\n\toutput\twire\t\tcpu_prof_stb;\n\toutput\twire\t[27+$clog2(128/8)-1:0]\tcpu_prof_addr;\n\toutput\twire [31:0]\tcpu_prof_ticks;\n`endif\n\tinput\twire\t\ti_cpu_reset;\n// }}}\n\t// Make Verilator happy\n\t// {{{\n\t// Defining bus wires for lots of components often ends up with unused\n\t// wires lying around.  We'll turn off Ver1lator's lint warning\n\t// here that checks for unused wires.\n\t// }}}\n\t// verilator lint_off UNUSED\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// Declaring interrupt lines\n\t// {{{\n\t// These declarations come from the various components values\n\t// given under the @INT.<interrupt name>.WIRE key.\n\t//\n\twire\ti2c_int;\t// i2c.INT.I2C.WIRE\n\twire\tedid_int;\t// edid.INT.EDID.WIRE\n\twire\tgpsurxf_int;\t// gpsu.INT.GPSRXF.WIRE\n\twire\tgpsutxf_int;\t// gpsu.INT.GPSTXF.WIRE\n\twire\tgpsutx_int;\t// gpsu.INT.GPSTX.WIRE\n\twire\tgpsurx_int;\t// gpsu.INT.GPSRX.WIRE\n\twire\thdmi_int;\t// hdmi.INT.VIDFRAME.WIRE\n\twire\tedidslvscope_int;\t// edidslvscope.INT.EDIDSLVSCOPE.WIRE\n\twire\trtc_int;\t// rtc.INT.RTC.WIRE\n\twire\tspio_int;\t// spio.INT.SPIO.WIRE\n\twire\tgpio_int;\t// gpio.INT.GPIO.WIRE\n\twire\tsdio_int;\t// sdio.INT.SDCARD.WIRE\n\twire\tw_bus_int;\t// buspic.INT.BUS.WIRE\n\twire\tgck_pps;\t// gck.INT.PPS.WIRE\n\twire\toled_int;\t// oled.INT.OLED.WIRE\n\twire\tpmic_int;\t// pmic.INT.MIC.WIRE\n\twire\tzip_cpu_int;\t// zip.INT.ZIP.WIRE\n\t// }}}\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// Component declarations\n\t// {{{\n\t// These declarations come from the @MAIN.DEFNS keys found in the\n\t// various components comprising the design.\n\t//\n\t// Definitions for the flash debug port\n\t// Verilator lint_off UNUSED\n\twire\t\tflash_dbg_trigger;\n\twire\t[31:0]\tflash_debug;\n\t// Verilator lint_on  UNUSED\n\t// I2C Controller\n\t// {{{\n\t// Verilator lint_off UNUSED\n\tlocalparam\tI2CCPU_WIDTH=(2 == 0) ? 1 : 2;\n\n\twire\t\ti2c_valid, i2c_ready, i2c_last;\n\twire\t[7:0]\ti2c_data;\n\twire\t[I2CCPU_WIDTH-1:0]\ti2c_id;\n\n\twire\t[31:0]\ti2c_debug;\n\t// Verilator lint_on  UNUSED\n\t// }}}\n\treg\t[30-1:0]\tr_buserr_addr;\n`ifndef\tGPSTRK_ACCESS\n\treg\t[31:0]\tr_subseconds_data;\n`endif\n\treg\tr_adcclk_ack;\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// EXBUS: USB-UART interface declarations\n\t// {{{\n\t//\n\twire\t[7:0]\twbu_rx_data, wbu_tx_data;\n\twire\t\twbu_rx_stb;\n\twire\t\twbu_tx_stb, wbu_tx_busy;\n\n\t// Verilator lint_off UNUSED\n\twire\t[0:0]\tex_reset;\n\twire\t[1:0]\tex_gpio;\n\t// Verilator lint_on  UNUSED\n\t// }}}\n\t// I2C Controller\n\t// {{{\n\t// Verilator lint_off UNUSED\n\tlocalparam\tEDID_WIDTH=(2 == 0) ? 1 : 2;\n\n\twire\t\tedid_valid, edid_ready, edid_last;\n\twire\t[7:0]\tedid_data;\n\twire\t[EDID_WIDTH-1:0]\tedid_id;\n\n\twire\t[31:0]\tedid_debug;\n\t// Verilator lint_on  UNUSED\n\t// }}}\n\twire\tw_gpsu_cts_n, w_gpsu_rts_n;\n\tassign\tw_gpsu_cts_n=1'b1;\n\t// Verilator lint_off UNUSED\n`ifdef\tVERILATOR\n\twire\t\ti_hdmiclk;\n`endif\n\twire\t\thdmidbg_ce, hdmidbg_trigger;\n\twire\t[31:0]\thdmiclr_debug;\n\t// Verilator lint_on  UNUSED\n\t// Verilator lint_off UNUSED\n\twire\t[31:0]\tedidslv_dbg;\n\t// Verilator lint_on  UNUSED\n\treg\tr_txclk_ack;\n\treg\tr_rxeth0ck_ack;\n\t// Verilator lint_off UNUSED\n\treg\t\trtc_pps;\n\treg\t[26:0]\trtc_pps_counter;\n\t// Verilator lint_on  UNUSED\n\t// Verilator lint_off UNUSED\n\twire\t[SDRAMAUX_WIDTH-1:0]\tddr3_aux_out;\n\twire\t[31:0]\tddr3_debug;\n\t// Verilator lint_on  UNUSED\n\twire\ti2cdma_ready;\n\treg\t[31:0]\tr_pwrcount_data;\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// I2S Audio signal definitions\n\t// {{{\n\twire\t\tw_i2saudio_en;\n\t// Verilator lint_off UNUSED\n\t//\n\t// These wires may or may not be connected to anything ...\n\twire\t\tw_audio_out_valid, w_audio_out_ready, w_audio_out_last;\n\twire\t[23:0]\tw_audio_out_data;\n\t//\n\t// w_audio_in... comes from the microphone (if present)\n\twire\t\tw_audio_in_valid, w_audio_in_ready,\n\t\t\tw_audio_in_last;\n\twire\t[23:0]\tw_audio_in_data;\n\n\twire\t[31:0]\tw_i2saudio_debug;\n\t// Verilator lint_on  UNUSED\n\t// }}}\n\twire\ttb_pps;\n        // Ethernet (RGMII) control\n\t// {{{\n\t// Verilator lint_off UNUSED\n\twire\t[47:0]\tnet_hwmac, net_last_ping_hwmac;\n\twire\t[31:0]\tnet_ip_addr, net_last_ping_ipaddr;\n\n\twire\t\tnetcpurx_valid, netcpurx_ready;\n\twire\t[31:0]\tnetcpurx_data;\n\twire\t[1:0]\tnetcpurx_bytes;\n\twire\t\tnetcpurx_last, netcpurx_abort;\n\n\twire\t\tnetcputx_valid, netcputx_ready,\n\t\t\tnetcputx_last, netcputx_abort;\n\twire\t[31:0]\tnetcputx_data;\n\twire\t[1:0]\tnetcputx_bytes;\n\n\twire\t\tnet_dbg_valid, net_dbg_ready,\n\t\t\tnet_dbg_last;\n\twire\t[31:0]\tnet_dbg_data;\n\twire\t[1:0]\tnet_dbg_bytes;\n\n\twire\t\tnet_high_speed;\n\n\twire\t\tnet_debug_clk;\n\twire\t[31:0]\tnet_debug;\n\twire\t\tign_rxpkt_net_ready;\n\n\t// Verilator lint_on  UNUSED\n\t// }}}\n\t// Definitions in support of the GPS driven RTC\n\t// This clock step is designed to match 100000000 Hz\n\tlocalparam\t[31:0]\tRTC_CLKSTEP = 32'h002af31d;\n\twire\trtc_ppd;\n\twire\trtc_pps;\n\twire\t[5-1:0]\tw_btn;\n\twire\t[8-1:0]\tw_led;\n\twire\tsd_reset;\n\t// SDIO SD Card definitions\n\t// Verilator lint_off UNUSED\n\twire\t[31:0]\tw_sdio_sdwb_debug;\n\twire\t\ts_sdio_ready,\n\t\t\tm_sdio_valid, m_sdio_last;\n\treg\t[31:0]\tsdio_debug;\n\twire\t[31:0]\tm_sdio_data;\n\t// assign\t\tsdio_debug = i_sdio_debug;\n\t// Verilator lint_on  UNUSED\n\twire\ti_net_tx_clk;\n\twire\t\tck_pps;\n\twire\t\tgps_pps, gps_led, gps_locked, gps_tracking;\n\twire\t[63:0]\tgps_now, gps_err, gps_step;\n\twire\t[1:0]\tgps_dbg_tick;\n\t// Verilator lint_off UNUSED\n\twire[31:0]\tmdio_debug;\n\t// Verilator lint_on  UNUSED\n// BUILDTIME doesnt need to include builddate.v a second time\n// `include \"builddate.v\"\n\t// OLEDBW\n\t// {{{\n\t// Verilator lint_off UNUSED\n\twire\t[1:0]\tw_oled_csn;\n\twire\t\tign_oled_valid, ign_oled_last,\n\t\t\tign_oled_id;\n\twire\t[7:0]\tign_oled_data;\n\twire\t[31:0]\toled_debug;\n\t// Verilator lint_on  UNUSED\n\t// }}}\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// ZipSystem/ZipCPU connection definitions\n\t// {{{\n`ifndef\tVERILATOR\n\twire\t\tcpu_prof_stb;\n\twire\t[27+$clog2(128/8)-1:0]\tcpu_prof_addr;\n\twire [31:0]\tcpu_prof_ticks;\n`endif\n\t// All we define here is a set of scope wires\n\t// Verilator lint_off UNUSED\n\twire\t\traw_cpu_dbg_stall, raw_cpu_dbg_ack;\n\twire\t[31:0]\tzip_debug;\n\twire\t\tzip_trigger;\n\t// Verilator lint_on  UNUSED\n\twire\t[ZIP_INTS-1:0] zip_int_vector;\n\t// }}}\n\n// }}}\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// Declaring interrupt vector wires\n\t// {{{\n\t// These declarations come from the various components having\n\t// PIC and PIC.MAX keys.\n\t//\n\twire\t[14:0]\tsys_int_vector;\n\twire\t[14:0]\talt_int_vector;\n\twire\t[14:0]\tbus_int_vector;\n\t// }}}\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// Declare bus signals\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\n\t// Bus wbwide\n\t// {{{\n\t// Wishbone definitions for bus wbwide, component i2c\n\t// Verilator lint_off UNUSED\n\twire\t\twbwide_i2cm_cyc, wbwide_i2cm_stb, wbwide_i2cm_we;\n\twire\t[26:0]\twbwide_i2cm_addr;\n\twire\t[127:0]\twbwide_i2cm_data;\n\twire\t[15:0]\twbwide_i2cm_sel;\n\twire\t\twbwide_i2cm_stall, wbwide_i2cm_ack, wbwide_i2cm_err;\n\twire\t[127:0]\twbwide_i2cm_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wbwide, component edid\n\t// Verilator lint_off UNUSED\n\twire\t\twbwide_edidm_cyc, wbwide_edidm_stb, wbwide_edidm_we;\n\twire\t[26:0]\twbwide_edidm_addr;\n\twire\t[127:0]\twbwide_edidm_data;\n\twire\t[15:0]\twbwide_edidm_sel;\n\twire\t\twbwide_edidm_stall, wbwide_edidm_ack, wbwide_edidm_err;\n\twire\t[127:0]\twbwide_edidm_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wbwide, component hdmi\n\t// Verilator lint_off UNUSED\n\twire\t\twbwide_hdmi_cyc, wbwide_hdmi_stb, wbwide_hdmi_we;\n\twire\t[26:0]\twbwide_hdmi_addr;\n\twire\t[127:0]\twbwide_hdmi_data;\n\twire\t[15:0]\twbwide_hdmi_sel;\n\twire\t\twbwide_hdmi_stall, wbwide_hdmi_ack, wbwide_hdmi_err;\n\twire\t[127:0]\twbwide_hdmi_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wbwide, component i2cdma\n\t// Verilator lint_off UNUSED\n\twire\t\twbwide_i2cdma_cyc, wbwide_i2cdma_stb, wbwide_i2cdma_we;\n\twire\t[26:0]\twbwide_i2cdma_addr;\n\twire\t[127:0]\twbwide_i2cdma_data;\n\twire\t[15:0]\twbwide_i2cdma_sel;\n\twire\t\twbwide_i2cdma_stall, wbwide_i2cdma_ack, wbwide_i2cdma_err;\n\twire\t[127:0]\twbwide_i2cdma_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wbwide, component sdio\n\t// Verilator lint_off UNUSED\n\twire\t\twbwide_sdio_cyc, wbwide_sdio_stb, wbwide_sdio_we;\n\twire\t[26:0]\twbwide_sdio_addr;\n\twire\t[127:0]\twbwide_sdio_data;\n\twire\t[15:0]\twbwide_sdio_sel;\n\twire\t\twbwide_sdio_stall, wbwide_sdio_ack, wbwide_sdio_err;\n\twire\t[127:0]\twbwide_sdio_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wbwide, component oled\n\t// Verilator lint_off UNUSED\n\twire\t\twbwide_oledm_cyc, wbwide_oledm_stb, wbwide_oledm_we;\n\twire\t[26:0]\twbwide_oledm_addr;\n\twire\t[127:0]\twbwide_oledm_data;\n\twire\t[15:0]\twbwide_oledm_sel;\n\twire\t\twbwide_oledm_stall, wbwide_oledm_ack, wbwide_oledm_err;\n\twire\t[127:0]\twbwide_oledm_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wbwide, component wbu_arbiter\n\t// Verilator lint_off UNUSED\n\twire\t\twbwide_wbu_arbiter_cyc, wbwide_wbu_arbiter_stb, wbwide_wbu_arbiter_we;\n\twire\t[26:0]\twbwide_wbu_arbiter_addr;\n\twire\t[127:0]\twbwide_wbu_arbiter_data;\n\twire\t[15:0]\twbwide_wbu_arbiter_sel;\n\twire\t\twbwide_wbu_arbiter_stall, wbwide_wbu_arbiter_ack, wbwide_wbu_arbiter_err;\n\twire\t[127:0]\twbwide_wbu_arbiter_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wbwide, component zip\n\t// Verilator lint_off UNUSED\n\twire\t\twbwide_zip_cyc, wbwide_zip_stb, wbwide_zip_we;\n\twire\t[26:0]\twbwide_zip_addr;\n\twire\t[127:0]\twbwide_zip_data;\n\twire\t[15:0]\twbwide_zip_sel;\n\twire\t\twbwide_zip_stall, wbwide_zip_ack, wbwide_zip_err;\n\twire\t[127:0]\twbwide_zip_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wbwide, component crossflash\n\t// Verilator lint_off UNUSED\n\twire\t\twbwide_crossflash_cyc, wbwide_crossflash_stb, wbwide_crossflash_we;\n\twire\t[26:0]\twbwide_crossflash_addr;\n\twire\t[127:0]\twbwide_crossflash_data;\n\twire\t[15:0]\twbwide_crossflash_sel;\n\twire\t\twbwide_crossflash_stall, wbwide_crossflash_ack, wbwide_crossflash_err;\n\twire\t[127:0]\twbwide_crossflash_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wbwide, component crossbus\n\t// Verilator lint_off UNUSED\n\twire\t\twbwide_crossbus_cyc, wbwide_crossbus_stb, wbwide_crossbus_we;\n\twire\t[26:0]\twbwide_crossbus_addr;\n\twire\t[127:0]\twbwide_crossbus_data;\n\twire\t[15:0]\twbwide_crossbus_sel;\n\twire\t\twbwide_crossbus_stall, wbwide_crossbus_ack, wbwide_crossbus_err;\n\twire\t[127:0]\twbwide_crossbus_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wbwide, component bkram\n\t// Verilator lint_off UNUSED\n\twire\t\twbwide_bkram_cyc, wbwide_bkram_stb, wbwide_bkram_we;\n\twire\t[26:0]\twbwide_bkram_addr;\n\twire\t[127:0]\twbwide_bkram_data;\n\twire\t[15:0]\twbwide_bkram_sel;\n\twire\t\twbwide_bkram_stall, wbwide_bkram_ack, wbwide_bkram_err;\n\twire\t[127:0]\twbwide_bkram_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wbwide, component ddr3\n\t// Verilator lint_off UNUSED\n\twire\t\twbwide_ddr3_cyc, wbwide_ddr3_stb, wbwide_ddr3_we;\n\twire\t[26:0]\twbwide_ddr3_addr;\n\twire\t[127:0]\twbwide_ddr3_data;\n\twire\t[15:0]\twbwide_ddr3_sel;\n\twire\t\twbwide_ddr3_stall, wbwide_ddr3_ack, wbwide_ddr3_err;\n\twire\t[127:0]\twbwide_ddr3_idata;\n\t// Verilator lint_on UNUSED\n\t// }}}\n\t// Bus wbflash\n\t// {{{\n\t// Wishbone definitions for bus wbflash, component crossflash\n\t// Verilator lint_off UNUSED\n\twire\t\twbflash_crossflash_cyc, wbflash_crossflash_stb, wbflash_crossflash_we;\n\twire\t[22:0]\twbflash_crossflash_addr;\n\twire\t[31:0]\twbflash_crossflash_data;\n\twire\t[3:0]\twbflash_crossflash_sel;\n\twire\t\twbflash_crossflash_stall, wbflash_crossflash_ack, wbflash_crossflash_err;\n\twire\t[31:0]\twbflash_crossflash_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wbflash, component sdio\n\t// Verilator lint_off UNUSED\n\twire\t\twbflash_sdio_cyc, wbflash_sdio_stb, wbflash_sdio_we;\n\twire\t[22:0]\twbflash_sdio_addr;\n\twire\t[31:0]\twbflash_sdio_data;\n\twire\t[3:0]\twbflash_sdio_sel;\n\twire\t\twbflash_sdio_stall, wbflash_sdio_ack, wbflash_sdio_err;\n\twire\t[31:0]\twbflash_sdio_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wbflash, component flash\n\t// Verilator lint_off UNUSED\n\twire\t\twbflash_flash_cyc, wbflash_flash_stb, wbflash_flash_we;\n\twire\t[22:0]\twbflash_flash_addr;\n\twire\t[31:0]\twbflash_flash_data;\n\twire\t[3:0]\twbflash_flash_sel;\n\twire\t\twbflash_flash_stall, wbflash_flash_ack, wbflash_flash_err;\n\twire\t[31:0]\twbflash_flash_idata;\n\t// Verilator lint_on UNUSED\n\t// }}}\n\t// Bus wb32\n\t// {{{\n\t// Wishbone definitions for bus wb32, component crossbus\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_crossbus_cyc, wb32_crossbus_stb, wb32_crossbus_we;\n\twire\t[11:0]\twb32_crossbus_addr;\n\twire\t[31:0]\twb32_crossbus_data;\n\twire\t[3:0]\twb32_crossbus_sel;\n\twire\t\twb32_crossbus_stall, wb32_crossbus_ack, wb32_crossbus_err;\n\twire\t[31:0]\twb32_crossbus_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(SIO), component adcclk\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_adcclk_cyc, wb32_adcclk_stb, wb32_adcclk_we;\n\twire\t[11:0]\twb32_adcclk_addr;\n\twire\t[31:0]\twb32_adcclk_data;\n\twire\t[3:0]\twb32_adcclk_sel;\n\twire\t\twb32_adcclk_stall, wb32_adcclk_ack, wb32_adcclk_err;\n\twire\t[31:0]\twb32_adcclk_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(SIO), component buildtime\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_buildtime_cyc, wb32_buildtime_stb, wb32_buildtime_we;\n\twire\t[11:0]\twb32_buildtime_addr;\n\twire\t[31:0]\twb32_buildtime_data;\n\twire\t[3:0]\twb32_buildtime_sel;\n\twire\t\twb32_buildtime_stall, wb32_buildtime_ack, wb32_buildtime_err;\n\twire\t[31:0]\twb32_buildtime_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(SIO), component buserr\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_buserr_cyc, wb32_buserr_stb, wb32_buserr_we;\n\twire\t[11:0]\twb32_buserr_addr;\n\twire\t[31:0]\twb32_buserr_data;\n\twire\t[3:0]\twb32_buserr_sel;\n\twire\t\twb32_buserr_stall, wb32_buserr_ack, wb32_buserr_err;\n\twire\t[31:0]\twb32_buserr_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(SIO), component buspic\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_buspic_cyc, wb32_buspic_stb, wb32_buspic_we;\n\twire\t[11:0]\twb32_buspic_addr;\n\twire\t[31:0]\twb32_buspic_data;\n\twire\t[3:0]\twb32_buspic_sel;\n\twire\t\twb32_buspic_stall, wb32_buspic_ack, wb32_buspic_err;\n\twire\t[31:0]\twb32_buspic_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(SIO), component gpio\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_gpio_cyc, wb32_gpio_stb, wb32_gpio_we;\n\twire\t[11:0]\twb32_gpio_addr;\n\twire\t[31:0]\twb32_gpio_data;\n\twire\t[3:0]\twb32_gpio_sel;\n\twire\t\twb32_gpio_stall, wb32_gpio_ack, wb32_gpio_err;\n\twire\t[31:0]\twb32_gpio_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(SIO), component pwrcount\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_pwrcount_cyc, wb32_pwrcount_stb, wb32_pwrcount_we;\n\twire\t[11:0]\twb32_pwrcount_addr;\n\twire\t[31:0]\twb32_pwrcount_data;\n\twire\t[3:0]\twb32_pwrcount_sel;\n\twire\t\twb32_pwrcount_stall, wb32_pwrcount_ack, wb32_pwrcount_err;\n\twire\t[31:0]\twb32_pwrcount_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(SIO), component rtcdate\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_rtcdate_cyc, wb32_rtcdate_stb, wb32_rtcdate_we;\n\twire\t[11:0]\twb32_rtcdate_addr;\n\twire\t[31:0]\twb32_rtcdate_data;\n\twire\t[3:0]\twb32_rtcdate_sel;\n\twire\t\twb32_rtcdate_stall, wb32_rtcdate_ack, wb32_rtcdate_err;\n\twire\t[31:0]\twb32_rtcdate_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(SIO), component rxeth0ck\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_rxeth0ck_cyc, wb32_rxeth0ck_stb, wb32_rxeth0ck_we;\n\twire\t[11:0]\twb32_rxeth0ck_addr;\n\twire\t[31:0]\twb32_rxeth0ck_data;\n\twire\t[3:0]\twb32_rxeth0ck_sel;\n\twire\t\twb32_rxeth0ck_stall, wb32_rxeth0ck_ack, wb32_rxeth0ck_err;\n\twire\t[31:0]\twb32_rxeth0ck_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(SIO), component spio\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_spio_cyc, wb32_spio_stb, wb32_spio_we;\n\twire\t[11:0]\twb32_spio_addr;\n\twire\t[31:0]\twb32_spio_data;\n\twire\t[3:0]\twb32_spio_sel;\n\twire\t\twb32_spio_stall, wb32_spio_ack, wb32_spio_err;\n\twire\t[31:0]\twb32_spio_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(SIO), component subseconds\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_subseconds_cyc, wb32_subseconds_stb, wb32_subseconds_we;\n\twire\t[11:0]\twb32_subseconds_addr;\n\twire\t[31:0]\twb32_subseconds_data;\n\twire\t[3:0]\twb32_subseconds_sel;\n\twire\t\twb32_subseconds_stall, wb32_subseconds_ack, wb32_subseconds_err;\n\twire\t[31:0]\twb32_subseconds_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(SIO), component txclk\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_txclk_cyc, wb32_txclk_stb, wb32_txclk_we;\n\twire\t[11:0]\twb32_txclk_addr;\n\twire\t[31:0]\twb32_txclk_data;\n\twire\t[3:0]\twb32_txclk_sel;\n\twire\t\twb32_txclk_stall, wb32_txclk_ack, wb32_txclk_err;\n\twire\t[31:0]\twb32_txclk_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(SIO), component version\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_version_cyc, wb32_version_stb, wb32_version_we;\n\twire\t[11:0]\twb32_version_addr;\n\twire\t[31:0]\twb32_version_data;\n\twire\t[3:0]\twb32_version_sel;\n\twire\t\twb32_version_stall, wb32_version_ack, wb32_version_err;\n\twire\t[31:0]\twb32_version_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(DIO), component edid\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_edids_cyc, wb32_edids_stb, wb32_edids_we;\n\twire\t[11:0]\twb32_edids_addr;\n\twire\t[31:0]\twb32_edids_data;\n\twire\t[3:0]\twb32_edids_sel;\n\twire\t\twb32_edids_stall, wb32_edids_ack, wb32_edids_err;\n\twire\t[31:0]\twb32_edids_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(DIO), component gck\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_gck_cyc, wb32_gck_stb, wb32_gck_we;\n\twire\t[11:0]\twb32_gck_addr;\n\twire\t[31:0]\twb32_gck_data;\n\twire\t[3:0]\twb32_gck_sel;\n\twire\t\twb32_gck_stall, wb32_gck_ack, wb32_gck_err;\n\twire\t[31:0]\twb32_gck_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(DIO), component i2c\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_i2cs_cyc, wb32_i2cs_stb, wb32_i2cs_we;\n\twire\t[11:0]\twb32_i2cs_addr;\n\twire\t[31:0]\twb32_i2cs_data;\n\twire\t[3:0]\twb32_i2cs_sel;\n\twire\t\twb32_i2cs_stall, wb32_i2cs_ack, wb32_i2cs_err;\n\twire\t[31:0]\twb32_i2cs_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(DIO), component i2cdma\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_i2cdma_cyc, wb32_i2cdma_stb, wb32_i2cdma_we;\n\twire\t[11:0]\twb32_i2cdma_addr;\n\twire\t[31:0]\twb32_i2cdma_data;\n\twire\t[3:0]\twb32_i2cdma_sel;\n\twire\t\twb32_i2cdma_stall, wb32_i2cdma_ack, wb32_i2cdma_err;\n\twire\t[31:0]\twb32_i2cdma_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(DIO), component oled\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_oled_cyc, wb32_oled_stb, wb32_oled_we;\n\twire\t[11:0]\twb32_oled_addr;\n\twire\t[31:0]\twb32_oled_data;\n\twire\t[3:0]\twb32_oled_sel;\n\twire\t\twb32_oled_stall, wb32_oled_ack, wb32_oled_err;\n\twire\t[31:0]\twb32_oled_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(DIO), component rtc\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_rtc_cyc, wb32_rtc_stb, wb32_rtc_we;\n\twire\t[11:0]\twb32_rtc_addr;\n\twire\t[31:0]\twb32_rtc_data;\n\twire\t[3:0]\twb32_rtc_sel;\n\twire\t\twb32_rtc_stall, wb32_rtc_ack, wb32_rtc_err;\n\twire\t[31:0]\twb32_rtc_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(DIO), component gtb\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_gtb_cyc, wb32_gtb_stb, wb32_gtb_we;\n\twire\t[11:0]\twb32_gtb_addr;\n\twire\t[31:0]\twb32_gtb_data;\n\twire\t[3:0]\twb32_gtb_sel;\n\twire\t\twb32_gtb_stall, wb32_gtb_ack, wb32_gtb_err;\n\twire\t[31:0]\twb32_gtb_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(DIO), component wb32_sio\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_sio_cyc, wb32_sio_stb, wb32_sio_we;\n\twire\t[11:0]\twb32_sio_addr;\n\twire\t[31:0]\twb32_sio_data;\n\twire\t[3:0]\twb32_sio_sel;\n\twire\t\twb32_sio_stall, wb32_sio_ack, wb32_sio_err;\n\twire\t[31:0]\twb32_sio_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32(DIO), component edidslv\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_edidslv_cyc, wb32_edidslv_stb, wb32_edidslv_we;\n\twire\t[11:0]\twb32_edidslv_addr;\n\twire\t[31:0]\twb32_edidslv_data;\n\twire\t[3:0]\twb32_edidslv_sel;\n\twire\t\twb32_edidslv_stall, wb32_edidslv_ack, wb32_edidslv_err;\n\twire\t[31:0]\twb32_edidslv_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32, component flashcfg\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_flashcfg_cyc, wb32_flashcfg_stb, wb32_flashcfg_we;\n\twire\t[11:0]\twb32_flashcfg_addr;\n\twire\t[31:0]\twb32_flashcfg_data;\n\twire\t[3:0]\twb32_flashcfg_sel;\n\twire\t\twb32_flashcfg_stall, wb32_flashcfg_ack, wb32_flashcfg_err;\n\twire\t[31:0]\twb32_flashcfg_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32, component edidslvscope\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_edidslvscope_cyc, wb32_edidslvscope_stb, wb32_edidslvscope_we;\n\twire\t[11:0]\twb32_edidslvscope_addr;\n\twire\t[31:0]\twb32_edidslvscope_data;\n\twire\t[3:0]\twb32_edidslvscope_sel;\n\twire\t\twb32_edidslvscope_stall, wb32_edidslvscope_ack, wb32_edidslvscope_err;\n\twire\t[31:0]\twb32_edidslvscope_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32, component pmic\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_pmic_cyc, wb32_pmic_stb, wb32_pmic_we;\n\twire\t[11:0]\twb32_pmic_addr;\n\twire\t[31:0]\twb32_pmic_data;\n\twire\t[3:0]\twb32_pmic_sel;\n\twire\t\twb32_pmic_stall, wb32_pmic_ack, wb32_pmic_err;\n\twire\t[31:0]\twb32_pmic_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32, component gpsu\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_gpsu_cyc, wb32_gpsu_stb, wb32_gpsu_we;\n\twire\t[11:0]\twb32_gpsu_addr;\n\twire\t[31:0]\twb32_gpsu_data;\n\twire\t[3:0]\twb32_gpsu_sel;\n\twire\t\twb32_gpsu_stall, wb32_gpsu_ack, wb32_gpsu_err;\n\twire\t[31:0]\twb32_gpsu_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32, component icape\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_icape_cyc, wb32_icape_stb, wb32_icape_we;\n\twire\t[11:0]\twb32_icape_addr;\n\twire\t[31:0]\twb32_icape_data;\n\twire\t[3:0]\twb32_icape_sel;\n\twire\t\twb32_icape_stall, wb32_icape_ack, wb32_icape_err;\n\twire\t[31:0]\twb32_icape_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32, component net\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_net_cyc, wb32_net_stb, wb32_net_we;\n\twire\t[11:0]\twb32_net_addr;\n\twire\t[31:0]\twb32_net_data;\n\twire\t[3:0]\twb32_net_sel;\n\twire\t\twb32_net_stall, wb32_net_ack, wb32_net_err;\n\twire\t[31:0]\twb32_net_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32, component ddr3_phy\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_ddr3_phy_cyc, wb32_ddr3_phy_stb, wb32_ddr3_phy_we;\n\twire\t[11:0]\twb32_ddr3_phy_addr;\n\twire\t[31:0]\twb32_ddr3_phy_data;\n\twire\t[3:0]\twb32_ddr3_phy_sel;\n\twire\t\twb32_ddr3_phy_stall, wb32_ddr3_phy_ack, wb32_ddr3_phy_err;\n\twire\t[31:0]\twb32_ddr3_phy_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32, component pxclk\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_pxclk_cyc, wb32_pxclk_stb, wb32_pxclk_we;\n\twire\t[11:0]\twb32_pxclk_addr;\n\twire\t[31:0]\twb32_pxclk_data;\n\twire\t[3:0]\twb32_pxclk_sel;\n\twire\t\twb32_pxclk_stall, wb32_pxclk_ack, wb32_pxclk_err;\n\twire\t[31:0]\twb32_pxclk_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32, component wb32_dio\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_dio_cyc, wb32_dio_stb, wb32_dio_we;\n\twire\t[11:0]\twb32_dio_addr;\n\twire\t[31:0]\twb32_dio_data;\n\twire\t[3:0]\twb32_dio_sel;\n\twire\t\twb32_dio_stall, wb32_dio_ack, wb32_dio_err;\n\twire\t[31:0]\twb32_dio_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32, component hdmi\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_hdmi_cyc, wb32_hdmi_stb, wb32_hdmi_we;\n\twire\t[11:0]\twb32_hdmi_addr;\n\twire\t[31:0]\twb32_hdmi_data;\n\twire\t[3:0]\twb32_hdmi_sel;\n\twire\t\twb32_hdmi_stall, wb32_hdmi_ack, wb32_hdmi_err;\n\twire\t[31:0]\twb32_hdmi_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wb32, component mdio\n\t// Verilator lint_off UNUSED\n\twire\t\twb32_mdio_cyc, wb32_mdio_stb, wb32_mdio_we;\n\twire\t[11:0]\twb32_mdio_addr;\n\twire\t[31:0]\twb32_mdio_data;\n\twire\t[3:0]\twb32_mdio_sel;\n\twire\t\twb32_mdio_stall, wb32_mdio_ack, wb32_mdio_err;\n\twire\t[31:0]\twb32_mdio_idata;\n\t// Verilator lint_on UNUSED\n\t// }}}\n\t// Bus wbu\n\t// {{{\n\t// Wishbone definitions for bus wbu, component wbu\n\t// Verilator lint_off UNUSED\n\twire\t\twbu_cyc, wbu_stb, wbu_we;\n\twire\t[29:0]\twbu_addr;\n\twire\t[31:0]\twbu_data;\n\twire\t[3:0]\twbu_sel;\n\twire\t\twbu_stall, wbu_ack, wbu_err;\n\twire\t[31:0]\twbu_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wbu, component wbu_arbiter\n\t// Verilator lint_off UNUSED\n\twire\t\twbu_wbu_arbiter_cyc, wbu_wbu_arbiter_stb, wbu_wbu_arbiter_we;\n\twire\t[29:0]\twbu_wbu_arbiter_addr;\n\twire\t[31:0]\twbu_wbu_arbiter_data;\n\twire\t[3:0]\twbu_wbu_arbiter_sel;\n\twire\t\twbu_wbu_arbiter_stall, wbu_wbu_arbiter_ack, wbu_wbu_arbiter_err;\n\twire\t[31:0]\twbu_wbu_arbiter_idata;\n\t// Verilator lint_on UNUSED\n\t// Wishbone definitions for bus wbu, component zip\n\t// Verilator lint_off UNUSED\n\twire\t\twbu_zip_cyc, wbu_zip_stb, wbu_zip_we;\n\twire\t[29:0]\twbu_zip_addr;\n\twire\t[31:0]\twbu_zip_data;\n\twire\t[3:0]\twbu_zip_sel;\n\twire\t\twbu_zip_stall, wbu_zip_ack, wbu_zip_err;\n\twire\t[31:0]\twbu_zip_idata;\n\t// Verilator lint_on UNUSED\n\t// }}}\n\t// }}}\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// Peripheral address decoding, bus handling\n\t// {{{\n\t//\n\t// BUS-LOGIC for wbwide\n\t// {{{\n\t//\n\t// No class SINGLE peripherals on the \"wbwide\" bus\n\t//\n\n\t//\n\t// No class DOUBLE peripherals on the \"wbwide\" bus\n\t//\n\n\t// info: @ERROR.WIRE for crossflash matches the buses error name, wbwide_crossflash_err\n\t// info: @ERROR.WIRE for crossbus matches the buses error name, wbwide_crossbus_err\n\tassign\twbwide_bkram_err= 1'b0;\n\tassign\twbwide_ddr3_err= 1'b0;\n\t//\n\t// Connect the wbwide bus components together using the wbxbar()\n\t//\n\t//\n\twbxbar #(\n\t\t.NM(8), .NS(4), .AW(27), .DW(128),\n\t\t.SLAVE_ADDR({\n\t\t\t// Address width    = 27\n\t\t\t// Address LSBs     = 4\n\t\t\t{ 27'h4000000 }, //       ddr3: 0x40000000\n\t\t\t{ 27'h1000000 }, //      bkram: 0x10000000\n\t\t\t{ 27'h0800000 }, //   crossbus: 0x08000000\n\t\t\t{ 27'h0000000 }  // crossflash: 0x00000000\n\t\t}),\n\t\t.SLAVE_MASK({\n\t\t\t// Address width    = 27\n\t\t\t// Address LSBs     = 4\n\t\t\t{ 27'h4000000 }, //       ddr3\n\t\t\t{ 27'h7800000 }, //      bkram\n\t\t\t{ 27'h7800000 }, //   crossbus\n\t\t\t{ 27'h7800000 }  // crossflash\n\t\t}),\n\t\t.OPT_DBLBUFFER(1'b1))\n\twbwide_xbar(\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t.i_mcyc({\n\t\t\twbwide_zip_cyc,\n\t\t\twbwide_wbu_arbiter_cyc,\n\t\t\twbwide_oledm_cyc,\n\t\t\twbwide_sdio_cyc,\n\t\t\twbwide_i2cdma_cyc,\n\t\t\twbwide_hdmi_cyc,\n\t\t\twbwide_edidm_cyc,\n\t\t\twbwide_i2cm_cyc\n\t\t}),\n\t\t.i_mstb({\n\t\t\twbwide_zip_stb,\n\t\t\twbwide_wbu_arbiter_stb,\n\t\t\twbwide_oledm_stb,\n\t\t\twbwide_sdio_stb,\n\t\t\twbwide_i2cdma_stb,\n\t\t\twbwide_hdmi_stb,\n\t\t\twbwide_edidm_stb,\n\t\t\twbwide_i2cm_stb\n\t\t}),\n\t\t.i_mwe({\n\t\t\twbwide_zip_we,\n\t\t\twbwide_wbu_arbiter_we,\n\t\t\twbwide_oledm_we,\n\t\t\twbwide_sdio_we,\n\t\t\twbwide_i2cdma_we,\n\t\t\twbwide_hdmi_we,\n\t\t\twbwide_edidm_we,\n\t\t\twbwide_i2cm_we\n\t\t}),\n\t\t.i_maddr({\n\t\t\twbwide_zip_addr,\n\t\t\twbwide_wbu_arbiter_addr,\n\t\t\twbwide_oledm_addr,\n\t\t\twbwide_sdio_addr,\n\t\t\twbwide_i2cdma_addr,\n\t\t\twbwide_hdmi_addr,\n\t\t\twbwide_edidm_addr,\n\t\t\twbwide_i2cm_addr\n\t\t}),\n\t\t.i_mdata({\n\t\t\twbwide_zip_data,\n\t\t\twbwide_wbu_arbiter_data,\n\t\t\twbwide_oledm_data,\n\t\t\twbwide_sdio_data,\n\t\t\twbwide_i2cdma_data,\n\t\t\twbwide_hdmi_data,\n\t\t\twbwide_edidm_data,\n\t\t\twbwide_i2cm_data\n\t\t}),\n\t\t.i_msel({\n\t\t\twbwide_zip_sel,\n\t\t\twbwide_wbu_arbiter_sel,\n\t\t\twbwide_oledm_sel,\n\t\t\twbwide_sdio_sel,\n\t\t\twbwide_i2cdma_sel,\n\t\t\twbwide_hdmi_sel,\n\t\t\twbwide_edidm_sel,\n\t\t\twbwide_i2cm_sel\n\t\t}),\n\t\t.o_mstall({\n\t\t\twbwide_zip_stall,\n\t\t\twbwide_wbu_arbiter_stall,\n\t\t\twbwide_oledm_stall,\n\t\t\twbwide_sdio_stall,\n\t\t\twbwide_i2cdma_stall,\n\t\t\twbwide_hdmi_stall,\n\t\t\twbwide_edidm_stall,\n\t\t\twbwide_i2cm_stall\n\t\t}),\n\t\t.o_mack({\n\t\t\twbwide_zip_ack,\n\t\t\twbwide_wbu_arbiter_ack,\n\t\t\twbwide_oledm_ack,\n\t\t\twbwide_sdio_ack,\n\t\t\twbwide_i2cdma_ack,\n\t\t\twbwide_hdmi_ack,\n\t\t\twbwide_edidm_ack,\n\t\t\twbwide_i2cm_ack\n\t\t}),\n\t\t.o_mdata({\n\t\t\twbwide_zip_idata,\n\t\t\twbwide_wbu_arbiter_idata,\n\t\t\twbwide_oledm_idata,\n\t\t\twbwide_sdio_idata,\n\t\t\twbwide_i2cdma_idata,\n\t\t\twbwide_hdmi_idata,\n\t\t\twbwide_edidm_idata,\n\t\t\twbwide_i2cm_idata\n\t\t}),\n\t\t.o_merr({\n\t\t\twbwide_zip_err,\n\t\t\twbwide_wbu_arbiter_err,\n\t\t\twbwide_oledm_err,\n\t\t\twbwide_sdio_err,\n\t\t\twbwide_i2cdma_err,\n\t\t\twbwide_hdmi_err,\n\t\t\twbwide_edidm_err,\n\t\t\twbwide_i2cm_err\n\t\t}),\n\t\t// Slave connections\n\t\t.o_scyc({\n\t\t\twbwide_ddr3_cyc,\n\t\t\twbwide_bkram_cyc,\n\t\t\twbwide_crossbus_cyc,\n\t\t\twbwide_crossflash_cyc\n\t\t}),\n\t\t.o_sstb({\n\t\t\twbwide_ddr3_stb,\n\t\t\twbwide_bkram_stb,\n\t\t\twbwide_crossbus_stb,\n\t\t\twbwide_crossflash_stb\n\t\t}),\n\t\t.o_swe({\n\t\t\twbwide_ddr3_we,\n\t\t\twbwide_bkram_we,\n\t\t\twbwide_crossbus_we,\n\t\t\twbwide_crossflash_we\n\t\t}),\n\t\t.o_saddr({\n\t\t\twbwide_ddr3_addr,\n\t\t\twbwide_bkram_addr,\n\t\t\twbwide_crossbus_addr,\n\t\t\twbwide_crossflash_addr\n\t\t}),\n\t\t.o_sdata({\n\t\t\twbwide_ddr3_data,\n\t\t\twbwide_bkram_data,\n\t\t\twbwide_crossbus_data,\n\t\t\twbwide_crossflash_data\n\t\t}),\n\t\t.o_ssel({\n\t\t\twbwide_ddr3_sel,\n\t\t\twbwide_bkram_sel,\n\t\t\twbwide_crossbus_sel,\n\t\t\twbwide_crossflash_sel\n\t\t}),\n\t\t.i_sstall({\n\t\t\twbwide_ddr3_stall,\n\t\t\twbwide_bkram_stall,\n\t\t\twbwide_crossbus_stall,\n\t\t\twbwide_crossflash_stall\n\t\t}),\n\t\t.i_sack({\n\t\t\twbwide_ddr3_ack,\n\t\t\twbwide_bkram_ack,\n\t\t\twbwide_crossbus_ack,\n\t\t\twbwide_crossflash_ack\n\t\t}),\n\t\t.i_sdata({\n\t\t\twbwide_ddr3_idata,\n\t\t\twbwide_bkram_idata,\n\t\t\twbwide_crossbus_idata,\n\t\t\twbwide_crossflash_idata\n\t\t}),\n\t\t.i_serr({\n\t\t\twbwide_ddr3_err,\n\t\t\twbwide_bkram_err,\n\t\t\twbwide_crossbus_err,\n\t\t\twbwide_crossflash_err\n\t\t})\n\t\t);\n\n\t// End of bus logic for wbwide\n\t// }}}\n\t//\n\t// BUS-LOGIC for wbflash\n\t// {{{\n\t//\n\t// No class SINGLE peripherals on the \"wbflash\" bus\n\t//\n\n\t//\n\t// No class DOUBLE peripherals on the \"wbflash\" bus\n\t//\n\n\tassign\twbflash_sdio_err= 1'b0;\n\tassign\twbflash_flash_err= 1'b0;\n\t//\n\t// Connect the wbflash bus components together using the wbxbar()\n\t//\n\t//\n\twbxbar #(\n\t\t.NM(1), .NS(2), .AW(23), .DW(32),\n\t\t.SLAVE_ADDR({\n\t\t\t// Address width    = 23\n\t\t\t// Address LSBs     = 2\n\t\t\t{ 23'h400000 }, // flash: 0x1000000\n\t\t\t{ 23'h200000 }  //  sdio: 0x0800000\n\t\t}),\n\t\t.SLAVE_MASK({\n\t\t\t// Address width    = 23\n\t\t\t// Address LSBs     = 2\n\t\t\t{ 23'h400000 }, // flash\n\t\t\t{ 23'h600000 }  //  sdio\n\t\t}),\n\t\t.OPT_DBLBUFFER(1'b1))\n\twbflash_xbar(\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t.i_mcyc({\n\t\t\twbflash_crossflash_cyc\n\t\t}),\n\t\t.i_mstb({\n\t\t\twbflash_crossflash_stb\n\t\t}),\n\t\t.i_mwe({\n\t\t\twbflash_crossflash_we\n\t\t}),\n\t\t.i_maddr({\n\t\t\twbflash_crossflash_addr\n\t\t}),\n\t\t.i_mdata({\n\t\t\twbflash_crossflash_data\n\t\t}),\n\t\t.i_msel({\n\t\t\twbflash_crossflash_sel\n\t\t}),\n\t\t.o_mstall({\n\t\t\twbflash_crossflash_stall\n\t\t}),\n\t\t.o_mack({\n\t\t\twbflash_crossflash_ack\n\t\t}),\n\t\t.o_mdata({\n\t\t\twbflash_crossflash_idata\n\t\t}),\n\t\t.o_merr({\n\t\t\twbflash_crossflash_err\n\t\t}),\n\t\t// Slave connections\n\t\t.o_scyc({\n\t\t\twbflash_flash_cyc,\n\t\t\twbflash_sdio_cyc\n\t\t}),\n\t\t.o_sstb({\n\t\t\twbflash_flash_stb,\n\t\t\twbflash_sdio_stb\n\t\t}),\n\t\t.o_swe({\n\t\t\twbflash_flash_we,\n\t\t\twbflash_sdio_we\n\t\t}),\n\t\t.o_saddr({\n\t\t\twbflash_flash_addr,\n\t\t\twbflash_sdio_addr\n\t\t}),\n\t\t.o_sdata({\n\t\t\twbflash_flash_data,\n\t\t\twbflash_sdio_data\n\t\t}),\n\t\t.o_ssel({\n\t\t\twbflash_flash_sel,\n\t\t\twbflash_sdio_sel\n\t\t}),\n\t\t.i_sstall({\n\t\t\twbflash_flash_stall,\n\t\t\twbflash_sdio_stall\n\t\t}),\n\t\t.i_sack({\n\t\t\twbflash_flash_ack,\n\t\t\twbflash_sdio_ack\n\t\t}),\n\t\t.i_sdata({\n\t\t\twbflash_flash_idata,\n\t\t\twbflash_sdio_idata\n\t\t}),\n\t\t.i_serr({\n\t\t\twbflash_flash_err,\n\t\t\twbflash_sdio_err\n\t\t})\n\t\t);\n\n\t// End of bus logic for wbflash\n\t// }}}\n\t//\n\t// BUS-LOGIC for wb32\n\t// {{{\n\t//\n\t// wb32 Bus logic to handle SINGLE slaves\n\t//\n\treg\t\tr_wb32_sio_ack;\n\treg\t[31:0]\tr_wb32_sio_data;\n\n\tassign\twb32_sio_stall = 1'b0;\n\n\tinitial r_wb32_sio_ack = 1'b0;\n\talways\t@(posedge i_clk)\n\t\tr_wb32_sio_ack <= (wb32_sio_stb);\n\tassign\twb32_sio_ack = r_wb32_sio_ack;\n\n\talways\t@(posedge i_clk)\n\tcasez( wb32_sio_addr[3:0] )\n\t4'h0: r_wb32_sio_data <= wb32_adcclk_idata;\n\t4'h1: r_wb32_sio_data <= wb32_buildtime_idata;\n\t4'h2: r_wb32_sio_data <= wb32_buserr_idata;\n\t4'h3: r_wb32_sio_data <= wb32_buspic_idata;\n\t4'h4: r_wb32_sio_data <= wb32_gpio_idata;\n\t4'h5: r_wb32_sio_data <= wb32_pwrcount_idata;\n\t4'h6: r_wb32_sio_data <= wb32_rtcdate_idata;\n\t4'h7: r_wb32_sio_data <= wb32_rxeth0ck_idata;\n\t4'h8: r_wb32_sio_data <= wb32_spio_idata;\n\t4'h9: r_wb32_sio_data <= wb32_subseconds_idata;\n\t4'ha: r_wb32_sio_data <= wb32_txclk_idata;\n\t4'hb: r_wb32_sio_data <= wb32_version_idata;\n\tdefault: r_wb32_sio_data <= wb32_version_idata;\n\tendcase\n\tassign\twb32_sio_idata = r_wb32_sio_data;\n\n\n\t//\n\t// Now to translate this logic to the various SIO slaves\n\t//\n\t// In this case, the SIO bus has the prefix wb32_sio\n\t// and all of the slaves have various wires beginning\n\t// with their own respective bus prefixes.\n\t// Our goal here is to make certain that all of\n\t// the slave bus inputs match the SIO bus wires\n\tassign\twb32_adcclk_cyc = wb32_sio_cyc;\n\tassign\twb32_adcclk_stb = wb32_sio_stb && (wb32_sio_addr[ 3: 0] ==  4'h0);  // 0x000\n\tassign\twb32_adcclk_we  = wb32_sio_we;\n\tassign\twb32_adcclk_data= wb32_sio_data;\n\tassign\twb32_adcclk_sel = wb32_sio_sel;\n\tassign\twb32_buildtime_cyc = wb32_sio_cyc;\n\tassign\twb32_buildtime_stb = wb32_sio_stb && (wb32_sio_addr[ 3: 0] ==  4'h1);  // 0x004\n\tassign\twb32_buildtime_we  = wb32_sio_we;\n\tassign\twb32_buildtime_data= wb32_sio_data;\n\tassign\twb32_buildtime_sel = wb32_sio_sel;\n\tassign\twb32_buserr_cyc = wb32_sio_cyc;\n\tassign\twb32_buserr_stb = wb32_sio_stb && (wb32_sio_addr[ 3: 0] ==  4'h2);  // 0x008\n\tassign\twb32_buserr_we  = wb32_sio_we;\n\tassign\twb32_buserr_data= wb32_sio_data;\n\tassign\twb32_buserr_sel = wb32_sio_sel;\n\tassign\twb32_buspic_cyc = wb32_sio_cyc;\n\tassign\twb32_buspic_stb = wb32_sio_stb && (wb32_sio_addr[ 3: 0] ==  4'h3);  // 0x00c\n\tassign\twb32_buspic_we  = wb32_sio_we;\n\tassign\twb32_buspic_data= wb32_sio_data;\n\tassign\twb32_buspic_sel = wb32_sio_sel;\n\tassign\twb32_gpio_cyc = wb32_sio_cyc;\n\tassign\twb32_gpio_stb = wb32_sio_stb && (wb32_sio_addr[ 3: 0] ==  4'h4);  // 0x010\n\tassign\twb32_gpio_we  = wb32_sio_we;\n\tassign\twb32_gpio_data= wb32_sio_data;\n\tassign\twb32_gpio_sel = wb32_sio_sel;\n\tassign\twb32_pwrcount_cyc = wb32_sio_cyc;\n\tassign\twb32_pwrcount_stb = wb32_sio_stb && (wb32_sio_addr[ 3: 0] ==  4'h5);  // 0x014\n\tassign\twb32_pwrcount_we  = wb32_sio_we;\n\tassign\twb32_pwrcount_data= wb32_sio_data;\n\tassign\twb32_pwrcount_sel = wb32_sio_sel;\n\tassign\twb32_rtcdate_cyc = wb32_sio_cyc;\n\tassign\twb32_rtcdate_stb = wb32_sio_stb && (wb32_sio_addr[ 3: 0] ==  4'h6);  // 0x018\n\tassign\twb32_rtcdate_we  = wb32_sio_we;\n\tassign\twb32_rtcdate_data= wb32_sio_data;\n\tassign\twb32_rtcdate_sel = wb32_sio_sel;\n\tassign\twb32_rxeth0ck_cyc = wb32_sio_cyc;\n\tassign\twb32_rxeth0ck_stb = wb32_sio_stb && (wb32_sio_addr[ 3: 0] ==  4'h7);  // 0x01c\n\tassign\twb32_rxeth0ck_we  = wb32_sio_we;\n\tassign\twb32_rxeth0ck_data= wb32_sio_data;\n\tassign\twb32_rxeth0ck_sel = wb32_sio_sel;\n\tassign\twb32_spio_cyc = wb32_sio_cyc;\n\tassign\twb32_spio_stb = wb32_sio_stb && (wb32_sio_addr[ 3: 0] ==  4'h8);  // 0x020\n\tassign\twb32_spio_we  = wb32_sio_we;\n\tassign\twb32_spio_data= wb32_sio_data;\n\tassign\twb32_spio_sel = wb32_sio_sel;\n\tassign\twb32_subseconds_cyc = wb32_sio_cyc;\n\tassign\twb32_subseconds_stb = wb32_sio_stb && (wb32_sio_addr[ 3: 0] ==  4'h9);  // 0x024\n\tassign\twb32_subseconds_we  = wb32_sio_we;\n\tassign\twb32_subseconds_data= wb32_sio_data;\n\tassign\twb32_subseconds_sel = wb32_sio_sel;\n\tassign\twb32_txclk_cyc = wb32_sio_cyc;\n\tassign\twb32_txclk_stb = wb32_sio_stb && (wb32_sio_addr[ 3: 0] ==  4'ha);  // 0x028\n\tassign\twb32_txclk_we  = wb32_sio_we;\n\tassign\twb32_txclk_data= wb32_sio_data;\n\tassign\twb32_txclk_sel = wb32_sio_sel;\n\tassign\twb32_version_cyc = wb32_sio_cyc;\n\tassign\twb32_version_stb = wb32_sio_stb && (wb32_sio_addr[ 3: 0] ==  4'hb);  // 0x02c\n\tassign\twb32_version_we  = wb32_sio_we;\n\tassign\twb32_version_data= wb32_sio_data;\n\tassign\twb32_version_sel = wb32_sio_sel;\n\t//\n\t// wb32 Bus logic to handle 9 DOUBLE slaves\n\t//\n\t//\n\treg\t[1:0]\tr_wb32_dio_ack;\n\t// # dlist = 9, nextlg(#dlist) = 4\n\treg\t[3:0]\tr_wb32_dio_bus_select;\n\treg\t[31:0]\tr_wb32_dio_data;\n\n\t// DOUBLE peripherals are not allowed to stall.\n\tassign\twb32_dio_stall = 1'b0;\n\n\t// DOUBLE peripherals return their acknowledgments in two\n\t// clocks--always, allowing us to collect this logic together\n\t// in a slave independent manner.  Here, the acknowledgment\n\t// is treated as a two stage shift register, cleared on any\n\t// reset, or any time the cycle line drops.  (Dropping the\n\t// cycle line aborts the transaction.)\n\tinitial\tr_wb32_dio_ack = 0;\n\talways\t@(posedge i_clk)\n\tif (i_reset || !wb32_dio_cyc)\n\t\tr_wb32_dio_ack <= 0;\n\telse\n\t\tr_wb32_dio_ack <= { r_wb32_dio_ack[0], (wb32_dio_stb) };\n\tassign\twb32_dio_ack = r_wb32_dio_ack[1];\n\n\t// Since it costs us two clocks to go through this\n\t// logic, we'll take one of those clocks here to set\n\t// a selection index, and then on the next clock we'll\n\t// use this index to select from among the vaious\n\t// possible bus return values\n\talways @(posedge i_clk)\n\tcasez(wb32_dio_addr[6:2])\n\t5'b0_0000: r_wb32_dio_bus_select <= 4'd0;\n\t5'b0_0001: r_wb32_dio_bus_select <= 4'd1;\n\t5'b0_0010: r_wb32_dio_bus_select <= 4'd2;\n\t5'b0_0011: r_wb32_dio_bus_select <= 4'd3;\n\t5'b0_0100: r_wb32_dio_bus_select <= 4'd4;\n\t5'b0_0101: r_wb32_dio_bus_select <= 4'd5;\n\t5'b0_011?: r_wb32_dio_bus_select <= 4'd6;\n\t5'b0_10??: r_wb32_dio_bus_select <= 4'd7;\n\t5'b1_????: r_wb32_dio_bus_select <= 4'd8;\n\tdefault: r_wb32_dio_bus_select <= 0;\n\tendcase\n\n\talways\t@(posedge i_clk)\n\tcasez(r_wb32_dio_bus_select)\n\t4'd0: r_wb32_dio_data <= wb32_edids_idata;\n\t4'd1: r_wb32_dio_data <= wb32_gck_idata;\n\t4'd2: r_wb32_dio_data <= wb32_i2cs_idata;\n\t4'd3: r_wb32_dio_data <= wb32_i2cdma_idata;\n\t4'd4: r_wb32_dio_data <= wb32_oled_idata;\n\t4'd5: r_wb32_dio_data <= wb32_rtc_idata;\n\t4'd6: r_wb32_dio_data <= wb32_gtb_idata;\n\t4'd7: r_wb32_dio_data <= wb32_sio_idata;\n\t4'd8: r_wb32_dio_data <= wb32_edidslv_idata;\n\tdefault: r_wb32_dio_data <= wb32_edidslv_idata;\n\tendcase\n\n\tassign\twb32_dio_idata = r_wb32_dio_data;\n\n\tassign\twb32_edids_cyc = wb32_dio_cyc;\n\tassign\twb32_edids_stb = wb32_dio_stb && ((wb32_dio_addr[ 6: 2] &  5'h1f) ==  5'h00);  // 0x000 - 0x00f\n\tassign\twb32_edids_we  = wb32_dio_we;\n\tassign\twb32_edids_addr= wb32_dio_addr;\n\tassign\twb32_edids_data= wb32_dio_data;\n\tassign\twb32_edids_sel = wb32_dio_sel;\n\tassign\twb32_gck_cyc = wb32_dio_cyc;\n\tassign\twb32_gck_stb = wb32_dio_stb && ((wb32_dio_addr[ 6: 2] &  5'h1f) ==  5'h01);  // 0x010 - 0x01f\n\tassign\twb32_gck_we  = wb32_dio_we;\n\tassign\twb32_gck_addr= wb32_dio_addr;\n\tassign\twb32_gck_data= wb32_dio_data;\n\tassign\twb32_gck_sel = wb32_dio_sel;\n\tassign\twb32_i2cs_cyc = wb32_dio_cyc;\n\tassign\twb32_i2cs_stb = wb32_dio_stb && ((wb32_dio_addr[ 6: 2] &  5'h1f) ==  5'h02);  // 0x020 - 0x02f\n\tassign\twb32_i2cs_we  = wb32_dio_we;\n\tassign\twb32_i2cs_addr= wb32_dio_addr;\n\tassign\twb32_i2cs_data= wb32_dio_data;\n\tassign\twb32_i2cs_sel = wb32_dio_sel;\n\tassign\twb32_i2cdma_cyc = wb32_dio_cyc;\n\tassign\twb32_i2cdma_stb = wb32_dio_stb && ((wb32_dio_addr[ 6: 2] &  5'h1f) ==  5'h03);  // 0x030 - 0x03f\n\tassign\twb32_i2cdma_we  = wb32_dio_we;\n\tassign\twb32_i2cdma_addr= wb32_dio_addr;\n\tassign\twb32_i2cdma_data= wb32_dio_data;\n\tassign\twb32_i2cdma_sel = wb32_dio_sel;\n\tassign\twb32_oled_cyc = wb32_dio_cyc;\n\tassign\twb32_oled_stb = wb32_dio_stb && ((wb32_dio_addr[ 6: 2] &  5'h1f) ==  5'h04);  // 0x040 - 0x04f\n\tassign\twb32_oled_we  = wb32_dio_we;\n\tassign\twb32_oled_addr= wb32_dio_addr;\n\tassign\twb32_oled_data= wb32_dio_data;\n\tassign\twb32_oled_sel = wb32_dio_sel;\n\tassign\twb32_rtc_cyc = wb32_dio_cyc;\n\tassign\twb32_rtc_stb = wb32_dio_stb && ((wb32_dio_addr[ 6: 2] &  5'h1f) ==  5'h05);  // 0x050 - 0x05f\n\tassign\twb32_rtc_we  = wb32_dio_we;\n\tassign\twb32_rtc_addr= wb32_dio_addr;\n\tassign\twb32_rtc_data= wb32_dio_data;\n\tassign\twb32_rtc_sel = wb32_dio_sel;\n\tassign\twb32_gtb_cyc = wb32_dio_cyc;\n\tassign\twb32_gtb_stb = wb32_dio_stb && ((wb32_dio_addr[ 6: 2] &  5'h1e) ==  5'h06);  // 0x060 - 0x07f\n\tassign\twb32_gtb_we  = wb32_dio_we;\n\tassign\twb32_gtb_addr= wb32_dio_addr;\n\tassign\twb32_gtb_data= wb32_dio_data;\n\tassign\twb32_gtb_sel = wb32_dio_sel;\n\tassign\twb32_sio_cyc = wb32_dio_cyc;\n\tassign\twb32_sio_stb = wb32_dio_stb && ((wb32_dio_addr[ 6: 2] &  5'h1c) ==  5'h08);  // 0x080 - 0x0bf\n\tassign\twb32_sio_we  = wb32_dio_we;\n\tassign\twb32_sio_addr= wb32_dio_addr;\n\tassign\twb32_sio_data= wb32_dio_data;\n\tassign\twb32_sio_sel = wb32_dio_sel;\n\tassign\twb32_edidslv_cyc = wb32_dio_cyc;\n\tassign\twb32_edidslv_stb = wb32_dio_stb && ((wb32_dio_addr[ 6: 2] &  5'h10) ==  5'h10);  // 0x100 - 0x1ff\n\tassign\twb32_edidslv_we  = wb32_dio_we;\n\tassign\twb32_edidslv_addr= wb32_dio_addr;\n\tassign\twb32_edidslv_data= wb32_dio_data;\n\tassign\twb32_edidslv_sel = wb32_dio_sel;\n\tassign\twb32_flashcfg_err= 1'b0;\n\tassign\twb32_edidslvscope_err= 1'b0;\n\tassign\twb32_pmic_err= 1'b0;\n\tassign\twb32_gpsu_err= 1'b0;\n\tassign\twb32_icape_err= 1'b0;\n\tassign\twb32_net_err= 1'b0;\n\tassign\twb32_ddr3_phy_err= 1'b0;\n\tassign\twb32_pxclk_err= 1'b0;\n\tassign\twb32_dio_err= 1'b0;\n\tassign\twb32_hdmi_err= 1'b0;\n\tassign\twb32_mdio_err= 1'b0;\n\t//\n\t// Connect the wb32 bus components together using the wbxbar()\n\t//\n\t//\n\twbxbar #(\n\t\t.NM(1), .NS(11), .AW(12), .DW(32),\n\t\t.SLAVE_ADDR({\n\t\t\t// Address width    = 12\n\t\t\t// Address LSBs     = 2\n\t\t\t{ 12'hc00 }, //         mdio: 0x3000\n\t\t\t{ 12'h800 }, //         hdmi: 0x2000\n\t\t\t{ 12'h500 }, //     wb32_dio: 0x1400\n\t\t\t{ 12'h480 }, //        pxclk: 0x1200\n\t\t\t{ 12'h400 }, //     ddr3_phy: 0x1000\n\t\t\t{ 12'h380 }, //          net: 0x0e00\n\t\t\t{ 12'h300 }, //        icape: 0x0c00\n\t\t\t{ 12'h280 }, //         gpsu: 0x0a00\n\t\t\t{ 12'h200 }, //         pmic: 0x0800\n\t\t\t{ 12'h180 }, // edidslvscope: 0x0600\n\t\t\t{ 12'h100 }  //     flashcfg: 0x0400\n\t\t}),\n\t\t.SLAVE_MASK({\n\t\t\t// Address width    = 12\n\t\t\t// Address LSBs     = 2\n\t\t\t{ 12'hc00 }, //         mdio\n\t\t\t{ 12'hc00 }, //         hdmi\n\t\t\t{ 12'hf80 }, //     wb32_dio\n\t\t\t{ 12'hf80 }, //        pxclk\n\t\t\t{ 12'hf80 }, //     ddr3_phy\n\t\t\t{ 12'hf80 }, //          net\n\t\t\t{ 12'hf80 }, //        icape\n\t\t\t{ 12'hf80 }, //         gpsu\n\t\t\t{ 12'hf80 }, //         pmic\n\t\t\t{ 12'hf80 }, // edidslvscope\n\t\t\t{ 12'hf80 }  //     flashcfg\n\t\t}),\n\t\t.OPT_DBLBUFFER(1'b1))\n\twb32_xbar(\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t.i_mcyc({\n\t\t\twb32_crossbus_cyc\n\t\t}),\n\t\t.i_mstb({\n\t\t\twb32_crossbus_stb\n\t\t}),\n\t\t.i_mwe({\n\t\t\twb32_crossbus_we\n\t\t}),\n\t\t.i_maddr({\n\t\t\twb32_crossbus_addr\n\t\t}),\n\t\t.i_mdata({\n\t\t\twb32_crossbus_data\n\t\t}),\n\t\t.i_msel({\n\t\t\twb32_crossbus_sel\n\t\t}),\n\t\t.o_mstall({\n\t\t\twb32_crossbus_stall\n\t\t}),\n\t\t.o_mack({\n\t\t\twb32_crossbus_ack\n\t\t}),\n\t\t.o_mdata({\n\t\t\twb32_crossbus_idata\n\t\t}),\n\t\t.o_merr({\n\t\t\twb32_crossbus_err\n\t\t}),\n\t\t// Slave connections\n\t\t.o_scyc({\n\t\t\twb32_mdio_cyc,\n\t\t\twb32_hdmi_cyc,\n\t\t\twb32_dio_cyc,\n\t\t\twb32_pxclk_cyc,\n\t\t\twb32_ddr3_phy_cyc,\n\t\t\twb32_net_cyc,\n\t\t\twb32_icape_cyc,\n\t\t\twb32_gpsu_cyc,\n\t\t\twb32_pmic_cyc,\n\t\t\twb32_edidslvscope_cyc,\n\t\t\twb32_flashcfg_cyc\n\t\t}),\n\t\t.o_sstb({\n\t\t\twb32_mdio_stb,\n\t\t\twb32_hdmi_stb,\n\t\t\twb32_dio_stb,\n\t\t\twb32_pxclk_stb,\n\t\t\twb32_ddr3_phy_stb,\n\t\t\twb32_net_stb,\n\t\t\twb32_icape_stb,\n\t\t\twb32_gpsu_stb,\n\t\t\twb32_pmic_stb,\n\t\t\twb32_edidslvscope_stb,\n\t\t\twb32_flashcfg_stb\n\t\t}),\n\t\t.o_swe({\n\t\t\twb32_mdio_we,\n\t\t\twb32_hdmi_we,\n\t\t\twb32_dio_we,\n\t\t\twb32_pxclk_we,\n\t\t\twb32_ddr3_phy_we,\n\t\t\twb32_net_we,\n\t\t\twb32_icape_we,\n\t\t\twb32_gpsu_we,\n\t\t\twb32_pmic_we,\n\t\t\twb32_edidslvscope_we,\n\t\t\twb32_flashcfg_we\n\t\t}),\n\t\t.o_saddr({\n\t\t\twb32_mdio_addr,\n\t\t\twb32_hdmi_addr,\n\t\t\twb32_dio_addr,\n\t\t\twb32_pxclk_addr,\n\t\t\twb32_ddr3_phy_addr,\n\t\t\twb32_net_addr,\n\t\t\twb32_icape_addr,\n\t\t\twb32_gpsu_addr,\n\t\t\twb32_pmic_addr,\n\t\t\twb32_edidslvscope_addr,\n\t\t\twb32_flashcfg_addr\n\t\t}),\n\t\t.o_sdata({\n\t\t\twb32_mdio_data,\n\t\t\twb32_hdmi_data,\n\t\t\twb32_dio_data,\n\t\t\twb32_pxclk_data,\n\t\t\twb32_ddr3_phy_data,\n\t\t\twb32_net_data,\n\t\t\twb32_icape_data,\n\t\t\twb32_gpsu_data,\n\t\t\twb32_pmic_data,\n\t\t\twb32_edidslvscope_data,\n\t\t\twb32_flashcfg_data\n\t\t}),\n\t\t.o_ssel({\n\t\t\twb32_mdio_sel,\n\t\t\twb32_hdmi_sel,\n\t\t\twb32_dio_sel,\n\t\t\twb32_pxclk_sel,\n\t\t\twb32_ddr3_phy_sel,\n\t\t\twb32_net_sel,\n\t\t\twb32_icape_sel,\n\t\t\twb32_gpsu_sel,\n\t\t\twb32_pmic_sel,\n\t\t\twb32_edidslvscope_sel,\n\t\t\twb32_flashcfg_sel\n\t\t}),\n\t\t.i_sstall({\n\t\t\twb32_mdio_stall,\n\t\t\twb32_hdmi_stall,\n\t\t\twb32_dio_stall,\n\t\t\twb32_pxclk_stall,\n\t\t\twb32_ddr3_phy_stall,\n\t\t\twb32_net_stall,\n\t\t\twb32_icape_stall,\n\t\t\twb32_gpsu_stall,\n\t\t\twb32_pmic_stall,\n\t\t\twb32_edidslvscope_stall,\n\t\t\twb32_flashcfg_stall\n\t\t}),\n\t\t.i_sack({\n\t\t\twb32_mdio_ack,\n\t\t\twb32_hdmi_ack,\n\t\t\twb32_dio_ack,\n\t\t\twb32_pxclk_ack,\n\t\t\twb32_ddr3_phy_ack,\n\t\t\twb32_net_ack,\n\t\t\twb32_icape_ack,\n\t\t\twb32_gpsu_ack,\n\t\t\twb32_pmic_ack,\n\t\t\twb32_edidslvscope_ack,\n\t\t\twb32_flashcfg_ack\n\t\t}),\n\t\t.i_sdata({\n\t\t\twb32_mdio_idata,\n\t\t\twb32_hdmi_idata,\n\t\t\twb32_dio_idata,\n\t\t\twb32_pxclk_idata,\n\t\t\twb32_ddr3_phy_idata,\n\t\t\twb32_net_idata,\n\t\t\twb32_icape_idata,\n\t\t\twb32_gpsu_idata,\n\t\t\twb32_pmic_idata,\n\t\t\twb32_edidslvscope_idata,\n\t\t\twb32_flashcfg_idata\n\t\t}),\n\t\t.i_serr({\n\t\t\twb32_mdio_err,\n\t\t\twb32_hdmi_err,\n\t\t\twb32_dio_err,\n\t\t\twb32_pxclk_err,\n\t\t\twb32_ddr3_phy_err,\n\t\t\twb32_net_err,\n\t\t\twb32_icape_err,\n\t\t\twb32_gpsu_err,\n\t\t\twb32_pmic_err,\n\t\t\twb32_edidslvscope_err,\n\t\t\twb32_flashcfg_err\n\t\t})\n\t\t);\n\n\t// End of bus logic for wb32\n\t// }}}\n\t//\n\t// BUS-LOGIC for wbu\n\t// {{{\n\t//\n\t// No class SINGLE peripherals on the \"wbu\" bus\n\t//\n\n\t//\n\t// No class DOUBLE peripherals on the \"wbu\" bus\n\t//\n\n\t// info: @ERROR.WIRE for wbu_arbiter matches the buses error name, wbu_wbu_arbiter_err\n\tassign\twbu_zip_err= 1'b0;\n\t//\n\t// Connect the wbu bus components together using the wbxbar()\n\t//\n\t//\n\twbxbar #(\n\t\t.NM(1), .NS(2), .AW(30), .DW(32),\n\t\t.SLAVE_ADDR({\n\t\t\t// Address width    = 30\n\t\t\t// Address LSBs     = 2\n\t\t\t{ 30'h20000000 }, //         zip: 0x80000000\n\t\t\t{ 30'h00000000 }  // wbu_arbiter: 0x00000000\n\t\t}),\n\t\t.SLAVE_MASK({\n\t\t\t// Address width    = 30\n\t\t\t// Address LSBs     = 2\n\t\t\t{ 30'h38000000 }, //         zip\n\t\t\t{ 30'h20000000 }  // wbu_arbiter\n\t\t}),\n\t\t.OPT_DBLBUFFER(1'b1))\n\twbu_xbar(\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t.i_mcyc({\n\t\t\twbu_cyc\n\t\t}),\n\t\t.i_mstb({\n\t\t\twbu_stb\n\t\t}),\n\t\t.i_mwe({\n\t\t\twbu_we\n\t\t}),\n\t\t.i_maddr({\n\t\t\twbu_addr\n\t\t}),\n\t\t.i_mdata({\n\t\t\twbu_data\n\t\t}),\n\t\t.i_msel({\n\t\t\twbu_sel\n\t\t}),\n\t\t.o_mstall({\n\t\t\twbu_stall\n\t\t}),\n\t\t.o_mack({\n\t\t\twbu_ack\n\t\t}),\n\t\t.o_mdata({\n\t\t\twbu_idata\n\t\t}),\n\t\t.o_merr({\n\t\t\twbu_err\n\t\t}),\n\t\t// Slave connections\n\t\t.o_scyc({\n\t\t\twbu_zip_cyc,\n\t\t\twbu_wbu_arbiter_cyc\n\t\t}),\n\t\t.o_sstb({\n\t\t\twbu_zip_stb,\n\t\t\twbu_wbu_arbiter_stb\n\t\t}),\n\t\t.o_swe({\n\t\t\twbu_zip_we,\n\t\t\twbu_wbu_arbiter_we\n\t\t}),\n\t\t.o_saddr({\n\t\t\twbu_zip_addr,\n\t\t\twbu_wbu_arbiter_addr\n\t\t}),\n\t\t.o_sdata({\n\t\t\twbu_zip_data,\n\t\t\twbu_wbu_arbiter_data\n\t\t}),\n\t\t.o_ssel({\n\t\t\twbu_zip_sel,\n\t\t\twbu_wbu_arbiter_sel\n\t\t}),\n\t\t.i_sstall({\n\t\t\twbu_zip_stall,\n\t\t\twbu_wbu_arbiter_stall\n\t\t}),\n\t\t.i_sack({\n\t\t\twbu_zip_ack,\n\t\t\twbu_wbu_arbiter_ack\n\t\t}),\n\t\t.i_sdata({\n\t\t\twbu_zip_idata,\n\t\t\twbu_wbu_arbiter_idata\n\t\t}),\n\t\t.i_serr({\n\t\t\twbu_zip_err,\n\t\t\twbu_wbu_arbiter_err\n\t\t})\n\t\t);\n\n\t// End of bus logic for wbu\n\t// }}}\n\t// }}}\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// Declare the interrupt busses\n\t// {{{\n\t// Interrupt busses are defined by anything with a @PIC tag.\n\t// The @PIC.BUS tag defines the name of the wire bus below,\n\t// while the @PIC.MAX tag determines the size of the bus width.\n\t//\n\t// For your peripheral to be assigned to this bus, it must have an\n\t// @INT.NAME.WIRE= tag to define the wire name of the interrupt line,\n\t// and an @INT.NAME.PIC= tag matching the @PIC.BUS tag of the bus\n\t// your interrupt will be assigned to.  If an @INT.NAME.ID tag also\n\t// exists, then your interrupt will be assigned to the position given\n\t// by the ID# in that tag.\n\t//\n\tassign\tsys_int_vector = {\n\t\tpmic_int,\n\t\toled_int,\n\t\tgck_pps,\n\t\tsdio_int,\n\t\tgpio_int,\n\t\thdmi_int,\n\t\tedid_int,\n\t\ti2c_int,\n\t\tw_bus_int,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0\n\t};\n\tassign\talt_int_vector = {\n\t\t1'b0,\n\t\trtc_int,\n\t\tedidslvscope_int,\n\t\tgpsutxf_int,\n\t\tgpsurxf_int,\n\t\tgpsutx_int,\n\t\tgpsurx_int,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0\n\t};\n\tassign\tbus_int_vector = {\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\t1'b0,\n\t\tspio_int\n\t};\n\t// }}}\n\t////////////////////////////////////////////////////////////////////////\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// @MAIN.INSERT and @MAIN.ALT\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t//\n\t// Now we turn to defining all of the parts and pieces of what\n\t// each of the various peripherals does, and what logic it needs.\n\t//\n\t// This information comes from the @MAIN.INSERT and @MAIN.ALT tags.\n\t// If an @ACCESS tag is available, an ifdef is created to handle\n\t// having the access and not.  If the @ACCESS tag is `defined above\n\t// then the @MAIN.INSERT code is executed.  If not, the @MAIN.ALT\n\t// code is exeucted, together with any other cleanup settings that\n\t// might need to take place--such as returning zeros to the bus,\n\t// or making sure all of the various interrupt wires are set to\n\t// zero if the component is not included.\n\t//\n`ifdef\tFLASH_ACCESS\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// Flash controller\n\t// {{{\n\tqflexpress #(\n\t\t// {{{\n\t\t.LGFLASHSZ(24), .OPT_CLKDIV(1),\n\t\t.OPT_ENDIANSWAP(0),\n\t\t.NDUMMY(6), .RDDELAY(2),\n\t\t.OPT_STARTUP_FILE(\"spansion.hex\"),\n`ifdef\tFLASHCFG_ACCESS\n\t\t.OPT_CFG(1'b1)\n`else\n\t\t.OPT_CFG(1'b0)\n`endif\n\t\t// }}}\n\t) u_flash (\n\t\t// {{{\n\t\t.i_clk(i_clk),\n\t\t.i_reset(i_reset),\n\t\t// Primary memory reading inputs\n\t\t.i_wb_cyc(wbflash_flash_cyc), .i_wb_stb(wbflash_flash_stb), .i_wb_we(wbflash_flash_we),\n\t\t\t.i_wb_addr(wbflash_flash_addr[22-1:0]),\n\t\t\t.i_wb_data(wbflash_flash_data), // 32 bits wide\n\t\t\t.i_wb_sel(wbflash_flash_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wbflash_flash_stall),.o_wb_ack(wbflash_flash_ack), .o_wb_data(wbflash_flash_idata),\n\t\t// Configuration bus ports\n\t\t.i_cfg_cyc(wb32_flashcfg_cyc), .i_cfg_stb(wb32_flashcfg_stb), .i_cfg_we(wb32_flashcfg_we),\n\t\t\t.i_cfg_data(wb32_flashcfg_data), // 32 bits wide\n\t\t\t.i_cfg_sel(wb32_flashcfg_sel),  // 32/8 bits wide\n\t\t.o_cfg_stall(wb32_flashcfg_stall),.o_cfg_ack(wb32_flashcfg_ack), .o_cfg_data(wb32_flashcfg_idata),\n\t\t.o_qspi_sck(o_flash_sck),\n\t\t.o_qspi_cs_n(o_flash_cs_n),\n\t\t.o_qspi_mod(o_flash_mod),\n\t\t.o_qspi_dat(o_flash_dat),\n\t\t.i_qspi_dat(i_flash_dat),\n\t\t.o_dbg_trigger(flash_dbg_trigger),\n\t\t.o_debug(flash_debug)\n\t\t// }}}\n\t);\n\t// }}}\n\t// }}}\n`else\t// FLASH_ACCESS\n\t// {{{\n\tassign\to_flash_sck  = 1'b1;\n\tassign\to_flash_cs_n = 1'b1;\n\tassign\to_flash_mod  = 2'b01;\n\tassign\to_flash_dat  = 4'b1111;\n\t// Verilator lint_off UNUSED\n\twire\tflash_unused = &{ 1'b0, i_flash_dat };\n\t// Verilator lint_on UNUSED\n\t// Null bus slave\n\t// {{{\n\n\t//\n\t// In the case that there is no wbflash_flash peripheral\n\t// responding on the wbflash bus\n\tassign\twbflash_flash_ack   = 1'b0;\n\tassign\twbflash_flash_err   = (wbflash_flash_stb);\n\tassign\twbflash_flash_stall = 0;\n\tassign\twbflash_flash_idata = 0;\n\n\t// }}}\n\t// }}}\n`endif\t// FLASH_ACCESS\n\n`ifdef\tI2CCPU_ACCESS\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// The I2C Controller\n\t// {{{\n\n\twbi2ccpu #(\n\t\t.ADDRESS_WIDTH(27),\n\t\t.DATA_WIDTH(128),\n\t\t.AXIS_ID_WIDTH(2)\n\t) u_i2c (\n\t\t// {{{\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t.i_wb_cyc(wb32_i2cs_cyc), .i_wb_stb(wb32_i2cs_stb), .i_wb_we(wb32_i2cs_we),\n\t\t\t.i_wb_addr(wb32_i2cs_addr[2-1:0]),\n\t\t\t.i_wb_data(wb32_i2cs_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_i2cs_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_i2cs_stall),.o_wb_ack(wb32_i2cs_ack), .o_wb_data(wb32_i2cs_idata),\n\t\t.o_pf_cyc(wbwide_i2cm_cyc), .o_pf_stb(wbwide_i2cm_stb), .o_pf_we(wbwide_i2cm_we),\n\t\t\t.o_pf_addr(wbwide_i2cm_addr[27-1:0]),\n\t\t\t.o_pf_data(wbwide_i2cm_data), // 128 bits wide\n\t\t\t.o_pf_sel(wbwide_i2cm_sel),  // 128/8 bits wide\n\t\t.i_pf_stall(wbwide_i2cm_stall), .i_pf_ack(wbwide_i2cm_ack), .i_pf_data(wbwide_i2cm_idata), .i_pf_err(wbwide_i2cm_err),\n\t\t.i_i2c_sda(i_i2c_sda), .i_i2c_scl(i_i2c_scl),\n\t\t.o_i2c_sda(o_i2c_sda), .o_i2c_scl(o_i2c_scl),\n\t\t.M_AXIS_TVALID(i2c_valid), .M_AXIS_TREADY(i2c_ready),\n\t\t\t.M_AXIS_TDATA(i2c_data), .M_AXIS_TLAST(i2c_last),\n\t\t\t.M_AXIS_TID(i2c_id),\n\t\t.i_sync_signal(rtc_pps),\n\t\t//\n\t\t.o_interrupt(i2c_int),\n\t\t.o_debug(i2c_debug)\n\t\t// }}}\n\t);\n\n\tassign\ti2c_ready = (!i2c_valid) || (1'b0\n\t\t\t|| (i2c_id == 0)\t\t// NULL address\n\t\t\t|| (i2c_id == 1)\n`ifdef\tI2CDMA_ACCESS\n\t\t\t|| (i2c_id == 2 && i2cdma_ready)\n`else\n\t\t\t|| (i2c_id == 2)\n`endif\n\t\t\t|| (i2c_id > 2));\n\n\t// }}}\n\t// }}}\n`else\t// I2CCPU_ACCESS\n\t// {{{\n\tassign\to_i2c_scl = 1'b1;\n\tassign\to_i2c_sda = 1'b1;\n\t// Null bus master\n\t// {{{\n\t// }}}\n\t// Null interrupt definitions\n\t// {{{\n\tassign\ti2c_int = 1'b0;\t// i2c.INT.I2C.WIRE\n\t// }}}\n\t// }}}\n`endif\t// I2CCPU_ACCESS\n\n\talways @(posedge i_clk)\n\tif (wbwide_zip_err)\n\tbegin\n\t\tr_buserr_addr <= 0;\n\t\tr_buserr_addr[27-1:0] <= wbwide_zip_addr[27-1:0];\n\tend else if (wbu_err)\n\tbegin\n\t\tr_buserr_addr <= 0;\n\t\tr_buserr_addr[30-1:0] <= wbu_addr[30-1:0];\n\tend\n\tassign\twb32_buserr_stall= 1'b0;\n\tassign\twb32_buserr_ack  = wb32_buserr_stb;\n\tassign\twb32_buserr_idata = { {(30-30){1'b0}},\n\t\t\tr_buserr_addr, 2'b00 };\n`ifdef\tGPSTRK_ACCESS\n\tassign\twb32_subseconds_idata = gps_now[31:0];\n`else\n\talways @(posedge i_clk)\n\tif (wb32_subseconds_stb && wb32_subseconds_we)\n\t\tr_subseconds_data <= wb32_subseconds_data;\n\telse\n\t\tr_subseconds_data <= r_subseconds_data\n\t\t\t+ { 16'h0, RTC_CLKSTEP[31:16] };\n\n\tassign\twb32_subseconds_idata = r_subseconds_data;\n`endif\n`ifdef\tADCCLK\n\t// {{{\n\tclkcounter #(\n\t\t.CLOCKFREQ_HZ(0)\t// We'll count PPS externally\n\t) clkadcclkctr(\n\t\t.i_sys_clk(i_clk),\n\t\t.i_tst_clk(i_clk_200mhz),\n\t\t.i_sys_pps(rtc_pps),\n\t\t.o_sys_counts(wb32_adcclk_idata)\n\t);\n\n\tinitial\tr_adcclk_ack = 0;\n\talways @(posedge i_clk)\n\t\tr_adcclk_ack <= !i_reset && wb32_adcclk_stb;\n\tassign\twb32_adcclk_ack   = r_adcclk_ack;\n\tassign\twb32_adcclk_stall = 1'b0;\n\t// }}}\n`else\t// ADCCLK\n\t// {{{\n\t// }}}\n`endif\t// ADCCLK\n\n`ifdef\tEXBUS_MASTER\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// EXBUS: USB-UART driven bus master and console\n\t// {{{\n\t// The Host USB interface, to be used by the WB-UART bus\n\trxuartlite\t#(\n\t\t// {{{\n\t\t.TIMER_BITS(DBGBUSBITS),\n\t\t.CLOCKS_PER_BAUD(BUSUART[DBGBUSBITS-1:0])\n\t\t// }}}\n\t) rcv(\n\t\t// {{{\n\t\t.i_clk(      i_clk),\n\t\t.i_uart_rx(i_wbu_uart_rx),\n\t\t.o_wr(       wbu_rx_stb),\n\t\t.o_data(     wbu_rx_data)\n\t\t// }}}\n\t);\n\n\ttxuartlite\t#(\n\t\t// {{{\n\t\t.TIMING_BITS(DBGBUSBITS[4:0]),\n\t\t.CLOCKS_PER_BAUD(BUSUART[DBGBUSBITS-1:0])\n\t\t// }}}\n\t) txv(\n\t\t// {{{\n\t\t.i_clk(    i_clk),\n\t\t.i_wr(     wbu_tx_stb),\n\t\t.i_data(   wbu_tx_data),\n\t\t.o_uart_tx(o_wbu_uart_tx),\n\t\t.o_busy(   wbu_tx_busy)\n\t\t// }}}\n\t);\n\n`ifndef\tBUSPIC_ACCESS\n\twire\tw_bus_int;\n\tassign\tw_bus_int = 1'b0;\n`endif\n\t// Verilator lint_off UNUSED\n\twire\t[29:0]\twbu_tmp_addr;\n\t// Verilator lint_on  UNUSED\n\texbuswb #(\n\t\t// {{{\n\t\t// .LGWATCHDOG(DBGBUSWATCHDOG)\n\t\t.ADDRESS_WIDTH(30)\n\t\t// }}}\n\t) u_exbus(\n\t\t// {{{\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t.o_reset(ex_reset),\n\t\t.i_rx_stb(wbu_rx_stb), .i_rx_byte(wbu_rx_data),\n\t\t.o_tx_stb(wbu_tx_stb), .o_tx_byte(wbu_tx_data),\n\t\t\t.i_tx_busy(wbu_tx_busy),\n\t\t//\n\t\t.i_gpio(2'b00), .o_gpio(ex_gpio),\n\t\t//\n\t\t.i_console_stb(w_console_tx_stb),\n\t\t\t.i_console_byte(w_console_tx_data),\n\t\t\t.o_console_busy(w_console_busy),\n\t\t.o_console_stb(w_console_rx_stb),\n\t\t\t.o_console_byte(w_console_rx_data),\n\t\t//\n\t\t.o_wb_cyc(wbu_cyc), .o_wb_stb(wbu_stb),\n\t\t\t.o_wb_we(wbu_we),\n\t\t\t.o_wb_addr(wbu_addr),\n\t\t\t.o_wb_data(wbu_data),\n\t\t\t.o_wb_sel(wbu_sel),\n\t\t.i_wb_stall(wbu_stall),\n\t\t\t.i_wb_ack(wbu_ack),\n\t\t.i_wb_data(wbu_idata),\n\t\t.i_wb_err(wbu_err),\n\t\t.i_interrupt(w_bus_int)\n\t\t// }}}\n\t);\n\t// }}}\n\t// }}}\n`else\t// EXBUS_MASTER\n\t// {{{\n\t// Null bus master\n\t// {{{\n\t// }}}\n\t// }}}\n`endif\t// EXBUS_MASTER\n\n`ifdef\tFLASHCFG_ACCESS\n\t// {{{\n\t// The Flash control interface is defined by the flash instantiation\n\t// hence we don't need to do anything to define it here.\n\t// }}}\n`else\t// FLASHCFG_ACCESS\n\t// {{{\n\t// Null bus slave\n\t// {{{\n\n\t//\n\t// In the case that there is no wb32_flashcfg peripheral\n\t// responding on the wb32 bus\n\tassign\twb32_flashcfg_ack   = 1'b0;\n\tassign\twb32_flashcfg_err   = (wb32_flashcfg_stb);\n\tassign\twb32_flashcfg_stall = 0;\n\tassign\twb32_flashcfg_idata = 0;\n\n\t// }}}\n\t// }}}\n`endif\t// FLASHCFG_ACCESS\n\n`ifdef\tEDID_ACCESS\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// The EDID I2C Controller\n\t// {{{\n\n\twbi2ccpu #(\n\t\t.ADDRESS_WIDTH(27),\n\t\t.DATA_WIDTH(128),\n\t\t.AXIS_ID_WIDTH(2)\n\t) u_edid (\n\t\t// {{{\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t.i_wb_cyc(wb32_edids_cyc), .i_wb_stb(wb32_edids_stb), .i_wb_we(wb32_edids_we),\n\t\t\t.i_wb_addr(wb32_edids_addr[2-1:0]),\n\t\t\t.i_wb_data(wb32_edids_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_edids_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_edids_stall),.o_wb_ack(wb32_edids_ack), .o_wb_data(wb32_edids_idata),\n\t\t.o_pf_cyc(wbwide_edidm_cyc), .o_pf_stb(wbwide_edidm_stb), .o_pf_we(wbwide_edidm_we),\n\t\t\t.o_pf_addr(wbwide_edidm_addr[27-1:0]),\n\t\t\t.o_pf_data(wbwide_edidm_data), // 128 bits wide\n\t\t\t.o_pf_sel(wbwide_edidm_sel),  // 128/8 bits wide\n\t\t.i_pf_stall(wbwide_edidm_stall), .i_pf_ack(wbwide_edidm_ack), .i_pf_data(wbwide_edidm_idata), .i_pf_err(wbwide_edidm_err),\n\t\t.i_i2c_sda(i_edid_sda), .i_i2c_scl(i_edid_scl),\n\t\t.o_i2c_sda(o_edid_sda), .o_i2c_scl(o_edid_scl),\n\t\t.M_AXIS_TVALID(edid_valid), .M_AXIS_TREADY(edid_ready),\n\t\t\t.M_AXIS_TDATA(edid_data), .M_AXIS_TLAST(edid_last),\n\t\t\t.M_AXIS_TID(edid_id),\n\t\t.i_sync_signal(rtc_pps),\n\t\t//\n\t\t.o_interrupt(edid_int),\n\t\t.o_debug(edid_debug)\n\t\t// }}}\n\t);\n\n\t// }}}\n\t// }}}\n`else\t// EDID_ACCESS\n\t// {{{\n\tassign\to_edid_scl = 1'b1;\n\tassign\to_edid_sda = 1'b1;\n\t// Null bus master\n\t// {{{\n\t// }}}\n\t// Null interrupt definitions\n\t// {{{\n\tassign\tedid_int = 1'b0;\t// edid.INT.EDID.WIRE\n\t// }}}\n\t// }}}\n`endif\t// EDID_ACCESS\n\n`ifdef\tGPSUART_ACCESS\n\t// {{{\n\twbuart #(\n\t\t.INITIAL_SETUP(31'h000028b0)\n\t) u_gpsu_uart(\n\t\ti_clk, 1'b0,\n\t\twb32_gpsu_cyc, wb32_gpsu_stb, wb32_gpsu_we,\n\t\t\twb32_gpsu_addr[2-1:0],\n\t\t\twb32_gpsu_data, // 32 bits wide\n\t\t\twb32_gpsu_sel,  // 32/8 bits wide\n\t\twb32_gpsu_stall, wb32_gpsu_ack, wb32_gpsu_idata,\n\t\ti_gpsu_rx, o_gpsu_tx, w_gpsu_cts_n, w_gpsu_rts_n,\n\t\tgpsurx_int, gpsutx_int,\n\t\tgpsurxf_int, gpsutxf_int\n\t);\n\t// }}}\n`else\t// GPSUART_ACCESS\n\t// {{{\n\tassign\to_gpsu_tx    = 1'b1;\n\tassign\tw_gpsu_rts_n = 1'b0;\n\t// Null bus slave\n\t// {{{\n\n\t//\n\t// In the case that there is no wb32_gpsu peripheral\n\t// responding on the wb32 bus\n\tassign\twb32_gpsu_ack   = 1'b0;\n\tassign\twb32_gpsu_err   = (wb32_gpsu_stb);\n\tassign\twb32_gpsu_stall = 0;\n\tassign\twb32_gpsu_idata = 0;\n\n\t// }}}\n\t// Null interrupt definitions\n\t// {{{\n\tassign\tgpsurxf_int = 1'b0;\t// gpsu.INT.GPSRXF.WIRE\n\tassign\tgpsutxf_int = 1'b0;\t// gpsu.INT.GPSTXF.WIRE\n\tassign\tgpsutx_int = 1'b0;\t// gpsu.INT.GPSTX.WIRE\n\tassign\tgpsurx_int = 1'b0;\t// gpsu.INT.GPSRX.WIRE\n\t// }}}\n\t// }}}\n`endif\t// GPSUART_ACCESS\n\n`ifdef\tVIDPIPE_ACCESS\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// HDMI Video processing pipeline\n\t// {{{\n`ifdef\tVERILATOR\n\tassign\ti_hdmiclk = i_pixclk;\n`endif\n\n\tvidpipe #(\n\t\t.AW(27),\n\t\t.DW(128)\n\t) u_hdmi (\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t.i_wb_cyc(wb32_hdmi_cyc), .i_wb_stb(wb32_hdmi_stb), .i_wb_we(wb32_hdmi_we),\n\t\t\t.i_wb_addr(wb32_hdmi_addr[10-1:0]),\n\t\t\t.i_wb_data(wb32_hdmi_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_hdmi_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_hdmi_stall),.o_wb_ack(wb32_hdmi_ack), .o_wb_data(wb32_hdmi_idata),\n\t\t.i_hdmiclk(i_hdmiclk),\n\t\t.i_altclk(i_pixclk),\n\t\t.i_pixclk(i_pixclk),\n\t\t.i_hdmi_red(i_hdmi_red), .i_hdmi_grn(i_hdmi_grn),\n\t\t\t\t.i_hdmi_blu(i_hdmi_blu),\n\t\t.o_dma_cyc(wbwide_hdmi_cyc), .o_dma_stb(wbwide_hdmi_stb), .o_dma_we(wbwide_hdmi_we),\n\t\t\t.o_dma_addr(wbwide_hdmi_addr[27-1:0]),\n\t\t\t.o_dma_data(wbwide_hdmi_data), // 128 bits wide\n\t\t\t.o_dma_sel(wbwide_hdmi_sel),  // 128/8 bits wide\n\t\t.i_dma_stall(wbwide_hdmi_stall), .i_dma_ack(wbwide_hdmi_ack), .i_dma_data(wbwide_hdmi_idata), .i_dma_err(wbwide_hdmi_err),\n\t\t.o_hdmi_red(o_hdmi_red), .o_hdmi_grn(o_hdmi_grn),\n\t\t\t\t.o_hdmi_blu(o_hdmi_blu),\n\t\t.o_pix_reset_n(o_pix_reset_n),\n\t\t.i_pxpll_locked(i_pxpll_locked),\n\t\t.o_hdmirx_reset_n(o_hdmirx_reset_n),\n\t\t.o_pxclk_sel(o_pxclk_cksel),\n\t\t.o_iodelay(o_hdmi_iodelay),\n\t\t.i_iodelay(i_hdmi_iodelay),\n\t\t.o_interrupt(hdmi_int),\n\t\t//\n\t\t.o_dbg_ce(hdmidbg_ce),\n\t\t.o_dbg_trigger(hdmidbg_trigger),\n\t\t.o_pixdebug(hdmiclr_debug)\n\t);\n\n\t// }}}\n\t// }}}\n`else\t// VIDPIPE_ACCESS\n\t// {{{\n\t// Null bus master\n\t// {{{\n\t// }}}\n\t// Null bus slave\n\t// {{{\n\n\t//\n\t// In the case that there is no wb32_hdmi peripheral\n\t// responding on the wb32 bus\n\tassign\twb32_hdmi_ack   = 1'b0;\n\tassign\twb32_hdmi_err   = (wb32_hdmi_stb);\n\tassign\twb32_hdmi_stall = 0;\n\tassign\twb32_hdmi_idata = 0;\n\n\t// }}}\n\t// Null interrupt definitions\n\t// {{{\n\tassign\thdmi_int = 1'b0;\t// hdmi.INT.VIDFRAME.WIRE\n\t// }}}\n\t// }}}\n`endif\t// VIDPIPE_ACCESS\n\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// EDIDRX\n\t// {{{\n\twbi2cslave #(\n\t\t.AXIS_SUPPORT(1'b1),\n\t\t.SLAVE_ADDRESS(7'h50)\n\t) u_edidslv (\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t.i_wb_cyc(wb32_edidslv_cyc), .i_wb_stb(wb32_edidslv_stb), .i_wb_we(wb32_edidslv_we),\n\t\t\t.i_wb_addr(wb32_edidslv_addr[6-1:0]),\n\t\t\t.i_wb_data(wb32_edidslv_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_edidslv_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_edidslv_stall),.o_wb_ack(wb32_edidslv_ack), .o_wb_data(wb32_edidslv_idata),\n\t\t.s_valid(edid_valid), .s_ready(edid_ready),\n\t\t\t.s_data(edid_data), .s_last(edid_last),\n\t\t.i_i2c_scl(i_edidslv_scl), .i_i2c_sda(i_edidslv_sda),\n\t\t.o_i2c_scl(o_edidslv_scl), .o_i2c_sda(o_edidslv_sda),\n\t\t.o_dbg(edidslv_dbg)\n\t);\n\t// }}}\n\n`ifdef\tEDIDSLVSCOPE_SCOPC\n\t// {{{\n\twbscopc #(\n\t\t// {{{\n\t\t.LGMEM(13),\n\t\t.SYNCHRONOUS(1),\n\t\t.DEFAULT_HOLDOFF(0)\n\t\t// }}}\n\t) u_edidslvscope (\n\t\t// {{{\n\t\t.i_data_clk(i_clk), .i_ce(1'b1),\n\t\t.i_trigger(edidslv_dbg[31]), .i_data(edidslv_dbg[30:0]),\n\t\t.i_wb_clk(i_clk),\n\t\t.i_wb_cyc(wb32_edidslvscope_cyc), .i_wb_stb(wb32_edidslvscope_stb), .i_wb_we(wb32_edidslvscope_we),\n\t\t\t.i_wb_addr(wb32_edidslvscope_addr[1-1:0]),\n\t\t\t.i_wb_data(wb32_edidslvscope_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_edidslvscope_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_edidslvscope_stall),.o_wb_ack(wb32_edidslvscope_ack), .o_wb_data(wb32_edidslvscope_idata),\n\t\t.o_interrupt(edidslvscope_int)\n\t\t// }}}\n\t);\n\t// }}}\n`else\t// EDIDSLVSCOPE_SCOPC\n\t// {{{\n\t// Null bus slave\n\t// {{{\n\n\t//\n\t// In the case that there is no wb32_edidslvscope peripheral\n\t// responding on the wb32 bus\n\tassign\twb32_edidslvscope_ack   = 1'b0;\n\tassign\twb32_edidslvscope_err   = (wb32_edidslvscope_stb);\n\tassign\twb32_edidslvscope_stall = 0;\n\tassign\twb32_edidslvscope_idata = 0;\n\n\t// }}}\n\t// Null interrupt definitions\n\t// {{{\n\tassign\tedidslvscope_int = 1'b0;\t// edidslvscope.INT.EDIDSLVSCOPE.WIRE\n\t// }}}\n\t// }}}\n`endif\t// EDIDSLVSCOPE_SCOPC\n\n\twbdown #(\n\t\t// {{{\n\t\t// Slave bus address width: 27\n\t\t// Slave address width    : 21\n\t\t// Master address width   : 23\n\t\t.ADDRESS_WIDTH(21+$clog2(128/8)),\n\t\t.WIDE_DW(128),\n\t\t.SMALL_DW(32),\n\t\t.OPT_LITTLE_ENDIAN(1'b0),\n\t\t.OPT_LOWLOGIC(1'b0)\n\t\t// }}}\n\t) u_crossflash (\n\t\t// {{{\n\t\t.i_clk(i_clk),\n\t\t.i_reset(i_reset),\n\t\t// Slave/incoming\n\t\t// {{{\n\t\t.i_wcyc(  wbwide_crossflash_cyc),\n\t\t.i_wstb(  wbwide_crossflash_stb),\n\t\t.i_wwe(   wbwide_crossflash_we),\n\t\t.i_waddr( wbwide_crossflash_addr[21-1:0]),\n\t\t.i_wdata( wbwide_crossflash_data),\n\t\t.i_wsel(  wbwide_crossflash_sel),\n\t\t.o_wstall(wbwide_crossflash_stall),\n\t\t.o_wack(  wbwide_crossflash_ack),\n\t\t.o_wdata( wbwide_crossflash_idata),\n\t\t.o_werr(  wbwide_crossflash_err),\n\t\t// }}}\n\t\t// Master/down-range/outgoing\n\t\t// {{{\n\t\t.o_scyc(  wbflash_crossflash_cyc),\n\t\t.o_sstb(  wbflash_crossflash_stb),\n\t\t.o_swe(   wbflash_crossflash_we),\n\t\t.o_saddr( wbflash_crossflash_addr[23-1:0]),\n\t\t.o_sdata( wbflash_crossflash_data),\n\t\t.o_ssel(  wbflash_crossflash_sel),\n\t\t.i_sstall(wbflash_crossflash_stall),\n\t\t.i_sack(  wbflash_crossflash_ack),\n\t\t.i_sdata( wbflash_crossflash_idata),\n\t\t.i_serr(  wbflash_crossflash_err)\n\t\t// }}}\n\t\t// }}}\n\t);\n`ifdef\tCFG_ACCESS\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// ICAPE2 driver/controller\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t//\n`ifdef\tVERILATOR\n\treg\tr_icape_ack;\n\n\tinitial\tr_icape_ack = 1'b0;\n\talways @(posedge i_clk)\n\t\tr_icape_ack <= wb32_icape_stb;\n\tassign\twb32_icape_ack   = r_icape_ack;\n\tassign\twb32_icape_stall = 1'b0;\n\tassign\twb32_icape_idata = 32'h00;\n`else\n\twbicapetwo #(\n\t\t.LGDIV(ICAPE_LGDIV)\n\t) u_icape (\n\t\t// {{{\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t.i_wb_cyc(wb32_icape_cyc), .i_wb_stb(wb32_icape_stb), .i_wb_we(wb32_icape_we),\n\t\t\t.i_wb_addr(wb32_icape_addr[5-1:0]),\n\t\t\t.i_wb_data(wb32_icape_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_icape_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_icape_stall),.o_wb_ack(wb32_icape_ack), .o_wb_data(wb32_icape_idata)\n\t\t// }}}\n\t);\n`endif\n\t// }}}\n\t// }}}\n`else\t// CFG_ACCESS\n\t// {{{\n\t// Null bus slave\n\t// {{{\n\n\t//\n\t// In the case that there is no wb32_icape peripheral\n\t// responding on the wb32 bus\n\tassign\twb32_icape_ack   = 1'b0;\n\tassign\twb32_icape_err   = (wb32_icape_stb);\n\tassign\twb32_icape_stall = 0;\n\tassign\twb32_icape_idata = 0;\n\n\t// }}}\n\t// }}}\n`endif\t// CFG_ACCESS\n\n`ifdef\tTXCLK\n\t// {{{\n\tclkcounter #(\n\t\t.CLOCKFREQ_HZ(0)\t// We'll count PPS externally\n\t) clktxclkctr(\n\t\t.i_sys_clk(i_clk),\n\t\t.i_tst_clk(i_net_tx_clk),\n\t\t.i_sys_pps(rtc_pps),\n\t\t.o_sys_counts(wb32_txclk_idata)\n\t);\n\n\tinitial\tr_txclk_ack = 0;\n\talways @(posedge i_clk)\n\t\tr_txclk_ack <= !i_reset && wb32_txclk_stb;\n\tassign\twb32_txclk_ack   = r_txclk_ack;\n\tassign\twb32_txclk_stall = 1'b0;\n\t// }}}\n`else\t// TXCLK\n\t// {{{\n\t// }}}\n`endif\t// TXCLK\n\n`ifdef\tRXETH0CK\n\t// {{{\n\tclkcounter #(\n\t\t.CLOCKFREQ_HZ(0)\t// We'll count PPS externally\n\t) clkrxeth0ckctr(\n\t\t.i_sys_clk(i_clk),\n\t\t.i_tst_clk(i_eth0_rx_clk),\n\t\t.i_sys_pps(rtc_pps),\n\t\t.o_sys_counts(wb32_rxeth0ck_idata)\n\t);\n\n\tinitial\tr_rxeth0ck_ack = 0;\n\talways @(posedge i_clk)\n\t\tr_rxeth0ck_ack <= !i_reset && wb32_rxeth0ck_stb;\n\tassign\twb32_rxeth0ck_ack   = r_rxeth0ck_ack;\n\tassign\twb32_rxeth0ck_stall = 1'b0;\n\t// }}}\n`else\t// RXETH0CK\n\t// {{{\n\t// }}}\n`endif\t// RXETH0CK\n\n\tinitial\trtc_pps = 1'b0;\n\tinitial\trtc_pps_counter = 0;\n\talways @(posedge i_clk)\n\tif (rtc_pps_counter > 0)\n\tbegin\n\t\trtc_pps_counter <= rtc_pps_counter - 1;\n\t\trtc_pps <= 1'b0;\n\tend else begin\n\t\trtc_pps_counter <= 27'd100_000_000 - 1;\n\t\trtc_pps <= 1'b1;\n\tend\n`ifdef\tBKRAM_ACCESS\n\t// {{{\n\tmemdev #(\n\t\t.LGMEMSZ(20),\n\t\t.DW(128),\n\t\t.EXTRACLOCK(1)\n\t) u_bkram (\n\t\t.i_clk(i_clk),\n\t\t.i_reset(i_reset),\n\t\t.i_wb_cyc(wbwide_bkram_cyc), .i_wb_stb(wbwide_bkram_stb), .i_wb_we(wbwide_bkram_we),\n\t\t\t.i_wb_addr(wbwide_bkram_addr[16-1:0]),\n\t\t\t.i_wb_data(wbwide_bkram_data), // 128 bits wide\n\t\t\t.i_wb_sel(wbwide_bkram_sel),  // 128/8 bits wide\n\t\t.o_wb_stall(wbwide_bkram_stall),.o_wb_ack(wbwide_bkram_ack), .o_wb_data(wbwide_bkram_idata)\n\t);\n\t// }}}\n`else\t// BKRAM_ACCESS\n\t// {{{\n\t// Null bus slave\n\t// {{{\n\n\t//\n\t// In the case that there is no wbwide_bkram peripheral\n\t// responding on the wbwide bus\n\tassign\twbwide_bkram_ack   = 1'b0;\n\tassign\twbwide_bkram_err   = (wbwide_bkram_stb);\n\tassign\twbwide_bkram_stall = 0;\n\tassign\twbwide_bkram_idata = 0;\n\n\t// }}}\n\t// }}}\n`endif\t// BKRAM_ACCESS\n\n\twbdown #(\n\t\t// {{{\n\t\t// Slave bus address width: 27\n\t\t// Slave address width    : 10\n\t\t// Master address width   : 12\n\t\t.ADDRESS_WIDTH(10+$clog2(128/8)),\n\t\t.WIDE_DW(128),\n\t\t.SMALL_DW(32),\n\t\t.OPT_LITTLE_ENDIAN(1'b0),\n\t\t.OPT_LOWLOGIC(1'b0)\n\t\t// }}}\n\t) u_crossbus (\n\t\t// {{{\n\t\t.i_clk(i_clk),\n\t\t.i_reset(i_reset),\n\t\t// Slave/incoming\n\t\t// {{{\n\t\t.i_wcyc(  wbwide_crossbus_cyc),\n\t\t.i_wstb(  wbwide_crossbus_stb),\n\t\t.i_wwe(   wbwide_crossbus_we),\n\t\t.i_waddr( wbwide_crossbus_addr[10-1:0]),\n\t\t.i_wdata( wbwide_crossbus_data),\n\t\t.i_wsel(  wbwide_crossbus_sel),\n\t\t.o_wstall(wbwide_crossbus_stall),\n\t\t.o_wack(  wbwide_crossbus_ack),\n\t\t.o_wdata( wbwide_crossbus_idata),\n\t\t.o_werr(  wbwide_crossbus_err),\n\t\t// }}}\n\t\t// Master/down-range/outgoing\n\t\t// {{{\n\t\t.o_scyc(  wb32_crossbus_cyc),\n\t\t.o_sstb(  wb32_crossbus_stb),\n\t\t.o_swe(   wb32_crossbus_we),\n\t\t.o_saddr( wb32_crossbus_addr[12-1:0]),\n\t\t.o_sdata( wb32_crossbus_data),\n\t\t.o_ssel(  wb32_crossbus_sel),\n\t\t.i_sstall(wb32_crossbus_stall),\n\t\t.i_sack(  wb32_crossbus_ack),\n\t\t.i_sdata( wb32_crossbus_idata),\n\t\t.i_serr(  wb32_crossbus_err)\n\t\t// }}}\n\t\t// }}}\n\t);\n`ifdef\tSDRAM_ACCESS\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// DDR3 Controller instantiation\n\t// {{{\n           \n\tddr3_controller #(\n\t\t// {{{\n\t\t.CONTROLLER_CLK_PERIOD(SDRAMCONTROLLER_CLK_PERIOD), //ps, clock period of the controller interface\n\t\t.DDR3_CLK_PERIOD(DDR3_CLK_PERIOD), //ps, clock period of the DDR3 RAM device (must be 1/4 of the CONTROLLER_CLK_PERIOD) \n\t\t.ROW_BITS(SDRAMROW_BITS),\t//width of row address\n\t\t.COL_BITS(SDRAMCOL_BITS),\t//width of column address\n\t\t.BA_BITS(SDRAMBA_BITS),\t//width of bank address\n\t\t.DQ_BITS(SDRAMDQ_BITS),\t//width of DQ\n\t\t.LANES(SDRAMBYTE_LANES),\t\t// byte lanes\n\t\t.AUX_WIDTH(SDRAMAUX_WIDTH),\t//width of aux line (must be >= 4) \n\t\t.WB2_ADDR_BITS(7), \t\t//width of 2nd wishbone address bus \n            \t.WB2_DATA_BITS(32),  \t\t//width of 2nd wishbone data bus\n\t\t.MICRON_SIM(0),\t\t//simulation for micron ddr3 model (shorten POWER_ON_RESET_HIGH and INITIAL_CKE_LOW)\n\t\t.ODELAY_SUPPORTED(1),\t\t//set to 1 when ODELAYE2 is supported\n\t\t.SECOND_WISHBONE(1) \t\t//set to 1 if 2nd wishbone is needed \n\t\t// }}}\n\t) u_ddr3 (\n\t\t// {{{\n\t\t.i_controller_clk(i_clk), //i_controller_clk has period of CONTROLLER_CLK_PERIOD\n\t\t.i_rst_n(!i_reset), //200MHz input clock\n\t\t// Wishbone 1 (Controller)\n\t\t.i_wb_cyc(wbwide_ddr3_cyc), .i_wb_stb(wbwide_ddr3_stb), .i_wb_we(wbwide_ddr3_we),\n\t\t\t.i_wb_addr(wbwide_ddr3_addr[26-1:0]),\n\t\t\t.i_wb_data(wbwide_ddr3_data), // 128 bits wide\n\t\t\t.i_wb_sel(wbwide_ddr3_sel),  // 128/8 bits wide\n\t\t.o_wb_stall(wbwide_ddr3_stall),.o_wb_ack(wbwide_ddr3_ack), .o_wb_data(wbwide_ddr3_idata),\n\t\t.i_aux(0),\n\t\t.o_aux(ddr3_aux_out),\t// Leaving this empty would've caused a Verilator warning\n\t\t// Wishbone 2 (PHY)\n\t\t.i_wb2_cyc(wb32_ddr3_phy_cyc), .i_wb2_stb(wb32_ddr3_phy_stb), .i_wb2_we(wb32_ddr3_phy_we),\n\t\t\t.i_wb2_addr(wb32_ddr3_phy_addr[7-1:0]),\n\t\t\t.i_wb2_data(wb32_ddr3_phy_data), // 32 bits wide\n\t\t\t.i_wb2_sel(wb32_ddr3_phy_sel),  // 32/8 bits wide\n\t\t.o_wb2_stall(wb32_ddr3_phy_stall),.o_wb2_ack(wb32_ddr3_phy_ack), .o_wb2_data(wb32_ddr3_phy_idata),\n\t\t//\n\t\t// PHY interface\n\t\t.i_phy_iserdes_data(i_ddr3_iserdes_data),\n\t\t.i_phy_iserdes_dqs(i_ddr3_iserdes_dqs),\n\t\t.i_phy_iserdes_bitslip_reference(i_ddr3_iserdes_bitslip_reference),\n\t\t.i_phy_idelayctrl_rdy(i_ddr3_idelayctrl_rdy),\n\t\t.o_phy_cmd(o_ddr3_cmd),\n\t\t.o_phy_dqs_tri_control(o_ddr3_dqs_tri_control),\n\t\t.o_phy_dq_tri_control(o_ddr3_dq_tri_control),\n\t\t.o_phy_toggle_dqs(o_ddr3_toggle_dqs),\n\t\t.o_phy_data(o_ddr3_data),\n\t\t.o_phy_dm(o_ddr3_dm),\n\t\t.o_phy_odelay_data_cntvaluein(o_ddr3_odelay_data_cntvaluein),\n\t\t.o_phy_odelay_dqs_cntvaluein(o_ddr3_odelay_dqs_cntvaluein),\n\t\t.o_phy_idelay_data_cntvaluein(o_ddr3_idelay_data_cntvaluein),\n\t\t.o_phy_idelay_dqs_cntvaluein(o_ddr3_idelay_dqs_cntvaluein),\n\t\t.o_phy_odelay_data_ld(o_ddr3_odelay_data_ld),\n\t\t.o_phy_odelay_dqs_ld(o_ddr3_odelay_dqs_ld),\n\t\t.o_phy_idelay_data_ld(o_ddr3_idelay_data_ld),\n\t\t.o_phy_idelay_dqs_ld(o_ddr3_idelay_dqs_ld),\n\t\t.o_phy_bitslip(o_ddr3_bitslip),\n\t\t.o_phy_write_leveling_calib(o_ddr3_leveling_calib),\n\t\t.o_phy_reset(o_ddr3_reset),\n\t\t// Debug port\n\t\t.o_debug1(ddr3_debug),\n\t\t// Verilator lint_off PINCONNECTEMPTY\n\t\t.o_debug2(),\n\t\t.o_debug3()\n\t\t// Verilator lint_on  PINCONNECTEMPTY\n\t\t// }}}\n\t);\n\t// }}}\n\t// }}}\n`else\t// SDRAM_ACCESS\n\t// {{{\n\t// Null bus slave\n\t// {{{\n\n\t//\n\t// In the case that there is no wbwide_ddr3 peripheral\n\t// responding on the wbwide bus\n\tassign\twbwide_ddr3_ack   = 1'b0;\n\tassign\twbwide_ddr3_err   = (wbwide_ddr3_stb);\n\tassign\twbwide_ddr3_stall = 0;\n\tassign\twbwide_ddr3_idata = 0;\n\n\t// }}}\n\t// }}}\n`endif\t// SDRAM_ACCESS\n\n`ifdef\tI2CDMA_ACCESS\n\t// {{{\n\twbi2cdma #(\n\t\t.AW(27), .DW(128), .SW(8),\n\t\t.OPT_LITTLE_ENDIAN(1'b0)\n\t) u_i2cdma (\n\t\t// {{{\n\t\t.i_clk(i_clk),\n\t\t.i_reset(i_reset),\n\t\t//\n\t\t.i_wb_cyc(wb32_i2cdma_cyc), .i_wb_stb(wb32_i2cdma_stb), .i_wb_we(wb32_i2cdma_we),\n\t\t\t.i_wb_addr(wb32_i2cdma_addr[2-1:0]),\n\t\t\t.i_wb_data(wb32_i2cdma_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_i2cdma_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_i2cdma_stall),.o_wb_ack(wb32_i2cdma_ack), .o_wb_data(wb32_i2cdma_idata),\n\t\t.S_VALID(i2c_valid && i2c_id == 2),\n\t\t\t.S_READY(i2cdma_ready),\n\t\t\t.S_DATA(i2c_data), .S_LAST(i2c_last),\n\t\t.o_dma_cyc(wbwide_i2cdma_cyc), .o_dma_stb(wbwide_i2cdma_stb), .o_dma_we(wbwide_i2cdma_we),\n\t\t\t.o_dma_addr(wbwide_i2cdma_addr[27-1:0]),\n\t\t\t.o_dma_data(wbwide_i2cdma_data), // 128 bits wide\n\t\t\t.o_dma_sel(wbwide_i2cdma_sel),  // 128/8 bits wide\n\t\t.i_dma_stall(wbwide_i2cdma_stall), .i_dma_ack(wbwide_i2cdma_ack), .i_dma_data(wbwide_i2cdma_idata), .i_dma_err(wbwide_i2cdma_err)\n\t\t// }}}\n\t);\n\n\t// }}}\n`else\t// I2CDMA_ACCESS\n\t// {{{\n\tassign\ti2cdma_ready = 1'b0;\n\t// Null bus master\n\t// {{{\n\t// }}}\n\t// }}}\n`endif\t// I2CDMA_ACCESS\n\n`ifdef\tPWRCOUNT_ACCESS\n\t// {{{\n\tinitial\tr_pwrcount_data = 32'h0;\n\talways @(posedge i_clk)\n\tif (r_pwrcount_data[31])\n\t\tr_pwrcount_data[30:0] <= r_pwrcount_data[30:0] + 1'b1;\n\telse\n\t\tr_pwrcount_data[31:0] <= r_pwrcount_data[31:0] + 1'b1;\n\n\tassign\twb32_pwrcount_stall = 1'b0;\n\tassign\twb32_pwrcount_ack   = wb32_pwrcount_stb;\n\tassign\twb32_pwrcount_idata = r_pwrcount_data;\n\t// }}}\n`else\t// PWRCOUNT_ACCESS\n\t// {{{\n\t// }}}\n`endif\t// PWRCOUNT_ACCESS\n\n`ifdef\tI2SAUDIO\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// I2S Audio signal handler\n\t// {{{\n\n\tassign\to_i2s_mclk = i_genclk_clk;\n\tassign\tw_i2saudio_en = 1'b1;\n\n\taxisi2s #(\n\t\t.BDIV(4'h1)\n\t) u_i2saudio (\n\t\t// {{{\n\t\t.S_AXI_ACLK(i_clk), .S_AXI_ARESETN(!i_reset),\n\t\t//\n\t\t// Inputs to drive the speakers\n\t\t.S_AXIS_TVALID(w_audio_out_valid),\n\t\t.S_AXIS_TREADY(w_audio_out_ready),\n\t\t.S_AXIS_TDATA(w_audio_out_data),\n\t\t.S_AXIS_TLAST(w_audio_out_last),\n\t\t//\n\t\t// Outputs from the microphone\n\t\t.M_AXIS_TVALID(w_audio_in_valid),\n\t\t.M_AXIS_TREADY(w_audio_in_ready),\n\t\t.M_AXIS_TDATA(w_audio_in_data),\n\t\t.M_AXIS_TLAST(w_audio_in_last),\n\t\t//\n\t\t.i_mclk(o_i2s_mclk),\n\t\t.i_clken(w_i2saudio_en),\n\t\t.o_lrclk(o_i2s_lrclk),\n\t\t.o_bclk(o_i2s_bclk),\n\t\t.i_adc(i_i2s_adc),\n\t\t.o_dac(o_i2s_dac),\n\t\t.o_debug(w_i2saudio_debug)\n\t\t// }}}\n\t);\n\n`ifndef\tAUDIOSINK_ACCESS\n\tassign\tw_audio_out_valid = 0;\n\tassign\tw_audio_out_data  = 0;\n\tassign\tw_audio_out_last  = 0;\n`endif\n`ifndef\tAUDIOSOURCE_ACCESS\n\tassign\tw_audio_in_ready = 1;\n`endif\n\t// }}}\n\t// }}}\n`else\t// I2SAUDIO\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// (No) I2S Audio signal handler (option)\n\t// {{{\n`ifndef\tAUDIOSINK_ACCESS\n\tassign\tw_audio_out_valid = 0;\n\tassign\tw_audio_out_data  = 0;\n\tassign\tw_audio_out_last  = 0;\n`endif\n\tassign\tw_audio_out_ready = 0;\n\n\tassign\tw_audio_in_valid = 0;\n\tassign\tw_audio_in_data  = 0;\n\tassign\tw_audio_in_last  = 0;\n`ifndef\tAUDIOSOURCE_ACCESS\n\tassign\tw_audio_in_ready = 0;\n`endif\n\t// }}}\n\t// }}}\n`endif\t// I2SAUDIO\n\n\t// Generate a PPS signal independent of the GPS--useful for testing\n\tgpsclock_tb #(\n\t\t.CLOCK_FREQUENCY_HZ(100000000)\n\t) ppstb(\n\t\t.i_clk(i_clk), .i_lcl_pps(ck_pps), .o_pps(tb_pps),\n\t\t.i_wb_cyc(wb32_gtb_cyc), .i_wb_stb(wb32_gtb_stb), .i_wb_we(wb32_gtb_we),\n\t\t\t.i_wb_addr(wb32_gtb_addr[3-1:0]),\n\t\t\t.i_wb_data(wb32_gtb_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_gtb_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_gtb_stall),.o_wb_ack(wb32_gtb_ack), .o_wb_data(wb32_gtb_idata),\n\t\t.i_err(gps_err), .i_count(gps_now), .i_step(gps_step)\n\t);\n\n\tassign\tgps_pps = tb_pps;\n\tassign\to_pxclk_cyc  = wb32_pxclk_cyc;\n\tassign\to_pxclk_stb  = wb32_pxclk_stb;\n\tassign\to_pxclk_we   = wb32_pxclk_we;\n\tassign\to_pxclk_addr = wb32_pxclk_addr[6:0];\n\tassign\to_pxclk_data = wb32_pxclk_data;\n\tassign\to_pxclk_sel  = wb32_pxclk_sel;\n\tassign\twb32_pxclk_stall = i_pxclk_stall;\n\tassign\twb32_pxclk_ack   = i_pxclk_ack;\n\tassign\twb32_pxclk_idata = i_pxclk_idata;\n`ifdef\tMEGANET_ACCESS\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// MegaNET MEGANET\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t//\n\n\tmeganet #(\n\t\t// {{{\n\t\t.DEF_HWMAC(DEF_HWMAC),\n\t\t.DEF_IPADDR(DEF_IPADDR),\n\t\t.UDP_DBGPORT(UDP_DBGPORT)\n\t\t// }}}\n\t) u_net (\n\t\t// {{{\n\t\t.S_AXI_ACLK(i_clk), .S_AXI_ARESETN(!i_reset),\n\t\t//\n\t\t.o_hwmac(net_hwmac), .o_ipaddr(net_ip_addr),\n\t\t.o_ping_hwmac(net_last_ping_hwmac),\n\t\t\t.o_ping_ipaddr(net_last_ping_ipaddr),\n\t\t// Wishbone port\n\t\t// {{{\n\t\t.i_wb_cyc(wb32_net_cyc), .i_wb_stb(wb32_net_stb), .i_wb_we(wb32_net_we),\n\t\t\t.i_wb_addr(wb32_net_addr[5-1:0]),\n\t\t\t.i_wb_data(wb32_net_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_net_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_net_stall),.o_wb_ack(wb32_net_ack), .o_wb_data(wb32_net_idata),\n\t\t// }}}\n\t\t// ifdef MEGANETCPUTX_ACCESS\n\t\t// {{{\n\t\t.S_CPU_VALID(netcputx_valid),\n\t\t\t.S_CPU_READY(netcputx_ready),\n\t\t\t.S_CPU_DATA(netcputx_data),\n\t\t\t.S_CPU_BYTES(netcputx_bytes),\n\t\t\t.S_CPU_LAST(netcputx_last),\n\t\t\t.S_CPU_ABORT(netcputx_abort),\n\t\t// }}}\n`ifdef\tNETBUS_ACCESS\n\t\t// {{{\n\t\t.S_DBG_VALID(netbus_valid),\n\t\t\t.S_DBG_READY(netbus_ready),\n\t\t\t.S_DBG_DATA(netbus_pkdata),\n\t\t\t// .S_DBG_BYTES(netbus_bytes),\n\t\t\t.S_DBG_LAST(netbus_last),\n`else\n\t\t.S_DBG_VALID(1'b0),\n\t\t\t.S_DBG_READY(net_dbg_ready),\n\t\t\t.S_DBG_DATA(32'h0),\n\t\t\t.S_DBG_LAST(1'b1),\n`endif\n\t\t// }}}\n\t\t// Data interface\n\t\t// {{{\n\t\t.S_DATA_VALID(1'b0),\n\t\t\t.S_DATA_READY(ign_rxpkt_net_ready),\n\t\t\t.S_DATA_DATA(32'h0),\n\t\t\t.S_DATA_BYTES(2'h0),\n\t\t\t.S_DATA_LAST(1'b1),\n\t\t// }}}\n\t\t// ifdef MEGANETCPURX_ACCESS\n\t\t// {{{\n\t\t.M_CPU_VALID(netcpurx_valid),\n\t\t\t.M_CPU_READY(netcpurx_ready),\n\t\t\t.M_CPU_DATA(netcpurx_data),\n\t\t\t.M_CPU_BYTES(netcpurx_bytes),\n\t\t\t.M_CPU_LAST(netcpurx_last),\n\t\t\t.M_CPU_ABORT(netcpurx_abort),\n\t\t// }}}\n\t\t// Debug IP/UDP RX packets\n\t\t// {{{\n\t\t.M_DBG_VALID(net_dbg_valid),\n\t\t\t.M_DBG_READY(net_dbg_ready),\n\t\t\t.M_DBG_DATA( net_dbg_data),\n\t\t\t.M_DBG_BYTES(net_dbg_bytes),\n\t\t\t.M_DBG_LAST( net_dbg_last),\n\t\t// }}}\n\t\t// Interface to top-level IOs\n\t\t// {{{\n\t\t.o_net_reset_n(o_net_reset_n),\n\t\t.i_net_rx_clk(i_net_rx_clk), .i_net_rx_dv(i_net_rx_dv),\n\t\t.i_net_rx_err(i_net_rx_err), .i_net_rxd(i_net_rxd),\n\t\t//\n\t\t.i_net_tx_clk(i_net_tx_clk), .o_net_tx_ck(o_net_tx_clk),\n\t\t.o_net_tx_ctl(o_net_tx_ctl), .o_net_txd(o_net_txd),\n\t\t// }}}\n\t\t.o_debug_clk(net_debug_clk),\n\t\t.o_debug(net_debug)\n\t\t// }}}\n\t);\n\n`ifndef\tNETBUS_ACCESS\n\t// {{{\n\tassign\tnet_dbg_ready = 1'b1;\n\t// Verilator lint_off UNUSED\n\twire\tunused_net_dbgrx;\n\tassign\tunused_net_dbgrx = &{ 1'b0,\n\t\t\tnet_dbg_valid, net_dbg_data,\n\t\t\t\tnet_dbg_bytes, net_dbg_last };\n\t// Verilator lint_on  UNUSED\n\t// }}}\n`endif\n\n`ifndef\tMEGANETCPURX_ACCESS\n\t// {{{\n\tassign\tnetcpurx_ready = 1'b1;\n\t// Verilator lint_off UNUSED\n\twire\tunused_net_cpu_rx;\n\tassign\tunused_net_cpu_rx = &{ 1'b0,\n\t\t\tnetcpurx_valid, netcpurx_data,\n\t\t\t\tnetcpurx_bytes,\n\t\t\tnetcpurx_abort, netcpurx_last };\n\t// Verilator lint_on  UNUSED\n\t// }}}\n`endif\n\n`ifndef\tMEGANETCPUTX_ACCESS\n\t// {{{\n\tassign\tnetcputx_valid = 1'b0;\n\tassign\tnetcputx_data  = 32'h0;\n\tassign\tnetcputx_bytes =  2'h0;\n\tassign\tnetcputx_last  =  1'b1;\n\tassign\tnetcputx_abort =  1'b0;\n\t// }}}\n`endif\n\n\n\t// }}}\n\t// }}}\n`else\t// MEGANET_ACCESS\n\t// {{{\n\t// Null bus slave\n\t// {{{\n\n\t//\n\t// In the case that there is no wb32_net peripheral\n\t// responding on the wb32 bus\n\tassign\twb32_net_ack   = 1'b0;\n\tassign\twb32_net_err   = (wb32_net_stb);\n\tassign\twb32_net_stall = 0;\n\tassign\twb32_net_idata = 0;\n\n\t// }}}\n\t// }}}\n`endif\t// MEGANET_ACCESS\n\n`ifdef\tRTCDATE_ACCESS\n\t// {{{\n\t//\n\t// The Calendar DATE\n\t//\n\trtcdate #(\n\t\t.INITIAL_DATE(`DATESTAMP)\n\t) u_rtcdate(\n\t\t.i_clk(i_clk), .i_ppd(rtc_ppd),\n\t\t.i_wb_cyc(wb32_rtcdate_cyc), .i_wb_stb(wb32_rtcdate_stb), .i_wb_we(wb32_rtcdate_we),\n\t\t\t.i_wb_data(wb32_rtcdate_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_rtcdate_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_rtcdate_stall),.o_wb_ack(wb32_rtcdate_ack), .o_wb_data(wb32_rtcdate_idata)\n\t);\n\t// }}}\n`else\t// RTCDATE_ACCESS\n\t// {{{\n\t// }}}\n`endif\t// RTCDATE_ACCESS\n\n`ifdef\tRTC_ACCESS\n\t// {{{\n`ifdef\tGPSTRK_ACCESS\n\trtcgps\t#(\n\t\t.DEFAULT_SPEED(RTC_CLKSTEP)\n\t) u_rtc(\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t.i_wb_cyc(wb32_rtc_cyc), .i_wb_stb(wb32_rtc_stb), .i_wb_we(wb32_rtc_we),\n\t\t\t.i_wb_addr(wb32_rtc_addr[2-1:0]),\n\t\t\t.i_wb_data(wb32_rtc_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_rtc_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_rtc_stall),.o_wb_ack(wb32_rtc_ack), .o_wb_data(wb32_rtc_idata),\n\t\t.o_interrupt(rtc_int), .o_ppd(rtc_ppd),\n\t\t.i_gps_valid(gps_tracking), .i_gps_pps(ck_pps),\n\t\t\t.i_gps_ckspeed(gps_step[47:16]), .o_rtc_pps(rtc_pps)\n\t);\n`else\n\trtclight #(\n\t\t.DEFAULT_SPEED(32'h2af31d)\n\t) u_rtc(\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t// Can't use the ANSIPORTLIST tag, because the address widths\n\t\t// don't match\n\t\t.i_wb_cyc(wb32_rtc_cyc),\n\t\t.i_wb_stb(wb32_rtc_stb),\n\t\t.i_wb_we(wb32_rtc_we),\n\t\t.i_wb_addr({ 1'b0, wb32_rtc_addr[1:0] }),\n\t\t.i_wb_data(wb32_rtc_data),\n\t\t.i_wb_sel(wb32_rtc_sel),\n\t\t.o_wb_stall(wb32_rtc_stall),\n\t\t.o_wb_ack(wb32_rtc_ack),\n\t\t.o_wb_data(wb32_rtc_idata),\n\t\t.o_interrupt(rtc_int),\n\t\t.o_pps(rtc_pps),\n\t\t.o_ppd(rtc_ppd)\n\t);\n\n\t// Verilator lint_off UNUSED\n\twire\tunused_rtc;\n\tassign\tunused_rtc = &{ 1'b0, i_gps_pps };\n\t// Verilator lint_on  UNUSED\n`endif\n\t// }}}\n`else\t// RTC_ACCESS\n\t// {{{\n`ifdef\tGPSTRK_ACCESS\n\tassign\trtc_pps = ck_pps;\n`endif\n\tassign\trtc_ppd = 1'b0;\n\t// Null interrupt definitions\n\t// {{{\n\tassign\trtc_int = 1'b0;\t// rtc.INT.RTC.WIRE\n\t// }}}\n\t// }}}\n`endif\t// RTC_ACCESS\n\n`ifdef\tSPIO_ACCESS\n\t// {{{\n\t//\n\t// Special purpose I/O driver (buttons, LEDs, and switches)\n\t//\n\tassign\tw_btn = { i_btnc, i_btnd, i_btnl, i_btnr, i_btnu };\n\n\tspio #(\n\t\t.NBTN(5), .NLEDS(8), .NSW(8)\n\t) u_spio (\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t.i_wb_cyc(wb32_spio_cyc), .i_wb_stb(wb32_spio_stb), .i_wb_we(wb32_spio_we),\n\t\t\t.i_wb_data(wb32_spio_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_spio_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_spio_stall),.o_wb_ack(wb32_spio_ack), .o_wb_data(wb32_spio_idata),\n\t\t.i_sw(i_sw), .i_btn(w_btn), .o_led(w_led),\n\t\t.o_int(spio_int)\n\t);\n\n\tassign\to_led = w_led;\n\n\t// }}}\n`else\t// SPIO_ACCESS\n\t// {{{\n\tassign\tw_btn = 0;\n\tassign\to_led = 0;\n\t// Null interrupt definitions\n\t// {{{\n\tassign\tspio_int = 1'b0;\t// spio.INT.SPIO.WIRE\n\t// }}}\n\t// }}}\n`endif\t// SPIO_ACCESS\n\n`ifdef\tGPIO_ACCESS\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// GPIO\n\t// {{{\n\t// This interface should allow us to control up to 16 GPIO inputs,\n\t// and another 16 GPIO outputs.  The interrupt trips when any of\n\t// the inputs changes.  (Sorry, which input isn't (yet) selectable.)\n\t//\n\tlocalparam [NGPO-1:0]\tINITIAL_GPIO = 10'h13;\n\n\twbgpio\t#(\n\t\t.NIN(NGPI), .NOUT(NGPO), .DEFAULT(INITIAL_GPIO)\n\t) u_gpio (\n\t\t// {{{\n\t\t.i_clk(i_clk),\n\t\t.i_wb_cyc(wb32_gpio_cyc), .i_wb_stb(wb32_gpio_stb), .i_wb_we(wb32_gpio_we),\n\t\t\t.i_wb_data(wb32_gpio_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_gpio_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_gpio_stall),.o_wb_ack(wb32_gpio_ack), .o_wb_data(wb32_gpio_idata),\n\t\t.i_gpio(i_gpio), .o_gpio(o_gpio),\n\t\t.o_int(gpio_int)\n\t\t// }}}\n\t);\n\n`ifdef\tSDIO_ACCESS\n\t// This bit is used by the SDSPI controller, not the SDIO controller.\n\tassign\tsd_reset = !o_sdio_hwreset_n;\n`else\n\tassign\tsd_reset = o_gpio[3];\n`endif\n\n`ifdef\tVERILATOR\n\twire\tverilator_halt;\n\tassign\to_trace = o_gpio[8];\n\n\tassign\tverilator_halt = o_gpio[9];\n\tassign\to_halt = verilator_halt;\n\talways @(posedge verilator_halt)\n\t\t$finish;\n`endif\n\t// }}}\n\t// }}}\n`else\t// GPIO_ACCESS\n\t// {{{\n\t// Null interrupt definitions\n\t// {{{\n\tassign\tgpio_int = 1'b0;\t// gpio.INT.GPIO.WIRE\n\t// }}}\n\t// }}}\n`endif\t// GPIO_ACCESS\n\n`ifdef\tSDIO_ACCESS\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// SDIO SD Card handling\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t//\n\n\talways @(*)\n\tbegin\n\t\tsdio_debug = i_sdio_debug;\n\t\tsdio_debug = w_sdio_sdwb_debug;\n\tend\n\n\tsdio #(\n\t\t// {{{\n\t\t.LGFIFO(10), .NUMIO(4),\n\t\t.MW(32),\n\t\t.ADDRESS_WIDTH(27+$clog2(128/8)),\n\t\t.DMA_DW(128),\n\t\t.OPT_SERDES(1'b1),\n\t\t.OPT_EMMC(1'b0),\n\t\t.OPT_DMA(1'b1),\n\t\t.OPT_DDR(1'b1),\n\t\t.OPT_HWRESET(1'b0),\n\t\t.OPT_CARD_DETECT(1'b1),\n\t\t.OPT_CRCTOKEN(1),\n\t\t.OPT_1P8V(1'b0),\n`ifdef\tVERILATOR\n\t\t.LGTIMEOUT(18),\n`else\n\t\t.LGTIMEOUT(26),\n`endif\n\t\t.OPT_ISTREAM(1'b0),\n\t\t.OPT_OSTREAM(1'b0)\n\t\t// }}}\n\t) u_sdio(\n\t\t// {{{\n\t\t.i_clk(i_clk),\n\t\t.i_reset(i_reset),\n\t\t.i_wb_cyc(wbflash_sdio_cyc), .i_wb_stb(wbflash_sdio_stb), .i_wb_we(wbflash_sdio_we),\n\t\t\t.i_wb_addr(wbflash_sdio_addr[3-1:0]),\n\t\t\t.i_wb_data(wbflash_sdio_data), // 32 bits wide\n\t\t\t.i_wb_sel(wbflash_sdio_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wbflash_sdio_stall),.o_wb_ack(wbflash_sdio_ack), .o_wb_data(wbflash_sdio_idata),\n\t\t.o_dma_cyc(wbwide_sdio_cyc), .o_dma_stb(wbwide_sdio_stb), .o_dma_we(wbwide_sdio_we),\n\t\t\t.o_dma_addr(wbwide_sdio_addr[27-1:0]),\n\t\t\t.o_dma_data(wbwide_sdio_data), // 128 bits wide\n\t\t\t.o_dma_sel(wbwide_sdio_sel),  // 128/8 bits wide\n\t\t.i_dma_stall(wbwide_sdio_stall), .i_dma_ack(wbwide_sdio_ack), .i_dma_data(wbwide_sdio_idata), .i_dma_err(wbwide_sdio_err),\n\t\t// (Unused) DMA Stream assignments\n\t\t// {{{\n\t\t.s_valid(1'b0),\n\t\t.s_ready(s_sdio_ready),\n\t\t.s_data(32'h0),\n\t\t//\n\t\t.m_valid(m_sdio_valid),\n\t\t.m_ready(1'b1),\n\t\t.m_data(m_sdio_data),\n\t\t.m_last(m_sdio_last),\n\t\t// }}}\n\t\t.i_card_detect(i_sdio_detect),\n\t\t.o_hwreset_n(o_sdio_hwreset_n),\n\t\t.o_1p8v(o_sdio_1p8v),\n\t\t.o_int(sdio_int),\n\t\t//\n\t\t.o_cfg_ddr(o_sdio_cfg_ddr),\n\t\t.o_cfg_ds(o_sdio_cfg_ds),\n\t\t.o_cfg_dscmd(o_sdio_cfg_dscmd),\n\t\t.o_cfg_sample_shift(o_sdio_cfg_sample_shift),\n\t\t.o_cmd_tristate(o_sdio_cmd_tristate),\n\t\t.o_data_tristate(o_sdio_data_tristate),\n\t\t//\n\t\t.o_sdclk(   o_sdio_sdclk),\n\t\t.o_cmd_en(  o_sdio_cmd_en),\n\t\t.o_cmd_data(o_sdio_cmd_data),\n\t\t.o_data_en( o_sdio_data_en),\n\t\t.o_rx_en(   o_sdio_rx_en),\n\t\t.o_tx_data( o_sdio_tx_data),\n\t\t//\n\t\t.i_cmd_strb( i_sdio_cmd_strb),\n\t\t.i_cmd_data( i_sdio_cmd_data),\n\t\t.i_cmd_collision( i_sdio_cmd_collision),\n\t\t.i_crcack( i_sdio_crcack),\n\t\t.i_crcnak( i_sdio_crcnak),\n\t\t.i_card_busy(i_sdio_card_busy),\n\t\t.i_rx_strb(  i_sdio_rx_strb),\n\t\t.i_rx_data(  i_sdio_rx_data),\n\t\t//\n\t\t.S_AC_VALID(i_sdio_ac_valid),\n\t\t.S_AC_DATA( i_sdio_ac_data),\n\t\t.S_AD_VALID(i_sdio_ad_valid),\n\t\t.S_AD_DATA( i_sdio_ad_data),\n\t\t//\n\t\t.o_debug(w_sdio_sdwb_debug)\n\t\t// }}}\n\t);\n\n\t// }}}\n\t// }}}\n`else\t// SDIO_ACCESS\n\t// {{{\n\t// Null bus master\n\t// {{{\n\t// }}}\n\t// Null bus slave\n\t// {{{\n\n\t//\n\t// In the case that there is no wbflash_sdio peripheral\n\t// responding on the wbflash bus\n\tassign\twbflash_sdio_ack   = 1'b0;\n\tassign\twbflash_sdio_err   = (wbflash_sdio_stb);\n\tassign\twbflash_sdio_stall = 0;\n\tassign\twbflash_sdio_idata = 0;\n\n\t// }}}\n\t// Null interrupt definitions\n\t// {{{\n\tassign\tsdio_int = 1'b0;\t// sdio.INT.SDCARD.WIRE\n\t// }}}\n\t// }}}\n`endif\t// SDIO_ACCESS\n\n\tassign\ti_net_tx_clk = i_clk_125mhz;\n`ifdef\tBUSPIC_ACCESS\n\t// {{{\n\t//\n\t// The BUS Interrupt controller\n\t//\n\ticontrol #(15)\n\tu_buspic (\n\t\t.i_clk(i_clk), .i_reset(1'b0),\n\t\t.i_wb_cyc(wb32_buspic_cyc), .i_wb_stb(wb32_buspic_stb), .i_wb_we(wb32_buspic_we),\n\t\t\t.i_wb_data(wb32_buspic_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_buspic_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_buspic_stall),.o_wb_ack(wb32_buspic_ack), .o_wb_data(wb32_buspic_idata),\n\t\t.i_brd_ints(bus_int_vector),\n\t\t.o_interrupt(w_bus_int)\n\t);\n\t// }}}\n`else\t// BUSPIC_ACCESS\n\t// {{{\n\t// Null interrupt definitions\n\t// {{{\n\tassign\tw_bus_int = 1'b0;\t// buspic.INT.BUS.WIRE\n\t// }}}\n\t// }}}\n`endif\t// BUSPIC_ACCESS\n\n`ifdef\tGPSTRK_ACCESS\n\t// {{{\n\t// Verilator lint_off UNUSED\n\twire\t[1:0]\tck_dbg;\n\t// Verilator lint_on  UNUSED\n\n\tgpsclock #(\n\t\t.DEFAULT_STEP(GPSCLOCK_DEFAULT_STEP)\n\t) ppsck (\n\t\t.i_clk(i_clk), .i_rst(1'b0), .i_pps(gps_pps), .o_pps(ck_pps),\n\t\t\t.o_led(gps_led),\n\t\t.i_wb_cyc(wb32_gck_cyc), .i_wb_stb(wb32_gck_stb), .i_wb_we(wb32_gck_we),\n\t\t\t.i_wb_addr(wb32_gck_addr[2-1:0]),\n\t\t\t.i_wb_data(wb32_gck_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_gck_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_gck_stall),.o_wb_ack(wb32_gck_ack), .o_wb_data(wb32_gck_idata),\n\t\t.o_tracking(gps_tracking), .o_count(gps_now), .o_step(gps_step),\n\t\t.o_err(gps_err), .o_locked(gps_locked), .o_dbg(ck_dbg)\n\t);\n\n\tassign\tgck_pps = ck_pps;\n\n\t// }}}\n`else\t// GPSTRK_ACCESS\n\t// {{{\n\treg\t\tr_ck_pps;\n\treg\t[63:0]\tr_gps_now;\n\treg\t[31:0]\tr_gps_prior;\n\twire\t[47:0]\tpre_step;\n\tassign\tpre_step = { 16'h00, (({GPSCLOCK_DEFAULT_STEP[27:0],20'h00})\n\t\t\t\t>>GPSCLOCK_DEFAULT_STEP[31:28]) };\n\n\tinitial\t{ r_ck_pps, r_gps_prior } = 33'h0;\n\talways @(posedge i_clk)\n\t\t{ r_ck_pps, r_gps_prior[31:0] } <= r_gps_prior + pre_step[31:0];\n\n\tinitial\tr_gps_now = 64'h0;\n\talways @(posedge i_clk)\n\tbegin\n\t\tr_gps_now[63:32] <= r_gps_now[63:32]+(r_ck_pps ? 32'h1:32'h0);\n\t\tr_gps_now[31:0]  <= r_gps_prior;\n\tend\n\tassign\tck_pps     = r_ck_pps;\n\tassign\tgps_now    = r_gps_now;\n\tassign\tgps_err    = 64'h0;\n\tassign\tgps_step   = pre_step;\n\tassign\tgps_led    = 1'b0;\n\tassign\tgps_locked = 1'b0;\n\n\t// Null interrupt definitions\n\t// {{{\n\tassign\tgck_pps = 1'b0;\t// gck.INT.PPS.WIRE\n\t// }}}\n\t// }}}\n`endif\t// GPSTRK_ACCESS\n\n`ifdef\tNETCTRL_ACCESS\n\t// {{{\n\tenetctrl #(\n\t\t.CLKBITS(6)\n\t) u_mdio (\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t.i_wb_cyc(wb32_mdio_cyc), .i_wb_stb(wb32_mdio_stb), .i_wb_we(wb32_mdio_we),\n\t\t\t.i_wb_addr(wb32_mdio_addr[10-1:0]),\n\t\t\t.i_wb_data(wb32_mdio_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_mdio_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_mdio_stall),.o_wb_ack(wb32_mdio_ack), .o_wb_data(wb32_mdio_idata),\n\t\t.o_mdclk(o_mdclk), .o_mdio(o_mdio), .i_mdio(i_mdio),\n\t\t.o_mdwe(o_mdwe), .o_debug(mdio_debug)\n\t);\n\t// }}}\n`else\t// NETCTRL_ACCESS\n\t// {{{\n\tassign\to_mdclk = 1'b1;\n\tassign\to_mdio  = 1'b1;\n\tassign\to_mdwe  = 1'b0;\n\t// Null bus slave\n\t// {{{\n\n\t//\n\t// In the case that there is no wb32_mdio peripheral\n\t// responding on the wb32 bus\n\tassign\twb32_mdio_ack   = 1'b0;\n\tassign\twb32_mdio_err   = (wb32_mdio_stb);\n\tassign\twb32_mdio_stall = 0;\n\tassign\twb32_mdio_idata = 0;\n\n\t// }}}\n\t// }}}\n`endif\t// NETCTRL_ACCESS\n\n\tassign\twb32_buildtime_idata = `BUILDTIME;\n\tassign\twb32_buildtime_ack = wb32_buildtime_stb;\n\tassign\twb32_buildtime_stall = 1'b0;\n`ifdef\tVERSION_ACCESS\n\t// {{{\n\tassign\twb32_version_idata = `DATESTAMP;\n\tassign\twb32_version_ack = wb32_version_stb;\n\tassign\twb32_version_stall = 1'b0;\n\t// }}}\n`else\t// VERSION_ACCESS\n\t// {{{\n\t// }}}\n`endif\t// VERSION_ACCESS\n\n`ifdef\tOLEDBW_ACCESS\n\t// {{{\n\tspicpu #(\n\t\t// {{{\n\t\t.ADDRESS_WIDTH(27),\n\t\t.DATA_WIDTH(128),\n\t\t.NCE(2),\n\t\t.OPT_MANUAL(1'b1), .OPT_LITTLE_ENDIAN(1'b0),\n\t\t.OPT_START_HALTED(1'b1), .OPT_SHARED_MISO(1'b1)\n\t\t// }}}\n\t) u_oled (\n\t\t// {{{\n\t\t.i_clk(i_clk), .i_reset(i_reset),\n\t\t.i_wb_cyc(wb32_oled_cyc), .i_wb_stb(wb32_oled_stb), .i_wb_we(wb32_oled_we),\n\t\t\t.i_wb_addr(wb32_oled_addr[2-1:0]),\n\t\t\t.i_wb_data(wb32_oled_data), // 32 bits wide\n\t\t\t.i_wb_sel(wb32_oled_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(wb32_oled_stall),.o_wb_ack(wb32_oled_ack), .o_wb_data(wb32_oled_idata),\n\t\t.o_pf_cyc(wbwide_oledm_cyc), .o_pf_stb(wbwide_oledm_stb), .o_pf_we(wbwide_oledm_we),\n\t\t\t.o_pf_addr(wbwide_oledm_addr[27-1:0]),\n\t\t\t.o_pf_data(wbwide_oledm_data), // 128 bits wide\n\t\t\t.o_pf_sel(wbwide_oledm_sel),  // 128/8 bits wide\n\t\t.i_pf_stall(wbwide_oledm_stall), .i_pf_ack(wbwide_oledm_ack), .i_pf_data(wbwide_oledm_idata), .i_pf_err(wbwide_oledm_err),\n\t\t.o_spi_csn(w_oled_csn), .o_spi_sck(o_oled_sck),\n\t\t.o_spi_mosi(o_oled_mosi), .i_spi_miso(1'b0),\n\t\t.M_AXIS_TVALID(ign_oled_valid),\n\t\t.M_AXIS_TREADY(1'b1),\n\t\t.M_AXIS_TDATA( ign_oled_data),\n\t\t.M_AXIS_TLAST( ign_oled_last),\n\t\t.M_AXIS_TID(   ign_oled_id),\n\t\t//\n\t\t.o_interrupt(oled_int),\n\t\t.i_sync_signal(rtc_pps),\n\t\t.o_debug(oled_debug)\n\t\t// }}}\n\t);\n\n\tassign\to_oled_dcn = w_oled_csn[0];\n\t// }}}\n`else\t// OLEDBW_ACCESS\n\t// {{{\n\tassign\to_oled_sck     = 1'b1;\n\tassign\to_oled_mosi    = 1'b1;\n\tassign\to_oled_dcn     = 1'b1;\n\n\t// Null bus master\n\t// {{{\n\t// }}}\n\t// Null interrupt definitions\n\t// {{{\n\tassign\toled_int = 1'b0;\t// oled.INT.OLED.WIRE\n\t// }}}\n\t// }}}\n`endif\t// OLEDBW_ACCESS\n\n`ifdef\tMICROPHONE_ACCESS\n\t// {{{\n\twbmic #(.DEFAULT_RELOAD(@$.CLKSPERSAMPLE))\n\t\tmicrophone(i_clk, 1'b0,\n\t\t\twb32_pmic_cyc, wb32_pmic_stb, wb32_pmic_we,\n\t\t\twb32_pmic_addr[1-1:0],\n\t\t\twb32_pmic_data, // 32 bits wide\n\t\t\twb32_pmic_sel,  // 32/8 bits wide\n\t\twb32_pmic_stall, wb32_pmic_ack, wb32_pmic_idata,\n\t\t\to_mic_csn, o_mic_sck, i_mic_din, pmic_int);\n\t// }}}\n`else\t// MICROPHONE_ACCESS\n\t// {{{\n\tassign\to_mic_csn    = 1'b1;\n\tassign\to_mic_sck    = 1'b1;\n\t// Null bus slave\n\t// {{{\n\n\t//\n\t// In the case that there is no wb32_pmic peripheral\n\t// responding on the wb32 bus\n\tassign\twb32_pmic_ack   = 1'b0;\n\tassign\twb32_pmic_err   = (wb32_pmic_stb);\n\tassign\twb32_pmic_stall = 0;\n\tassign\twb32_pmic_idata = 0;\n\n\t// }}}\n\t// Null interrupt definitions\n\t// {{{\n\tassign\tpmic_int = 1'b0;\t// pmic.INT.MIC.WIRE\n\t// }}}\n\t// }}}\n`endif\t// MICROPHONE_ACCESS\n\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// WBUBUS \"wbu_arbiter\" master->slave connection\n\t// {{{\n\n\twbupsz #(\n\t\t// {{{\n\t\t// Slave bus address width : 30\n\t\t// Slave address width     : 29\n\t\t// Master bus address width: 27\n\t\t.ADDRESS_WIDTH(27+$clog2(128/8)),\n\t\t.SMALL_DW(32),\n\t\t.WIDE_DW(128),\n\t\t.OPT_LITTLE_ENDIAN(1'b0)\n\t\t// }}}\n\t) u_wbu_wbwide_downsz (\n\t\t// {{{\n\t\t.i_clk(i_clk),\n\t\t.i_reset(i_reset),\n\t\t.i_scyc(wbu_wbu_arbiter_cyc), .i_sstb(wbu_wbu_arbiter_stb), .i_swe(wbu_wbu_arbiter_we),\n\t\t\t.i_saddr(wbu_wbu_arbiter_addr[29-1:0]),\n\t\t\t.i_sdata(wbu_wbu_arbiter_data), // 32 bits wide\n\t\t\t.i_ssel(wbu_wbu_arbiter_sel),  // 32/8 bits wide\n\t\t.o_sstall(wbu_wbu_arbiter_stall),.o_sack(wbu_wbu_arbiter_ack), .o_sdata(wbu_wbu_arbiter_idata), .o_serr(wbu_wbu_arbiter_err),\n\t\t.o_wcyc(wbwide_wbu_arbiter_cyc), .o_wstb(wbwide_wbu_arbiter_stb), .o_wwe(wbwide_wbu_arbiter_we),\n\t\t\t.o_waddr(wbwide_wbu_arbiter_addr[27-1:0]),\n\t\t\t.o_wdata(wbwide_wbu_arbiter_data), // 128 bits wide\n\t\t\t.o_wsel(wbwide_wbu_arbiter_sel),  // 128/8 bits wide\n\t\t.i_wstall(wbwide_wbu_arbiter_stall), .i_wack(wbwide_wbu_arbiter_ack), .i_wdata(wbwide_wbu_arbiter_idata), .i_werr(wbwide_wbu_arbiter_err)\n\t\t// }}}\n\t);\n\n\t// }}}\n`ifdef\tINCLUDE_ZIPCPU\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// The ZipCPU/ZipSystem BUS master\n\t// {{{\n\t//\n\tassign\tzip_int_vector = { alt_int_vector[14:8], sys_int_vector[14:6] };\n\tzipsystem #(\n\t\t// {{{\n\t\t.RESET_ADDRESS(RESET_ADDRESS),\n\t\t.ADDRESS_WIDTH(ZIP_ADDRESS_WIDTH + $clog2(128/8)),\n\t\t.BUS_WIDTH(128),\n\t\t.OPT_LGICACHE(12),\n\t\t.OPT_LGDCACHE(12),\n\t\t.START_HALTED(ZIP_START_HALTED),\n\t\t.RESET_DURATION(20),\n\t\t.OPT_PIPELINED(1),\n`ifdef\tVERILATOR\n\t\t.OPT_PROFILER(1'b1),\n`else\n\t\t.OPT_PROFILER(1'b0),\n`endif\n`ifdef\tZIPSCOPE_SCOPE\n\t\t.OPT_TRACE_PORT(1'b1),\n`else\n\t\t.OPT_TRACE_PORT(1'b0),\n`endif\n\t\t.OPT_DISTRIBUTED_REGS(1),\n\t\t.EXTERNAL_INTERRUPTS(ZIP_INTS)\n\t\t// }}}\n\t) swic(\n\t\t// {{{\n\t\t.i_clk(i_clk), .i_reset(i_reset || i_cpu_reset),\n\t\t\t// Zipsys wishbone interface\n\t\t\t.o_wb_cyc(wbwide_zip_cyc), .o_wb_stb(wbwide_zip_stb), .o_wb_we(wbwide_zip_we),\n\t\t\t.o_wb_addr(wbwide_zip_addr[27-1:0]),\n\t\t\t.o_wb_data(wbwide_zip_data), // 128 bits wide\n\t\t\t.o_wb_sel(wbwide_zip_sel),  // 128/8 bits wide\n\t\t.i_wb_stall(wbwide_zip_stall), .i_wb_ack(wbwide_zip_ack), .i_wb_data(wbwide_zip_idata), .i_wb_err(wbwide_zip_err),\n\t\t\t.i_ext_int(zip_int_vector), .o_ext_int(zip_cpu_int),\n\t\t\t// Debug wishbone interface\n\t\t\t.i_dbg_cyc(wbu_zip_cyc || cpu_sim_cyc),\n\t\t\t.i_dbg_stb(cpu_sim_cyc ? cpu_sim_stb : wbu_zip_stb),\n\t\t\t.i_dbg_we( cpu_sim_cyc ? cpu_sim_we  : wbu_zip_we),\n\t\t\t.i_dbg_addr(cpu_sim_cyc? cpu_sim_addr : wbu_zip_addr[6:0]),\n\t\t\t.i_dbg_data (cpu_sim_cyc? cpu_sim_data : wbu_zip_data),\n\t\t\t.i_dbg_sel  (cpu_sim_cyc? 4'hf : wbu_zip_sel),\n\t\t\t.o_dbg_stall(raw_cpu_dbg_stall),\n\t\t\t.o_dbg_ack  (raw_cpu_dbg_ack),\n\t\t\t.o_dbg_data (wbu_zip_idata),\n\t\t\t//\n\t\t\t.o_cpu_debug(zip_debug),\n\t\t\t.o_prof_stb(cpu_prof_stb),\n\t\t\t.o_prof_addr(cpu_prof_addr),\n\t\t\t.o_prof_ticks(cpu_prof_ticks)\n\t\t// }}}\n\t);\n\tassign\tzip_trigger = zip_debug[31];\n\n\tassign\twbu_zip_stall =  cpu_sim_cyc || raw_cpu_dbg_stall;\n\tassign\twbu_zip_ack   = !cpu_sim_cyc && raw_cpu_dbg_ack;\n\tassign\tcpu_sim_stall = !cpu_sim_cyc || raw_cpu_dbg_stall;\n\tassign\tcpu_sim_ack   =  cpu_sim_cyc && raw_cpu_dbg_ack;\n\tassign\tcpu_sim_idata = wbu_zip_idata;\n\n\t// Keep Verilator happy\n\t// {{{\n\t// Verilator lint_off UNUSED\n\twire\tzip_unused;\n\tassign\tzip_unused = &{ 1'b0,\n\t\t\talt_int_vector[7:0], sys_int_vector[5:0]};\n\t// Verilator lint_on  UNUSED\n\t// }}}\n\t// }}}\n\t// }}}\n`else\t// INCLUDE_ZIPCPU\n\t// {{{\n\t// Null bus master\n\t// {{{\n\t// }}}\n\t// Null bus slave\n\t// {{{\n\n\t//\n\t// In the case that there is no wbu_zip peripheral\n\t// responding on the wbu bus\n\tassign\twbu_zip_ack   = 1'b0;\n\tassign\twbu_zip_err   = (wbu_zip_stb);\n\tassign\twbu_zip_stall = 0;\n\tassign\twbu_zip_idata = 0;\n\n\t// }}}\n\t// Null interrupt definitions\n\t// {{{\n\tassign\tzip_cpu_int = 1'b0;\t// zip.INT.ZIP.WIRE\n\t// }}}\n\t// }}}\n`endif\t// INCLUDE_ZIPCPU\n\n\t// }}}\nendmodule // main.v\n"
  },
  {
    "path": "demo-out/main_tb.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\t../demo-out/main_tb.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Computer Generated: This file is computer generated by AUTOFPGA. DO NOT EDIT.\n// DO NOT EDIT THIS FILE!\n//\n// CmdLine:\t./autofpga -d -o ../demo-out -I ../auto-data allclocks.txt bkram.txt buserr.txt clkcheck.txt crossbus.txt ddr3.txt edidslvscope.txt edid.txt exconsole.txt flashcfg.txt flash.txt global.txt gpio.txt gps.txt hdmi.txt i2ccpu.txt i2cdma.txt i2saudio.txt icape.txt meganet.txt mdio.txt pic.txt pwrcount.txt rtcdate.txt rtcgps.txt spio.txt sdio.txt vadj33.txt version.txt wboledbw.txt wbpmic.txt wbuarbiter.txt wbubus.txt zipcpu.txt zipmaster.txt\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n//\n// SIM.INCLUDE\n//\n// Any SIM.INCLUDE tags you define will be pasted here.\n// This is useful for guaranteeing any include functions\n// your simulation needs are called.\n//\n#include \"verilated.h\"\n#include \"Vmain.h\"\n#define\tBASECLASS\tVmain\n\n#include \"design.h\"\n#include \"regdefs.h\"\n#include \"testb.h\"\n#include \"flashsim.h\"\n#include \"dbluartsim.h\"\n#include \"uartsim.h\"\n#include \"hdmisource.h\"\n#include \"hdmisim.h\"\n#include \"byteswap.h\"\n#include \"netsim.h\"\n#include \"sdiosim.h\"\n#include \"enetctrlsim.h\"\n#include \"zipelf.h\"\n\n//\n// SIM.DEFINES\n//\n// This tag is useful fr pasting in any #define values that\n// might then control the simulation following.\n//\n#ifndef VVAR\n#ifdef  ROOT_VERILATOR\n#include \"Vmain___024root.h\"\n\n#define VVAR(A) rootp->main__DOT_ ## A\n#elif\tdefined(NEW_VERILATOR)\n#define VVAR(A) main__DOT_ ## A\n#else\n#define VVAR(A) v__DOT_ ## A\n#endif\n#endif\n\n#define\tblock_ram\trootp->main__DOT__u_bkram__DOT__mem.m_storage\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// ZipCPU simulation defines\n// {{{\n#ifndef\tVVAR\n#ifdef\tROOT_VERILATOR\n\n#include \"Vmain___024root.h\"\n#define\tVVAR(A)\trootp->main__DOT_ ## A\n\n#elif\tdefined(NEW_VERILATOR)\n#define\tVVAR(A)\tmain__DOT_ ## A\n#else\n#define\tVVAR(A)\tv__DOT_ ## A\n#endif\n#endif\n\n#define\tOPT_PIPELINED\n#define\tCPUVAR(A)\tVVAR(_swic__DOT__thecpu__DOT__core__DOT_ ## A)\n\n#define\tcpu_break \tVVAR(_swic__DOT__cpu_break)\n// }}}\nclass\tMAINTB : public TESTB<Vmain> {\npublic:\n\t\t// SIM.DEFNS\n\t\t//\n\t\t// If you have any simulation components, create a\n\t\t// SIM.DEFNS tag to have those components defined here\n\t\t// as part of the main_tb.cpp function.\n#ifdef\tFLASH_ACCESS\n\tFLASHSIM\t*m_flash;\n#endif // FLASH_ACCESS\n\tDBLUARTSIM\t*m_wbu;\n#ifdef\tGPSUART_ACCESS\n\tUARTSIM\t*m_gpsu;\n#endif // GPSUART_ACCESS\n#ifdef VIDPIPE_ACCESS\n\tHDMISOURCE\t*m_hdmirx;\n\tHDMIWIN\t\t*m_hdmitx;\n#endif\t// VIDPIPE_ACCESS\n\t\tNETSIM\t*m_net;\n\tSDIOSIM\t\t*m_sdio;\n#ifdef\tNETCTRL_ACCESS\n\tENETCTRLSIM\t*m_mdio;\n#endif // NETCTRL_ACCESS\n\tint\tm_cpu_bombed;\n\tMAINTB(void) {\n\t\t// SIM.INIT\n\t\t//\n\t\t// If your simulation components need to be initialized,\n\t\t// create a SIM.INIT tag.  That tag's value will be pasted\n\t\t// here.\n\t\t//\n\t\t// From flash\n#ifdef\tFLASH_ACCESS\n\t\tm_flash = new FLASHSIM(FLASHLGLEN, false, 2, 6);\n#endif // FLASH_ACCESS\n\t\t// From wbu\n\t\tm_wbu = new DBLUARTSIM();\n\t\tm_wbu->setup(100);\n\t\t// From gpsu\n#ifdef\tGPSUART_ACCESS\n\t\tm_gpsu = new UARTSIM(FPGAPORT+2);\n\t\tm_gpsu->setup(0x000028b0);\n#endif // GPSUART_ACCESS\n\t\t// From hdmi\n#ifdef\tVIDPIPE_ACCESS\n\t\tm_hdmirx = NULL;\n\t\tm_hdmitx = NULL;\n\t\tif (gbl_use_gui) {\n\t\t\tm_hdmirx = new HDMISOURCE(800, 600);\n\t\t\tm_hdmitx = new HDMIWIN(800, 600);\n\t\t}\n#endif\t// VIDPIPE_ACCESS\n\t\t// From net\n\t\t// Network init\n\t\t// {{{\n\t\tm_net = new NETSIM(); // DBGPORT: 6784, DATAPORT: 6785;\n\t\tm_net->external_mac[0] = 0xde;\n\t\tm_net->external_mac[1] = 0xad;\n\t\tm_net->external_mac[2] = 0xbe;\n\t\tm_net->external_mac[3] = 0xef;\n\t\tm_net->external_mac[4] = 0xda;\n\t\tm_net->external_mac[5] = 0xd0 | (200 & 0x0f);\n\t\tm_net->external_ip[0] = 127;\n\t\tm_net->external_ip[1] = 0;\n\t\tm_net->external_ip[2] = 0;\n\t\tm_net->external_ip[3] = 1;\n\t\tm_net->local_mac[0] = 0x82 & 0x0ff;\n\t\tm_net->local_mac[1] = 0x33 & 0x0ff;\n\t\tm_net->local_mac[2] = 0x48 & 0x0ff;\n\t\tm_net->local_mac[3] = 0x02 & 0x0ff;\n\t\tm_net->local_mac[4] = 0xe1 & 0x0ff;\n\t\tm_net->local_mac[5] = 0xc8 & 0x0ff;\n\t\tm_net->local_ip[0] = 0xc0 & 0x0ff; // 192\n\t\tm_net->local_ip[1] = 0xa8 & 0x0ff; // 168\n\t\tm_net->local_ip[2] = 0x0f & 0x0ff; //  15\n\t\tm_net->local_ip[3] = 0x1d & 0x0ff; //  29\n\t\tm_net->local_ipu = 0xc0a80f1d;\n\t\t// }}}\n\t\t// From sdio\n#ifdef\tSDIO_ACCESS\n\t\tm_sdio = new SDIOSIM(\"sdcard.img\");\n\t\tm_core->i_sdio_detect = 1;\n\t\tm_core->i_sdio_crcack = 0;\n\t\tm_core->i_sdio_crcnak = 0;\n#endif\n\t\t// From mdio\n#ifdef\tNETCTRL_ACCESS\n\t\tm_mdio = new ENETCTRLSIM;\n#endif // NETCTRL_ACCESS\n\t\t// From zip\n\t\tm_cpu_bombed = 0;\n\t}\n\n\tvoid\treset(void) {\n\t\t// SIM.SETRESET\n\t\t// If your simulation component needs logic before the\n\t\t// tick with reset set, that logic can be placed into\n\t\t// the SIM.SETRESET tag and thus pasted here.\n\t\t//\n\t\tm_core->i_cpu_reset = 1;\n\t\tTESTB<Vmain>::reset();\n\t\t// SIM.CLRRESET\n\t\t// If your simulation component needs logic following the\n\t\t// reset tick, that logic can be placed into the\n\t\t// SIM.CLRRESET tag and thus pasted here.\n\t\t//\n\t\tm_core->i_cpu_reset = 0;\n\t}\n\n\tvoid\ttrace(const char *vcd_trace_file_name) {\n\t\tfprintf(stderr, \"Opening TRACE(%s)\\n\",\n\t\t\t\tvcd_trace_file_name);\n\t\topentrace(vcd_trace_file_name);\n\t\tm_time_ps = 0;\n\t}\n\n\tvoid\tclose(void) {\n\t\tm_done = true;\n\t}\n\n\tvoid\ttick(void) {\n\t\tTESTB<Vmain>::tick(); // Clock.size = 4\n\t}\n\n\n\t// Evaluating clock clk\n\n\t// sim_clk_tick() will be called from TESTB<Vmain>::tick()\n\t//   following any falling edge of clock clk\n\tvirtual\tvoid\tsim_clk_tick(void) {\n\t\t// Default clock tick\n\t\t//\n\t\t// SIM.TICK tags go here for SIM.CLOCK=clk\n\t\t//\n\t\t// SIM.TICK from flash\n#ifdef\tFLASH_ACCESS\n\t\tm_core->i_flash_dat = m_flash->simtick(\n\t\t\tm_core->o_flash_cs_n,\n\t\t\tm_core->o_flash_sck,\n\t\t\tm_core->o_flash_dat,\n\t\t\tm_core->o_flash_mod);\n#endif // FLASH_ACCESS\n\t\t// SIM.TICK from i2c\n\t\tm_core->i_i2c_scl = m_core->o_i2c_scl;\n\t\tm_core->i_i2c_sda = m_core->o_i2c_sda;\n\t\t// SIM.TICK from wbu\n\t\tm_core->i_wbu_uart_rx = (*m_wbu)(m_core->o_wbu_uart_tx);\n\t\t// SIM.TICK from edid\n\t\tm_core->i_edid_scl = m_core->o_edid_scl;\n\t\tm_core->i_edid_sda = m_core->o_edid_sda;\n\t\t// SIM.TICK from pxclk\n\t\tm_core->i_pxclk_stall = 0;\n\t\tm_core->i_pxclk_ack   = m_core->o_pxclk_stb;\n\t\tm_core->i_pxclk_idata = m_core->o_pxclk_data;\n\t\t// SIM.TICK from sdio\n#ifdef\tSDIO_ACCESS\n\t\t{ unsigned\ttmp, tmp_async;\n\t\tm_sdio->apply(\n\t\t\t(unsigned)m_core->o_sdio_sdclk,\n\t\t\t(unsigned)m_core->o_sdio_cfg_ddr,\n\t\t\t(unsigned)m_core->o_sdio_cmd_en,\n\t\t\t(unsigned)m_core->o_sdio_cmd_data,\n\t\t\t(unsigned)m_core->o_sdio_data_en,\n\t\t\t(unsigned)m_core->o_sdio_rx_en,\n\t\t\t(unsigned)m_core->o_sdio_tx_data,\n\t\t\ttmp, tmp_async,\n\t\t\tm_core->i_sdio_ad_data);\n\t\tm_core->i_sdio_cmd_strb = (tmp >> 30) & 3;\n\t\tm_core->i_sdio_cmd_data = (tmp >> 28) & 3;\n\t\tm_core->i_sdio_rx_strb  = (tmp >> 24) & 3;\n\t\tm_core->i_sdio_rx_data  =  tmp & 0x0ffff;\n\t\tm_core->i_sdio_ac_valid = (tmp_async & 2) ? 1:0;\n\t\tm_core->i_sdio_ad_valid =  tmp_async & 1;\n\t\tm_core->i_sdio_detect = 1;\n\t\tm_core->i_sdio_card_busy = m_sdio->card_busy() ? 1:0;\n\t\tm_core->i_sdio_crcack = m_sdio->crctoken();\n\t\tm_core->i_sdio_crcnak = (m_core->i_sdio_crcack & 2)?1:0;\n\t\tm_core->i_sdio_crcack &= 1;\n\n\t\tif (!m_core->o_sdio_cfg_dscmd) {\n\t\t\tm_core->i_sdio_ac_valid = 0;\n\t\t\tm_core->i_sdio_ac_data = 0;\n\t\t} if (!m_core->o_sdio_cfg_ds) {\n\t\t\tm_core->i_sdio_ad_valid = 0;\n\t\t\tm_core->i_sdio_ad_data = 0;\n\t\t} }\n#endif\n\t\t// SIM.TICK from mdio\n#ifdef\tNETCTRL_ACCESS\n\t\tm_core->i_mdio = (*m_mdio)((m_core->i_reset)?1:0,\n\t\t\t\tm_core->o_mdclk,\n\t\t\t\t((m_core->o_mdwe)&&(!m_core->o_mdio))?0:1);\n#else\n\t\tm_core->i_mdio = ((m_core->o_mdwe)&&(!m_core->o_mdio))?0:1;\n#endif // NETCTRL_ACCESS\n\t\t// SIM.TICK from zip\n#ifdef\tINCLUDE_ZIPCPU\n\t\t// ZipCPU Sim instruction support\n\t\t// {{{\n\t\tif (m_cpu_bombed) {\n\t\t\tif (m_cpu_bombed++ > 12)\n\t\t\t\tm_done = true;\n\t\t} else if (m_core->cpu_break) {\n\t\t\tprintf(\"\\n\\nBOMB : CPU BREAK RECEIVED\\n\");\n\t\t\tm_cpu_bombed++;\n\t\t}\n\t\t// }}}\n#endif\t// INCLUDE_ZIPCPU\n\n\t}\n\n\t// Evaluating clock pixclk\n\n\t// sim_pixclk_tick() will be called from TESTB<Vmain>::tick()\n\t//   following any falling edge of clock pixclk\n\tvirtual\tvoid\tsim_pixclk_tick(void) {\n\t\t//\n\t\t// SIM.TICK tags go here for SIM.CLOCK=pixclk\n\t\t//\n\t\t// SIM.TICK from hdmi\n#ifdef\tVIDPIPE_ACCESS\n\t\t// Simulate both an external HDMI source and monitor\n\t\tif (gbl_use_gui) {\n\t\t\tint\tr, g, b;\n\n\t\t\t// HDMI input received by the design\n\t\t\t(*m_hdmirx)(b, g, r);\n\t\t\tm_core->i_hdmi_blu = b;\n\t\t\tm_core->i_hdmi_grn = g;\n\t\t\tm_core->i_hdmi_red = r;\n\n\t\t\tm_core->i_pxpll_locked = 1;\n\n\t\t\t// HDMI output, transmitted from the design\n\t\t\t(*m_hdmitx)(m_core->o_hdmi_blu, m_core->o_hdmi_grn,\n\t\t\t\t\tm_core->o_hdmi_red);\n\t\t}\n#endif\t// VIDPIPE_ACCESS\n\t}\n\n\t// Evaluating clock net_rx_clk\n\n\t// sim_net_rx_clk_tick() will be called from TESTB<Vmain>::tick()\n\t//   following any falling edge of clock net_rx_clk\n\tvirtual\tvoid\tsim_net_rx_clk_tick(void) {\n\t\t//\n\t\t// SIM.TICK tags go here for SIM.CLOCK=net_rx_clk\n\t\t//\n\t\t// SIM.TICK from net\n\t\t// Simulate the network\n\t\t// {{{\n\t\t{\n\t\t\tunsigned rxtmp = (*m_net)(m_core->o_net_reset_n,\n\t\t\t\t\tm_core->o_net_tx_ctl,\n\t\t\t\t\tm_core->o_net_txd);\n\n\t\t\tm_core->i_net_rx_err = 0;\n\t\t\tif (rxtmp & 0x0100) {\n\t\t\t\tm_core->i_net_rx_dv  = 1;\n\t\t\t\tm_core->i_net_rxd = rxtmp & 0x0ff;\n\t\t\t} else {\n\t\t\t\tm_core->i_net_rx_dv  = 0;\n\t\t\t\tm_core->i_net_rxd = 0x044;\n\t\t\t}\n\t\t}\n\t\t// }}}\n\t}\n\n\t// Evaluating clock clk_125mhz\n\n\t// sim_clk_125mhz_tick() will be called from TESTB<Vmain>::tick()\n\t//   following any falling edge of clock clk_125mhz\n\tvirtual\tvoid\tsim_clk_125mhz_tick(void) {\n\t\t//\n\t\t// SIM.TICK tags go here for SIM.CLOCK=clk_125mhz\n\t\t//\n\t\t// No SIM.TICK tags defined\n\t\tm_changed = false;\n\t}\n\t//\n\t// Step until clock clk ticks\n\t//\n\tvirtual\tvoid\ttick_clk(void) {\n\t\t// Advance until the default clock ticks\n\t\tdo {\n\t\t\ttick();\n\t\t} while(!m_clk.rising_edge());\n\t}\n\n\t//\n\t// Step until clock pixclk ticks\n\t//\n\tvirtual\tvoid\ttick_pixclk(void) {\n\t\tdo {\n\t\t\ttick();\n\t\t} while(!m_pixclk.rising_edge());\n\t}\n\n\t//\n\t// Step until clock net_rx_clk ticks\n\t//\n\tvirtual\tvoid\ttick_net_rx_clk(void) {\n\t\tdo {\n\t\t\ttick();\n\t\t} while(!m_net_rx_clk.rising_edge());\n\t}\n\n\t//\n\t// Step until clock clk_125mhz ticks\n\t//\n\tvirtual\tvoid\ttick_clk_125mhz(void) {\n\t\tdo {\n\t\t\ttick();\n\t\t} while(!m_clk_125mhz.rising_edge());\n\t}\n\n\t//\n\t// The load function\n\t//\n\t// This function is required by designs that need the flash or memory\n\t// set prior to run time.  The test harness should be able to call\n\t// this function to load values into any (memory-type) location\n\t// on the bus.\n\t//\n\tbool\tload(uint32_t addr, const char *buf, uint32_t len) {\n\t\tuint32_t\tstart, offset, wlen, base, adrln;\n\n\t\t//\n\t\t// Loading the flash component\n\t\t//\n\t\tbase  = 0x01000000; // in octets\n\t\tadrln = 0x01000000;\n\n\t\tif ((addr >= base)&&(addr < base + adrln)) {\n\t\t\t// If the start access is in flash\n\t\t\tstart = (addr > base) ? (addr-base) : 0;\n\t\t\toffset = (start + base) - addr;\n\t\t\twlen = (len-offset > adrln - start)\n\t\t\t\t? (adrln - start) : len - offset;\n#ifdef\tFLASH_ACCESS\n\t\t\t// FROM flash.SIM.LOAD\n\t\t\tm_flash->load(start, &buf[offset], wlen);\n\t\t\t// AUTOFPGA::Now clean up anything else\n\t\t\t// Was there more to write than we wrote?\n\t\t\tif (addr + len > base + adrln)\n\t\t\t\treturn load(base + adrln, &buf[offset+wlen], len-wlen);\n\t\t\treturn true;\n#else\t// FLASH_ACCESS\n\t\t\treturn false;\n#endif\t// FLASH_ACCESS\n\t\t//\n\t\t// End of components with a SIM.LOAD tag, and a\n\t\t// non-zero number of addresses (NADDR)\n\t\t//\n\t\t}\n\n\t\t//\n\t\t// Loading the bkram component\n\t\t//\n\t\tbase  = 0x10000000; // in octets\n\t\tadrln = 0x00100000;\n\n\t\tif ((addr >= base)&&(addr < base + adrln)) {\n\t\t\t// If the start access is in bkram\n\t\t\tstart = (addr > base) ? (addr-base) : 0;\n\t\t\toffset = (start + base) - addr;\n\t\t\twlen = (len-offset > adrln - start)\n\t\t\t\t? (adrln - start) : len - offset;\n#ifdef\tBKRAM_ACCESS\n\t\t\t// FROM bkram.SIM.LOAD\n\t\t\tstart = start & (-4);\n\t\t\twlen = (wlen+3)&(-4);\n\n\t\t\t// Need to byte swap data to get it into the memory\n\t\t\tif (128 == 32) {\n\t\t\t\tchar\t*bswapd = new char[len+8];\n\t\t\t\tmemcpy(bswapd, &buf[offset], wlen);\n\t\t\t\tbyteswapbuf(len>>2, (uint32_t *)bswapd);\n\t\t\t\tmemcpy(&m_core->block_ram[start], bswapd, wlen);\n\t\t\t\tdelete[] bswapd;\n\t\t\t} else {\n\t\t\t\tfor(unsigned jk=0; jk<wlen; jk=jk+1) {\n\t\t\t\t\tunsigned word_addr, subword_addr;\n\t\t\t\t\tunsigned\t*wp;\n\t\t\t\t\tchar\t\t*cp;\n\n\t\t\t\t\tword_addr = start+jk;\n\t\t\t\t\tword_addr /= 128/8;\n\t\t\t\t\twp = m_core->block_ram[word_addr];\n\t\t\t\t\tcp = (char *)wp;\n\n\t\t\t\t\tsubword_addr = start+jk;\n\t\t\t\t\tsubword_addr = ~subword_addr;\n\t\t\t\t\tsubword_addr &= 128/8-1;\n\t\t\t\t\t// subword_addr = 128/8-subword_addr;\n\t\t\t\t\tcp[subword_addr] = buf[offset+jk];\n\t\t\t\t}\n\t\t\t}\n\t\t\t// AUTOFPGA::Now clean up anything else\n\t\t\t// Was there more to write than we wrote?\n\t\t\tif (addr + len > base + adrln)\n\t\t\t\treturn load(base + adrln, &buf[offset+wlen], len-wlen);\n\t\t\treturn true;\n#else\t// BKRAM_ACCESS\n\t\t\treturn false;\n#endif\t// BKRAM_ACCESS\n\t\t//\n\t\t// End of components with a SIM.LOAD tag, and a\n\t\t// non-zero number of addresses (NADDR)\n\t\t//\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t//\n\t// KYSIM.METHODS\n\t//\n\t// If your simulation code will need to call any of its own function\n\t// define this tag by those functions (or other sim code), and\n\t// it will be pasated here.\n\t//\n\tvoid\tconnect_idler(void) {\n\t\tGlib::signal_idle().connect(\n\t\t\tsigc::mem_fun((*this),&MAINTB::on_tick));\n\t}\n\n\tbool\ton_tick(void) {\n\t\tfor(int i=0; i<15; i++)\n\t\t\ttick();\n\t\treturn true;\n\t}\n#ifdef\tINCLUDE_ZIPCPU\n\t// ZipCPU Access functions\n\t// {{{\n\tvoid\tloadelf(const char *elfname) {\n\t\t// {{{\n\t\tELFSECTION\t**secpp, *secp;\n\t\tuint32_t\tentry;\n\n\t\telfread(elfname, entry, secpp);\n\n\t\tfor(int s=0; secpp[s]->m_len; s++) {\n\t\t\tbool\tsuccessful_load;\n\t\t\tsecp = secpp[s];\n\n\t\t\tsuccessful_load = load(secp->m_start,\n\t\t\t\tsecp->m_data, secp->m_len);\n\n\t\t\tif (!successful_load) {\n\t\t\t\tprintf(\"Could not load section \"\n\t\t\t\t\t\"from %08x to %08x--no such address\\n\",\n\t\t\t\t\tsecp->m_start,\n\t\t\t\t\tsecp->m_start+secp->m_len);\n\t\t\t}\n\t\t} free(secpp);\n\t}\n\t// }}}\n\n\tvoid\tcpu_dbg_write(const uint32_t addr, const uint32_t data) {\n\t\t// {{{\n\t\t// printf(\"CPU-DBG-WRITE(@0x%08x, 0x%08x);\\n\", addr, data);\n\t\tm_core->cpu_sim_cyc   = 1;\n\t\tm_core->cpu_sim_stb   = 1;\n\t\tm_core->cpu_sim_we    = 1;\n\t\tm_core->cpu_sim_addr  = addr >> 2;\n\t\tm_core->cpu_sim_data  = data;\n\n\t\tdo {\n\t\t\ttick_clk();\n\t\t} while(m_core->cpu_sim_stall);\n\n\t\tm_core->cpu_sim_stb = 0;\n\n\t\twhile(!m_core->cpu_sim_ack)\n\t\t\ttick_clk();\n\n\t\tm_core->cpu_sim_cyc  = 0;\n\t\tm_core->cpu_sim_we   = 0;\n\t\tm_core->cpu_sim_addr = 0;\n\t\tm_core->cpu_sim_data = 0;\n\n\t\ttick_clk();\n\t}\n\t// }}}\n\n\tuint32_t cpu_dbg_read(const uint32_t addr) {\n\t\t// {{{\n\t\tunsigned\tresult;\n\n\t\t// printf(\"CPU-DBG-WRITE(@0x%08x, 0x%08x);\\n\", addr, data);\n\t\tm_core->cpu_sim_cyc   = 1;\n\t\tm_core->cpu_sim_stb   = 1;\n\t\tm_core->cpu_sim_we    = 0;\n\t\tm_core->cpu_sim_addr  = addr >> 2;\n\t\tm_core->cpu_sim_data  = 0;\n\n\t\tdo {\n\t\t\ttick_clk();\n\t\t} while(m_core->cpu_sim_stall);\n\n\t\tm_core->cpu_sim_stb = 0;\n\n\t\twhile(!m_core->cpu_sim_ack)\n\t\t\ttick_clk();\n\n\t\tresult = m_core->cpu_sim_idata;\n\n\t\tm_core->cpu_sim_cyc  = 0;\n\t\tm_core->cpu_sim_we   = 0;\n\t\tm_core->cpu_sim_addr = 0;\n\t\tm_core->cpu_sim_data = 0;\n\n\t\ttick_clk();\n\n\t\treturn result;\n\t}\n\t// }}}\n\n\t// }}}\n#endif // INCLUDE_ZIPCPU\n\n};\n"
  },
  {
    "path": "demo-out/regdefs.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\t../demo-out/regdefs.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Computer Generated: This file is computer generated by AUTOFPGA. DO NOT EDIT.\n// DO NOT EDIT THIS FILE!\n//\n// CmdLine:\t./autofpga -d -o ../demo-out -I ../auto-data allclocks.txt bkram.txt buserr.txt clkcheck.txt crossbus.txt ddr3.txt edidslvscope.txt edid.txt exconsole.txt flashcfg.txt flash.txt global.txt gpio.txt gps.txt hdmi.txt i2ccpu.txt i2cdma.txt i2saudio.txt icape.txt meganet.txt mdio.txt pic.txt pwrcount.txt rtcdate.txt rtcgps.txt spio.txt sdio.txt vadj33.txt version.txt wboledbw.txt wbpmic.txt wbuarbiter.txt wbubus.txt zipcpu.txt zipmaster.txt\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdio.h>\n#include <stdlib.h>\n#include <strings.h>\n#include <ctype.h>\n#include \"regdefs.h\"\n\nconst\tREGNAME\traw_bregs[] = {\n\t{ R_SDIO_CTRL       ,\t\"SDCARD\"          \t},\n\t{ R_SDIO_DATA       ,\t\"SDDATA\"          \t},\n\t{ R_SDIO_FIFOA      ,\t\"SDFIFOA\"         \t},\n\t{ R_SDIO_FIFOA      ,\t\"SDFIF0\"          \t},\n\t{ R_SDIO_FIFOA      ,\t\"SDFIFA\"          \t},\n\t{ R_SDIO_FIFOB      ,\t\"SDFIFOB\"         \t},\n\t{ R_SDIO_FIFOB      ,\t\"SDFIF1\"          \t},\n\t{ R_SDIO_FIFOB      ,\t\"SDFIFB\"          \t},\n\t{ R_SDIO_PHY        ,\t\"SDPHY\"           \t},\n\t{ R_FLASH           ,\t\"FLASH\"           \t},\n\t{ R_FLASHCFG        ,\t\"FLASHCFG\"        \t},\n\t{ R_FLASHCFG        ,\t\"QSPIC\"           \t},\n\t{ R_EDIDSLVSCOPE    ,\t\"EDIDSLVSCOPE\"    \t},\n\t{ R_EDIDSLVSCOPED   ,\t\"EDIDSLVSCOPED\"   \t},\n\t{ R_MIC_DATA        ,\t\"MICD\"            \t},\n\t{ R_MIC_CTRL        ,\t\"MICC\"            \t},\n\t{ R_GPSU_SETUP      ,\t\"GPSSETUP\"        \t},\n\t{ R_GPSU_FIFO       ,\t\"GPSFIFO\"         \t},\n\t{ R_GPSU_UARTRX     ,\t\"GPSRX\"           \t},\n\t{ R_GPSU_UARTTX     ,\t\"GPSTX\"           \t},\n\t{ R_CFG_CRC         ,\t\"FPGACRC\"         \t},\n\t{ R_CFG_FAR         ,\t\"FPGAFAR\"         \t},\n\t{ R_CFG_FDRI        ,\t\"FPGAFDRI\"        \t},\n\t{ R_CFG_FDRO        ,\t\"FPGAFDRO\"        \t},\n\t{ R_CFG_CMD         ,\t\"FPGACMD\"         \t},\n\t{ R_CFG_CTL0        ,\t\"FPGACTL0\"        \t},\n\t{ R_CFG_MASK        ,\t\"FPGAMASK\"        \t},\n\t{ R_CFG_STAT        ,\t\"FPGASTAT\"        \t},\n\t{ R_CFG_LOUT        ,\t\"FPGALOUT\"        \t},\n\t{ R_CFG_COR0        ,\t\"FPGACOR0\"        \t},\n\t{ R_CFG_MFWR        ,\t\"FPGAMFWR\"        \t},\n\t{ R_CFG_CBC         ,\t\"FPGACBC\"         \t},\n\t{ R_CFG_IDCODE      ,\t\"FPGAIDCODE\"      \t},\n\t{ R_CFG_AXSS        ,\t\"FPGAAXSS\"        \t},\n\t{ R_CFG_COR1        ,\t\"FPGACOR1\"        \t},\n\t{ R_CFG_WBSTAR      ,\t\"WBSTAR\"          \t},\n\t{ R_CFG_TIMER       ,\t\"CFGTIMER\"        \t},\n\t{ R_CFG_BOOTSTS     ,\t\"BOOTSTS\"         \t},\n\t{ R_CFG_CTL1        ,\t\"FPGACTL1\"        \t},\n\t{ R_CFG_BSPI        ,\t\"FPGABSPI\"        \t},\n\t{ R_MEGANET_RXCMD   ,\t\"MEGANETRX\"       \t},\n\t{ R_MEGANET_TXCMD   ,\t\"MEGANETTX\"       \t},\n\t{ R_MEGANET_MACHI   ,\t\"MEGANETMACHI\"    \t},\n\t{ R_MEGANET_MACLO   ,\t\"MEGANETMACLO\"    \t},\n\t{ R_MEGANET_IPADDR  ,\t\"MEGANETIPADDR\"   \t},\n\t{ R_MEGANET_IPADDR  ,\t\"MEGANETIP\"       \t},\n\t{ R_MEGANET_RXMISS  ,\t\"MEGANETMISS\"     \t},\n\t{ R_MEGANET_RXERR   ,\t\"MEGANETERR\"      \t},\n\t{ R_MEGANET_RXCRC   ,\t\"MEGANETCRCER\"    \t},\n\t{ R_MEGANET_DBGSEL  ,\t\"MEGANETDBGSL\"    \t},\n\t{ R_MEGANET_RXPKTS  ,\t\"MEGANETRXPKT\"    \t},\n\t{ R_MEGANET_ARPRX   ,\t\"MEGANETARPRX\"    \t},\n\t{ R_MEGANET_ICMPRX  ,\t\"MEGANETICMRX\"    \t},\n\t{ R_MEGANET_TXPKTS  ,\t\"MEGANETTXPKT\"    \t},\n\t{ R_MEGANET_ARPTX   ,\t\"MEGANETARPTX\"    \t},\n\t{ R_MEGANET_ICMPTX  ,\t\"MEGANETICMTX\"    \t},\n\t{ R_MEGANET_DATATX  ,\t\"MEGANETDATTX\"    \t},\n\t{ R_MEGANET_TXABORTS,\t\"MEGANETABRTS\"    \t},\n\t{ R_MEGANET_DBGRX   ,\t\"MEGANETDBGRX\"    \t},\n\t{ R_MEGANET_DBGTX   ,\t\"MEGANETDBGTX\"    \t},\n\t{ R_DDR3_PHY        ,\t\"DDR3_PHY\"        \t},\n\t{ R_DDR3_PHY        ,\t\"DPHYSTAT0\"       \t},\n\t{ R_DDR3_PHYSTAT1   ,\t\"DDR3_PHYSTAT1\"   \t},\n\t{ R_DDR3_PHYSTAT1   ,\t\"DPHYSTAT1\"       \t},\n\t{ R_DDR3_PHYSTAT2   ,\t\"DDR3_PHYSTAT2\"   \t},\n\t{ R_DDR3_PHYSTAT2   ,\t\"DPHYSTAT2\"       \t},\n\t{ R_DDR3_PHYSTAT3   ,\t\"DDR3_PHYSTAT3\"   \t},\n\t{ R_DDR3_PHYSTAT3   ,\t\"DPHYSTAT3\"       \t},\n\t{ R_DDR3_PHYCTRLSTAT,\t\"DDR3_PHYCTRLSTAT\"\t},\n\t{ R_DDR3_PHYCTRLSTAT,\t\"DCTRLSTAT\"       \t},\n\t{ R_DDR3_PHYRESET   ,\t\"DDR3_PHYRESET\"   \t},\n\t{ R_DDR3_PHYRESET   ,\t\"DCTRLRESET\"      \t},\n\t{ R_DDR3_PHYDBGSEL  ,\t\"DDR3_PHYDBGSEL\"  \t},\n\t{ R_DDR3_PHYDBGSEL  ,\t\"DCTRLDBG\"        \t},\n\t{ R_PXPLL           ,\t\"PXPLL\"           \t},\n\t{ R_EDID            ,\t\"EDID\"            \t},\n\t{ R_EDID            ,\t\"EDID_CTRL\"       \t},\n\t{ R_EDID            ,\t\"EDIDCTRL\"        \t},\n\t{ R_EDID_OVW        ,\t\"EDID_OVW\"        \t},\n\t{ R_EDID_OVW        ,\t\"EDID_OVERRIDE\"   \t},\n\t{ R_EDID_ADDR       ,\t\"EDID_ADDR\"       \t},\n\t{ R_EDID_ADDR       ,\t\"EDID_ADDRESS\"    \t},\n\t{ R_EDID_CKCOUNT    ,\t\"EDIDCLK\"         \t},\n\t{ R_EDID_CKCOUNT    ,\t\"EDID_CKCOUNT\"    \t},\n\t{ R_GPS_ALPHA       ,\t\"ALPHA\"           \t},\n\t{ R_GPS_BETA        ,\t\"BETA\"            \t},\n\t{ R_GPS_GAMMA       ,\t\"GAMMA\"           \t},\n\t{ R_GPS_STEP        ,\t\"STEP\"            \t},\n\t{ R_I2CCPU          ,\t\"I2CCPU\"          \t},\n\t{ R_I2CCPU          ,\t\"I2CCPU_CTRL\"     \t},\n\t{ R_I2CCPU          ,\t\"I2CCPUCTRL\"      \t},\n\t{ R_I2CCPU_OVW      ,\t\"I2CCPU_OVW\"      \t},\n\t{ R_I2CCPU_OVW      ,\t\"I2CCPU_OVERRIDE\" \t},\n\t{ R_I2CCPU_ADDR     ,\t\"I2CCPU_ADDR\"     \t},\n\t{ R_I2CCPU_ADDR     ,\t\"I2CCPU_ADDRESS\"  \t},\n\t{ R_I2CCPU_CKCOUNT  ,\t\"I2CCPUCLK\"       \t},\n\t{ R_I2CCPU_CKCOUNT  ,\t\"I2CCPU_CKCOUNT\"  \t},\n\t{ R_I2CDMA          ,\t\"I2CDMA\"          \t},\n\t{ R_I2CDMA_ADDR     ,\t\"I2CDMAADDR\"      \t},\n\t{ R_I2CDMA_BASE     ,\t\"I2CDMABASE\"      \t},\n\t{ R_I2CDMA_LEN      ,\t\"I2CDMALEN\"       \t},\n\t{ R_OLED            ,\t\"OLED\"            \t},\n\t{ R_OLED_OV         ,\t\"OLEDOV\"          \t},\n\t{ R_OLED_ADDR       ,\t\"OLEDADDR\"        \t},\n\t{ R_OLED_CLK        ,\t\"OLEDCLK\"         \t},\n\t{ R_CLOCK           ,\t\"CLOCK\"           \t},\n\t{ R_TIMER           ,\t\"TIMER\"           \t},\n\t{ R_STOPWATCH       ,\t\"STOPWATCH\"       \t},\n\t{ R_CKALARM         ,\t\"ALARM\"           \t},\n\t{ R_CKALARM         ,\t\"CKALARM\"         \t},\n\t{ R_GPSTB_FREQ      ,\t\"GPSFREQ\"         \t},\n\t{ R_GPSTB_JUMP      ,\t\"GPSJUMP\"         \t},\n\t{ R_GPSTB_ERRHI     ,\t\"ERRHI\"           \t},\n\t{ R_GPSTB_ERRLO     ,\t\"ERRLO\"           \t},\n\t{ R_GPSTB_COUNTHI   ,\t\"CNTHI\"           \t},\n\t{ R_GPSTB_COUNTLO   ,\t\"CNTLO\"           \t},\n\t{ R_GPSTB_STEPHI    ,\t\"STEPHI\"          \t},\n\t{ R_GPSTB_STEPLO    ,\t\"STEPLO\"          \t},\n\t{ R_ADCCLK          ,\t\"ADCCLK\"          \t},\n\t{ R_BUILDTIME       ,\t\"BUILDTIME\"       \t},\n\t{ R_BUILDTIME       ,\t\"BUILDTIME\"       \t},\n\t{ R_BUSERR          ,\t\"BUSERR\"          \t},\n\t{ R_PIC             ,\t\"PIC\"             \t},\n\t{ R_GPIO            ,\t\"GPIO\"            \t},\n\t{ R_GPIO            ,\t\"GPI\"             \t},\n\t{ R_GPIO            ,\t\"GPO\"             \t},\n\t{ R_PWRCOUNT        ,\t\"PWRCOUNT\"        \t},\n\t{ R_RTCDATE         ,\t\"RTCDATE\"         \t},\n\t{ R_RTCDATE         ,\t\"DATE\"            \t},\n\t{ R_RXETH0CK        ,\t\"RXETH0CK\"        \t},\n\t{ R_SPIO            ,\t\"SPIO\"            \t},\n\t{ R_SUBSECONDS      ,\t\"SUBSECONDS\"      \t},\n\t{ R_TXCLK           ,\t\"TXCLK\"           \t},\n\t{ R_VERSION         ,\t\"VERSION\"         \t},\n\t{ R_EDIDRX          ,\t\"EDIDRX\"          \t},\n\t{ R_VIDPIPE         ,\t\"VIDPIPE\"         \t},\n\t{ R_VIDPIPE         ,\t\"VIDCTRL\"         \t},\n\t{ R_HDMIFREQ        ,\t\"HDMIFREQ\"        \t},\n\t{ R_SIFREQ          ,\t\"SIFREQ\"          \t},\n\t{ R_PXFREQ          ,\t\"PXFREQ\"          \t},\n\t{ R_INSIZE          ,\t\"INSIZE\"          \t},\n\t{ R_INPORCH         ,\t\"INPORCH\"         \t},\n\t{ R_INSYNC          ,\t\"INSYNC\"          \t},\n\t{ R_INRAW           ,\t\"INRAW\"           \t},\n\t{ R_HDMISIZE        ,\t\"HDMISIZE\"        \t},\n\t{ R_HDMIPORCH       ,\t\"HDMIPORCH\"       \t},\n\t{ R_HDMISYNC        ,\t\"HDMISYNC\"        \t},\n\t{ R_HDMIRAW         ,\t\"HDMIRAW\"         \t},\n\t{ R_OVADDR          ,\t\"OVADDR\"          \t},\n\t{ R_OVSIZE          ,\t\"OVSIZE\"          \t},\n\t{ R_OVOFFSET        ,\t\"OVOFFSET\"        \t},\n\t{ R_FPS             ,\t\"FPS\"             \t},\n\t{ R_CAPTURE         ,\t\"VCAPTURE\"        \t},\n\t{ R_CAPBASE         ,\t\"VCAPBASE\"        \t},\n\t{ R_CAPWORDS        ,\t\"VCAPWORDS\"       \t},\n\t{ R_CAPPOSN         ,\t\"VCAPPOSN\"        \t},\n\t{ R_CAPSIZE         ,\t\"VCAPSIZE\"        \t},\n\t{ R_SYNCWORD        ,\t\"VSYNCWORD\"       \t},\n\t{ R_CMAP            ,\t\"CMAP\"            \t},\n\t{ R_MDIO_BMCR       ,\t\"BMCR\"            \t},\n\t{ R_MDIO_BMSR       ,\t\"BMSR\"            \t},\n\t{ R_MDIO_PHYIDR1    ,\t\"PHYIDR1\"         \t},\n\t{ R_MDIO_PHYIDR2    ,\t\"PHYIDR2\"         \t},\n\t{ R_MDIO_ANAR       ,\t\"ANAR\"            \t},\n\t{ R_MDIO_ANLPAR     ,\t\"ANLPAR\"          \t},\n\t{ R_MDIO_ANER       ,\t\"ANER\"            \t},\n\t{ R_MDIO_ANNPTR     ,\t\"ANNPTR\"          \t},\n\t{ R_MDIO_ANNPRR     ,\t\"ANNPRR\"          \t},\n\t{ R_MDIO_GBCR       ,\t\"GBCR\"            \t},\n\t{ R_MDIO_GBSR       ,\t\"GBSR\"            \t},\n\t{ R_MDIO_MACR       ,\t\"MACR\"            \t},\n\t{ R_MDIO_MAADR      ,\t\"MAADR\"           \t},\n\t{ R_MDIO_GBESR      ,\t\"GBESR\"           \t},\n\t{ R_MDIO_PHYCR      ,\t\"PHYCR\"           \t},\n\t{ R_MDIO_PHYSR      ,\t\"PHYSR\"           \t},\n\t{ R_MDIO_INER       ,\t\"INER\"            \t},\n\t{ R_MDIO_INSR       ,\t\"INSR\"            \t},\n\t{ R_MDIO_RXERC      ,\t\"RXERC\"           \t},\n\t{ R_MDIO_LDPSR      ,\t\"LDPSR\"           \t},\n\t{ R_MDIO_EPAGSR     ,\t\"EPAGSR\"          \t},\n\t{ R_MDIO_PAGSEL     ,\t\"PAGSEL\"          \t},\n\t{ R_XMDIO_PC1R      ,\t\"XPC1R\"           \t},\n\t{ R_XMDIO_PS1R      ,\t\"XPS1R\"           \t},\n\t{ R_XMDIO_EEECR     ,\t\"XEEECR\"          \t},\n\t{ R_XMDIO_EEEWER    ,\t\"XEEEWER\"         \t},\n\t{ R_XMDIO_EEEAR     ,\t\"XEEEAR\"          \t},\n\t{ R_XMDIO_EEELPAR   ,\t\"XEEELPAR\"        \t},\n\t{ R_XMDIO_LACR      ,\t\"XLACR\"           \t},\n\t{ R_XMDIO_LCR       ,\t\"XLCR\"            \t},\n\t{ R_BKRAM           ,\t\"RAM\"             \t},\n\t{ R_SDRAM           ,\t\"SDRAM\"           \t},\n\t{ R_ZIPCTRL         ,\t\"CPU\"             \t},\n\t{ R_ZIPCTRL         ,\t\"ZIPCTRL\"         \t},\n\t{ R_ZIPREGS         ,\t\"ZIPREGS\"         \t},\n\t{ R_ZIPS0           ,\t\"SR0\"             \t},\n\t{ R_ZIPS1           ,\t\"SR1\"             \t},\n\t{ R_ZIPS2           ,\t\"SR2\"             \t},\n\t{ R_ZIPS3           ,\t\"SR3\"             \t},\n\t{ R_ZIPS4           ,\t\"SR4\"             \t},\n\t{ R_ZIPS5           ,\t\"SR5\"             \t},\n\t{ R_ZIPS6           ,\t\"SR6\"             \t},\n\t{ R_ZIPS7           ,\t\"SR7\"             \t},\n\t{ R_ZIPS8           ,\t\"SR8\"             \t},\n\t{ R_ZIPS9           ,\t\"SR9\"             \t},\n\t{ R_ZIPS10          ,\t\"SR10\"            \t},\n\t{ R_ZIPS11          ,\t\"SR11\"            \t},\n\t{ R_ZIPS12          ,\t\"SR12\"            \t},\n\t{ R_ZIPSSP          ,\t\"SSP\"             \t},\n\t{ R_ZIPSSP          ,\t\"SR13\"            \t},\n\t{ R_ZIPCC           ,\t\"ZIPCC\"           \t},\n\t{ R_ZIPCC           ,\t\"CC\"              \t},\n\t{ R_ZIPCC           ,\t\"SCC\"             \t},\n\t{ R_ZIPCC           ,\t\"SR14\"            \t},\n\t{ R_ZIPPC           ,\t\"ZIPPC\"           \t},\n\t{ R_ZIPPC           ,\t\"PC\"              \t},\n\t{ R_ZIPPC           ,\t\"SPC\"             \t},\n\t{ R_ZIPPC           ,\t\"SR15\"            \t},\n\t{ R_ZIPUSER         ,\t\"ZIPUSER\"         \t},\n\t{ R_ZIPU0           ,\t\"UR0\"             \t},\n\t{ R_ZIPU1           ,\t\"UR1\"             \t},\n\t{ R_ZIPU2           ,\t\"UR2\"             \t},\n\t{ R_ZIPU3           ,\t\"UR3\"             \t},\n\t{ R_ZIPU4           ,\t\"UR4\"             \t},\n\t{ R_ZIPU5           ,\t\"UR5\"             \t},\n\t{ R_ZIPU6           ,\t\"UR6\"             \t},\n\t{ R_ZIPU7           ,\t\"UR7\"             \t},\n\t{ R_ZIPU8           ,\t\"UR8\"             \t},\n\t{ R_ZIPU9           ,\t\"UR9\"             \t},\n\t{ R_ZIPU10          ,\t\"SR10\"            \t},\n\t{ R_ZIPU11          ,\t\"SR11\"            \t},\n\t{ R_ZIPU12          ,\t\"SR12\"            \t},\n\t{ R_ZIPUSP          ,\t\"USP\"             \t},\n\t{ R_ZIPUSP          ,\t\"UR13\"            \t},\n\t{ R_ZIPUCC          ,\t\"ZIPUCC\"          \t},\n\t{ R_ZIPUCC          ,\t\"UCC\"             \t},\n\t{ R_ZIPUPC          ,\t\"ZIPUPC\"          \t},\n\t{ R_ZIPUPC          ,\t\"UPC\"             \t},\n\t{ R_ZIPSYSTEM       ,\t\"ZIPSYSTEM\"       \t},\n\t{ R_ZIPSYSTEM       ,\t\"ZIPSYS\"          \t},\n\t{ R_ZIPWATCHDOG     ,\t\"ZIPWATCHDOG\"     \t},\n\t{ R_ZIPBUSDOG       ,\t\"BUSDOG\"          \t},\n\t{ R_ZIPAPIC         ,\t\"ZIPAPIC\"         \t},\n\t{ R_ZIPAPIC         ,\t\"ALTPIC\"          \t},\n\t{ R_ZIPTIMERA       ,\t\"ZIPTMA\"          \t},\n\t{ R_ZIPTIMERA       ,\t\"ZIPTIMERA\"       \t},\n\t{ R_ZIPTIMERB       ,\t\"ZIPTMB\"          \t},\n\t{ R_ZIPTIMERB       ,\t\"ZIPTIMERB\"       \t},\n\t{ R_ZIPTIMERC       ,\t\"ZIPTMC\"          \t},\n\t{ R_ZIPTIMERC       ,\t\"ZIPTIMERC\"       \t},\n\t{ R_ZIPJIFFIES      ,\t\"ZIPJIFF\"         \t},\n\t{ R_ZIPMTASK        ,\t\"ZIPMTASK\"        \t},\n\t{ R_ZIPMSTALL       ,\t\"ZIPMSTALL\"       \t},\n\t{ R_ZIPMPSTAL       ,\t\"ZIPMPSTAL\"       \t},\n\t{ R_ZIPMINSN        ,\t\"ZIPMINSN\"        \t},\n\t{ R_ZIPUTASK        ,\t\"ZIPUTASK\"        \t},\n\t{ R_ZIPUSTALL       ,\t\"ZIPUSTALL\"       \t},\n\t{ R_ZIPUPSTAL       ,\t\"ZIPUPSTAL\"       \t},\n\t{ R_ZIPUINSN        ,\t\"ZIPUINSN\"        \t},\n\t{ R_ZIPUDMAC        ,\t\"ZIPDMAC\"         \t}\n};\n\n// REGSDEFS.CPP.INSERT for any bus masters\n// And then from the peripherals\n// And finally any master REGS.CPP.INSERT tags\n#define\tRAW_NREGS\t(sizeof(raw_bregs)/sizeof(bregs[0]))\n\nconst\tREGNAME\t\t*bregs = raw_bregs;\nconst\tint\tNREGS = RAW_NREGS;\n\nunsigned\taddrdecode(const char *v) {\n\tif (isalpha(v[0])) {\n\t\tfor(int i=0; i<NREGS; i++)\n\t\t\tif (strcasecmp(v, bregs[i].m_name)==0)\n\t\t\t\treturn bregs[i].m_addr;\n\t\tfprintf(stderr, \"Unknown register: %s\\n\", v);\n\t\texit(-2);\n\t} else\n\t\treturn strtoul(v, NULL, 0);\n}\n\nconst\tchar *addrname(const unsigned v) {\n\tfor(int i=0; i<NREGS; i++)\n\t\tif (bregs[i].m_addr == v)\n\t\t\treturn bregs[i].m_name;\n\treturn NULL;\n}\n\n"
  },
  {
    "path": "demo-out/regdefs.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\t../demo-out/regdefs.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Computer Generated: This file is computer generated by AUTOFPGA. DO NOT EDIT.\n// DO NOT EDIT THIS FILE!\n//\n// CmdLine:\t./autofpga -d -o ../demo-out -I ../auto-data allclocks.txt bkram.txt buserr.txt clkcheck.txt crossbus.txt ddr3.txt edidslvscope.txt edid.txt exconsole.txt flashcfg.txt flash.txt global.txt gpio.txt gps.txt hdmi.txt i2ccpu.txt i2cdma.txt i2saudio.txt icape.txt meganet.txt mdio.txt pic.txt pwrcount.txt rtcdate.txt rtcgps.txt spio.txt sdio.txt vadj33.txt version.txt wboledbw.txt wbpmic.txt wbuarbiter.txt wbubus.txt zipcpu.txt zipmaster.txt\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tREGDEFS_H\n#define\tREGDEFS_H\n\n\n//\n// The @REGDEFS.H.INCLUDE tag\n//\n// @REGDEFS.H.INCLUDE for masters\n// @REGDEFS.H.INCLUDE for peripherals\n#ifndef\tFPGAPORT\n#define\tFPGAPORT\t6782\n#define\tUARTDBGPORT\t6782\n#define\tUARTPORT\t6783\n#define\tUDP_DBGPORT\t6784\n#define\tUDP_DATAPORT\t6785\n#endif\n// And finally any master REGDEFS.H.INCLUDE tags\n// End of definitions from REGDEFS.H.INCLUDE\n\n\n//\n// Register address definitions, from @REGS.#d\n//\n// SDIO SD Card addresses\n#define\tR_SDIO_CTRL       \t0x00800000\t// 00800000, wbregs names: SDCARD\n#define\tR_SDIO_DATA       \t0x00800004\t// 00800000, wbregs names: SDDATA\n#define\tR_SDIO_FIFOA      \t0x00800008\t// 00800000, wbregs names: SDFIFOA, SDFIF0, SDFIFA\n#define\tR_SDIO_FIFOB      \t0x0080000c\t// 00800000, wbregs names: SDFIFOB, SDFIF1, SDFIFB\n#define\tR_SDIO_PHY        \t0x00800010\t// 00800000, wbregs names: SDPHY\n#define\tR_FLASH           \t0x01000000\t// 01000000, wbregs names: FLASH\n// FLASH erase/program configuration registers\n#define\tR_FLASHCFG        \t0x08000400\t// 08000400, wbregs names: FLASHCFG, QSPIC\n// edidslvscope compressed scope\n#define\tR_EDIDSLVSCOPE    \t0x08000600\t// 08000600, wbregs names: EDIDSLVSCOPE\n#define\tR_EDIDSLVSCOPED   \t0x08000604\t// 08000600, wbregs names: EDIDSLVSCOPED\n// WB-Microphone registers\n#define\tR_MIC_DATA        \t0x08000800\t// 08000800, wbregs names: MICD\n#define\tR_MIC_CTRL        \t0x08000804\t// 08000800, wbregs names: MICC\n// GPS UART registers, similar to WBUART\n#define\tR_GPSU_SETUP      \t0x08000a00\t// 08000a00, wbregs names: GPSSETUP\n#define\tR_GPSU_FIFO       \t0x08000a04\t// 08000a00, wbregs names: GPSFIFO\n#define\tR_GPSU_UARTRX     \t0x08000a08\t// 08000a00, wbregs names: GPSRX\n#define\tR_GPSU_UARTTX     \t0x08000a0c\t// 08000a00, wbregs names: GPSTX\n// FPGA CONFIG REGISTERS: 0x4e0-0x4ff\n#define\tR_CFG_CRC         \t0x08000c00\t// 08000c00, wbregs names: FPGACRC\n#define\tR_CFG_FAR         \t0x08000c04\t// 08000c00, wbregs names: FPGAFAR\n#define\tR_CFG_FDRI        \t0x08000c08\t// 08000c00, wbregs names: FPGAFDRI\n#define\tR_CFG_FDRO        \t0x08000c0c\t// 08000c00, wbregs names: FPGAFDRO\n#define\tR_CFG_CMD         \t0x08000c10\t// 08000c00, wbregs names: FPGACMD\n#define\tR_CFG_CTL0        \t0x08000c14\t// 08000c00, wbregs names: FPGACTL0\n#define\tR_CFG_MASK        \t0x08000c18\t// 08000c00, wbregs names: FPGAMASK\n#define\tR_CFG_STAT        \t0x08000c1c\t// 08000c00, wbregs names: FPGASTAT\n#define\tR_CFG_LOUT        \t0x08000c20\t// 08000c00, wbregs names: FPGALOUT\n#define\tR_CFG_COR0        \t0x08000c24\t// 08000c00, wbregs names: FPGACOR0\n#define\tR_CFG_MFWR        \t0x08000c28\t// 08000c00, wbregs names: FPGAMFWR\n#define\tR_CFG_CBC         \t0x08000c2c\t// 08000c00, wbregs names: FPGACBC\n#define\tR_CFG_IDCODE      \t0x08000c30\t// 08000c00, wbregs names: FPGAIDCODE\n#define\tR_CFG_AXSS        \t0x08000c34\t// 08000c00, wbregs names: FPGAAXSS\n#define\tR_CFG_COR1        \t0x08000c38\t// 08000c00, wbregs names: FPGACOR1\n#define\tR_CFG_WBSTAR      \t0x08000c40\t// 08000c00, wbregs names: WBSTAR\n#define\tR_CFG_TIMER       \t0x08000c44\t// 08000c00, wbregs names: CFGTIMER\n#define\tR_CFG_BOOTSTS     \t0x08000c58\t// 08000c00, wbregs names: BOOTSTS\n#define\tR_CFG_CTL1        \t0x08000c60\t// 08000c00, wbregs names: FPGACTL1\n#define\tR_CFG_BSPI        \t0x08000c7c\t// 08000c00, wbregs names: FPGABSPI\n// Meganet register definitions\n#define\tR_MEGANET_RXCMD   \t0x08000e00\t// 08000e00, wbregs names: MEGANETRX\n#define\tR_MEGANET_TXCMD   \t0x08000e04\t// 08000e00, wbregs names: MEGANETTX\n#define\tR_MEGANET_MACHI   \t0x08000e08\t// 08000e00, wbregs names: MEGANETMACHI\n#define\tR_MEGANET_MACLO   \t0x08000e0c\t// 08000e00, wbregs names: MEGANETMACLO\n#define\tR_MEGANET_IPADDR  \t0x08000e10\t// 08000e00, wbregs names: MEGANETIPADDR, MEGANETIP\n#define\tR_MEGANET_RXMISS  \t0x08000e14\t// 08000e00, wbregs names: MEGANETMISS\n#define\tR_MEGANET_RXERR   \t0x08000e18\t// 08000e00, wbregs names: MEGANETERR\n#define\tR_MEGANET_RXCRC   \t0x08000e1c\t// 08000e00, wbregs names: MEGANETCRCER\n#define\tR_MEGANET_DBGSEL  \t0x08000e20\t// 08000e00, wbregs names: MEGANETDBGSL\n#define\tR_MEGANET_RXPKTS  \t0x08000e20\t// 08000e00, wbregs names: MEGANETRXPKT\n#define\tR_MEGANET_ARPRX   \t0x08000e24\t// 08000e00, wbregs names: MEGANETARPRX\n#define\tR_MEGANET_ICMPRX  \t0x08000e28\t// 08000e00, wbregs names: MEGANETICMRX\n#define\tR_MEGANET_TXPKTS  \t0x08000e2c\t// 08000e00, wbregs names: MEGANETTXPKT\n#define\tR_MEGANET_ARPTX   \t0x08000e30\t// 08000e00, wbregs names: MEGANETARPTX\n#define\tR_MEGANET_ICMPTX  \t0x08000e34\t// 08000e00, wbregs names: MEGANETICMTX\n#define\tR_MEGANET_DATATX  \t0x08000e38\t// 08000e00, wbregs names: MEGANETDATTX\n#define\tR_MEGANET_TXABORTS\t0x08000e3c\t// 08000e00, wbregs names: MEGANETABRTS\n#define\tR_MEGANET_DBGRX   \t0x08000e40\t// 08000e00, wbregs names: MEGANETDBGRX\n#define\tR_MEGANET_DBGTX   \t0x08000e44\t// 08000e00, wbregs names: MEGANETDBGTX\n#define\tR_DDR3_PHY        \t0x08001000\t// 08001000, wbregs names: DDR3_PHY, DPHYSTAT0\n#define\tR_DDR3_PHYSTAT1   \t0x08001004\t// 08001000, wbregs names: DDR3_PHYSTAT1, DPHYSTAT1\n#define\tR_DDR3_PHYSTAT2   \t0x08001008\t// 08001000, wbregs names: DDR3_PHYSTAT2, DPHYSTAT2\n#define\tR_DDR3_PHYSTAT3   \t0x0800100c\t// 08001000, wbregs names: DDR3_PHYSTAT3, DPHYSTAT3\n#define\tR_DDR3_PHYCTRLSTAT\t0x08001010\t// 08001000, wbregs names: DDR3_PHYCTRLSTAT, DCTRLSTAT\n#define\tR_DDR3_PHYRESET   \t0x08001044\t// 08001000, wbregs names: DDR3_PHYRESET, DCTRLRESET\n#define\tR_DDR3_PHYDBGSEL  \t0x0800104c\t// 08001000, wbregs names: DDR3_PHYDBGSEL, DCTRLDBG\n// HDMI pixel clock PLL reconfiguration port\n#define\tR_PXPLL           \t0x08001200\t// 08001200, wbregs names: PXPLL\n// I2C Controller registers\n#define\tR_EDID            \t0x08001400\t// 08001400, wbregs names: EDID, EDID_CTRL, EDIDCTRL\n#define\tR_EDID_OVW        \t0x08001404\t// 08001400, wbregs names: EDID_OVW, EDID_OVERRIDE\n#define\tR_EDID_ADDR       \t0x08001408\t// 08001400, wbregs names: EDID_ADDR, EDID_ADDRESS\n#define\tR_EDID_CKCOUNT    \t0x0800140c\t// 08001400, wbregs names: EDIDCLK, EDID_CKCOUNT\n// GPS clock tracker, control loop settings registers\n#define\tR_GPS_ALPHA       \t0x08001410\t// 08001410, wbregs names: ALPHA\n#define\tR_GPS_BETA        \t0x08001414\t// 08001410, wbregs names: BETA\n#define\tR_GPS_GAMMA       \t0x08001418\t// 08001410, wbregs names: GAMMA\n#define\tR_GPS_STEP        \t0x0800141c\t// 08001410, wbregs names: STEP\n// I2C Controller registers\n#define\tR_I2CCPU          \t0x08001420\t// 08001420, wbregs names: I2CCPU, I2CCPU_CTRL, I2CCPUCTRL\n#define\tR_I2CCPU_OVW      \t0x08001424\t// 08001420, wbregs names: I2CCPU_OVW, I2CCPU_OVERRIDE\n#define\tR_I2CCPU_ADDR     \t0x08001428\t// 08001420, wbregs names: I2CCPU_ADDR, I2CCPU_ADDRESS\n#define\tR_I2CCPU_CKCOUNT  \t0x0800142c\t// 08001420, wbregs names: I2CCPUCLK, I2CCPU_CKCOUNT\n#define\tR_I2CDMA          \t0x08001430\t// 08001430, wbregs names: I2CDMA\n#define\tR_I2CDMA_ADDR     \t0x08001434\t// 08001430, wbregs names: I2CDMAADDR\n#define\tR_I2CDMA_BASE     \t0x08001438\t// 08001430, wbregs names: I2CDMABASE\n#define\tR_I2CDMA_LEN      \t0x0800143c\t// 08001430, wbregs names: I2CDMALEN\n#define\tR_OLED            \t0x08001440\t// 08001440, wbregs names: OLED\n#define\tR_OLED_OV         \t0x08001444\t// 08001440, wbregs names: OLEDOV\n#define\tR_OLED_ADDR       \t0x08001448\t// 08001440, wbregs names: OLEDADDR\n#define\tR_OLED_CLK        \t0x0800144c\t// 08001440, wbregs names: OLEDCLK\n// RTC clock registers\n#define\tR_CLOCK           \t0x08001450\t// 08001450, wbregs names: CLOCK\n#define\tR_TIMER           \t0x08001454\t// 08001450, wbregs names: TIMER\n#define\tR_STOPWATCH       \t0x08001458\t// 08001450, wbregs names: STOPWATCH\n#define\tR_CKALARM         \t0x0800145c\t// 08001450, wbregs names: ALARM, CKALARM\n// GPS clock test bench registers, for measuring the clock trackers performance\n#define\tR_GPSTB_FREQ      \t0x08001460\t// 08001460, wbregs names: GPSFREQ\n#define\tR_GPSTB_JUMP      \t0x08001464\t// 08001460, wbregs names: GPSJUMP\n#define\tR_GPSTB_ERRHI     \t0x08001468\t// 08001460, wbregs names: ERRHI\n#define\tR_GPSTB_ERRLO     \t0x0800146c\t// 08001460, wbregs names: ERRLO\n#define\tR_GPSTB_COUNTHI   \t0x08001470\t// 08001460, wbregs names: CNTHI\n#define\tR_GPSTB_COUNTLO   \t0x08001474\t// 08001460, wbregs names: CNTLO\n#define\tR_GPSTB_STEPHI    \t0x08001478\t// 08001460, wbregs names: STEPHI\n#define\tR_GPSTB_STEPLO    \t0x0800147c\t// 08001460, wbregs names: STEPLO\n// SYSCLK Clock Counter (measures clock speed)\n#define\tR_ADCCLK          \t0x08001480\t// 08001480, wbregs names: ADCCLK\n#define\tR_BUILDTIME       \t0x08001484\t// 08001484, wbregs names: BUILDTIME, BUILDTIME\n#define\tR_BUSERR          \t0x08001488\t// 08001488, wbregs names: BUSERR\n#define\tR_PIC             \t0x0800148c\t// 0800148c, wbregs names: PIC\n#define\tR_GPIO            \t0x08001490\t// 08001490, wbregs names: GPIO, GPI, GPO\n#define\tR_PWRCOUNT        \t0x08001494\t// 08001494, wbregs names: PWRCOUNT\n#define\tR_RTCDATE         \t0x08001498\t// 08001498, wbregs names: RTCDATE, DATE\n// SYSCLK Clock Counter (measures clock speed)\n#define\tR_RXETH0CK        \t0x0800149c\t// 0800149c, wbregs names: RXETH0CK\n#define\tR_SPIO            \t0x080014a0\t// 080014a0, wbregs names: SPIO\n// A register capturing subseconds, locked to GPS if present\n#define\tR_SUBSECONDS      \t0x080014a4\t// 080014a4, wbregs names: SUBSECONDS\n// SYSCLK Clock Counter (measures clock speed)\n#define\tR_TXCLK           \t0x080014a8\t// 080014a8, wbregs names: TXCLK\n#define\tR_VERSION         \t0x080014ac\t// 080014ac, wbregs names: VERSION\n#define\tR_EDIDRX          \t0x08001500\t// 08001500, wbregs names: EDIDRX\n// HDMI video processing pipe registers\n#define\tR_VIDPIPE         \t0x08002000\t// 08002000, wbregs names: VIDPIPE, VIDCTRL\n#define\tR_HDMIFREQ        \t0x08002004\t// 08002000, wbregs names: HDMIFREQ\n#define\tR_SIFREQ          \t0x08002008\t// 08002000, wbregs names: SIFREQ\n#define\tR_PXFREQ          \t0x0800200c\t// 08002000, wbregs names: PXFREQ\n#define\tR_INSIZE          \t0x08002010\t// 08002000, wbregs names: INSIZE\n#define\tR_INPORCH         \t0x08002014\t// 08002000, wbregs names: INPORCH\n#define\tR_INSYNC          \t0x08002018\t// 08002000, wbregs names: INSYNC\n#define\tR_INRAW           \t0x0800201c\t// 08002000, wbregs names: INRAW\n#define\tR_HDMISIZE        \t0x08002020\t// 08002000, wbregs names: HDMISIZE\n#define\tR_HDMIPORCH       \t0x08002024\t// 08002000, wbregs names: HDMIPORCH\n#define\tR_HDMISYNC        \t0x08002028\t// 08002000, wbregs names: HDMISYNC\n#define\tR_HDMIRAW         \t0x0800202c\t// 08002000, wbregs names: HDMIRAW\n#define\tR_OVADDR          \t0x08002030\t// 08002000, wbregs names: OVADDR\n#define\tR_OVSIZE          \t0x08002034\t// 08002000, wbregs names: OVSIZE\n#define\tR_OVOFFSET        \t0x08002038\t// 08002000, wbregs names: OVOFFSET\n#define\tR_FPS             \t0x0800203c\t// 08002000, wbregs names: FPS\n#define\tR_CAPTURE         \t0x08002040\t// 08002000, wbregs names: VCAPTURE\n#define\tR_CAPBASE         \t0x08002044\t// 08002000, wbregs names: VCAPBASE\n#define\tR_CAPWORDS        \t0x08002048\t// 08002000, wbregs names: VCAPWORDS\n#define\tR_CAPPOSN         \t0x0800204c\t// 08002000, wbregs names: VCAPPOSN\n#define\tR_CAPSIZE         \t0x08002050\t// 08002000, wbregs names: VCAPSIZE\n#define\tR_SYNCWORD        \t0x08002060\t// 08002000, wbregs names: VSYNCWORD\n#define\tR_CMAP            \t0x08002800\t// 08002000, wbregs names: CMAP\n// Ethernet configuration (MDIO) port\n#define\tR_MDIO_BMCR       \t0x08003000\t// 08003000, wbregs names: BMCR\n#define\tR_MDIO_BMSR       \t0x08003004\t// 08003000, wbregs names: BMSR\n#define\tR_MDIO_PHYIDR1    \t0x08003008\t// 08003000, wbregs names: PHYIDR1\n#define\tR_MDIO_PHYIDR2    \t0x0800300c\t// 08003000, wbregs names: PHYIDR2\n#define\tR_MDIO_ANAR       \t0x08003010\t// 08003000, wbregs names: ANAR\n#define\tR_MDIO_ANLPAR     \t0x08003014\t// 08003000, wbregs names: ANLPAR\n#define\tR_MDIO_ANER       \t0x08003018\t// 08003000, wbregs names: ANER\n#define\tR_MDIO_ANNPTR     \t0x0800301c\t// 08003000, wbregs names: ANNPTR\n#define\tR_MDIO_ANNPRR     \t0x08003020\t// 08003000, wbregs names: ANNPRR\n#define\tR_MDIO_GBCR       \t0x08003024\t// 08003000, wbregs names: GBCR\n#define\tR_MDIO_GBSR       \t0x08003028\t// 08003000, wbregs names: GBSR\n#define\tR_MDIO_MACR       \t0x08003034\t// 08003000, wbregs names: MACR\n#define\tR_MDIO_MAADR      \t0x08003038\t// 08003000, wbregs names: MAADR\n#define\tR_MDIO_GBESR      \t0x0800303c\t// 08003000, wbregs names: GBESR\n#define\tR_MDIO_PHYCR      \t0x08003040\t// 08003000, wbregs names: PHYCR\n#define\tR_MDIO_PHYSR      \t0x08003044\t// 08003000, wbregs names: PHYSR\n#define\tR_MDIO_INER       \t0x08003048\t// 08003000, wbregs names: INER\n#define\tR_MDIO_INSR       \t0x0800304c\t// 08003000, wbregs names: INSR\n#define\tR_MDIO_RXERC      \t0x08003060\t// 08003000, wbregs names: RXERC\n#define\tR_MDIO_LDPSR      \t0x0800306c\t// 08003000, wbregs names: LDPSR\n#define\tR_MDIO_EPAGSR     \t0x08003078\t// 08003000, wbregs names: EPAGSR\n#define\tR_MDIO_PAGSEL     \t0x0800307c\t// 08003000, wbregs names: PAGSEL\n#define\tR_XMDIO_PC1R      \t0x08003000\t// 08003000, wbregs names: XPC1R\n#define\tR_XMDIO_PS1R      \t0x08003004\t// 08003000, wbregs names: XPS1R\n#define\tR_XMDIO_EEECR     \t0x08003050\t// 08003000, wbregs names: XEEECR\n#define\tR_XMDIO_EEEWER    \t0x08003040\t// 08003000, wbregs names: XEEEWER\n#define\tR_XMDIO_EEEAR     \t0x080030f0\t// 08003000, wbregs names: XEEEAR\n#define\tR_XMDIO_EEELPAR   \t0x080030f4\t// 08003000, wbregs names: XEEELPAR\n#define\tR_XMDIO_LACR      \t0x08003068\t// 08003000, wbregs names: XLACR\n#define\tR_XMDIO_LCR       \t0x08003070\t// 08003000, wbregs names: XLCR\n#define\tR_BKRAM           \t0x10000000\t// 10000000, wbregs names: RAM\n#define\tR_SDRAM           \t0x40000000\t// 40000000, wbregs names: SDRAM\n// ZipCPU control/debug registers\n#define\tR_ZIPCTRL         \t0x80000000\t// 80000000, wbregs names: CPU, ZIPCTRL\n#define\tR_ZIPREGS         \t0x80000080\t// 80000000, wbregs names: ZIPREGS\n#define\tR_ZIPS0           \t0x80000080\t// 80000000, wbregs names: SR0\n#define\tR_ZIPS1           \t0x80000084\t// 80000000, wbregs names: SR1\n#define\tR_ZIPS2           \t0x80000088\t// 80000000, wbregs names: SR2\n#define\tR_ZIPS3           \t0x8000008c\t// 80000000, wbregs names: SR3\n#define\tR_ZIPS4           \t0x80000090\t// 80000000, wbregs names: SR4\n#define\tR_ZIPS5           \t0x80000094\t// 80000000, wbregs names: SR5\n#define\tR_ZIPS6           \t0x80000098\t// 80000000, wbregs names: SR6\n#define\tR_ZIPS7           \t0x8000009c\t// 80000000, wbregs names: SR7\n#define\tR_ZIPS8           \t0x800000a0\t// 80000000, wbregs names: SR8\n#define\tR_ZIPS9           \t0x800000a4\t// 80000000, wbregs names: SR9\n#define\tR_ZIPS10          \t0x800000a8\t// 80000000, wbregs names: SR10\n#define\tR_ZIPS11          \t0x800000ac\t// 80000000, wbregs names: SR11\n#define\tR_ZIPS12          \t0x800000b0\t// 80000000, wbregs names: SR12\n#define\tR_ZIPSSP          \t0x800000b4\t// 80000000, wbregs names: SSP, SR13\n#define\tR_ZIPCC           \t0x800000b8\t// 80000000, wbregs names: ZIPCC, CC, SCC, SR14\n#define\tR_ZIPPC           \t0x800000bc\t// 80000000, wbregs names: ZIPPC, PC, SPC, SR15\n#define\tR_ZIPUSER         \t0x800000c0\t// 80000000, wbregs names: ZIPUSER\n#define\tR_ZIPU0           \t0x800000c0\t// 80000000, wbregs names: UR0\n#define\tR_ZIPU1           \t0x800000c4\t// 80000000, wbregs names: UR1\n#define\tR_ZIPU2           \t0x800000c8\t// 80000000, wbregs names: UR2\n#define\tR_ZIPU3           \t0x800000cc\t// 80000000, wbregs names: UR3\n#define\tR_ZIPU4           \t0x800000d0\t// 80000000, wbregs names: UR4\n#define\tR_ZIPU5           \t0x800000d4\t// 80000000, wbregs names: UR5\n#define\tR_ZIPU6           \t0x800000d8\t// 80000000, wbregs names: UR6\n#define\tR_ZIPU7           \t0x800000dc\t// 80000000, wbregs names: UR7\n#define\tR_ZIPU8           \t0x800000e0\t// 80000000, wbregs names: UR8\n#define\tR_ZIPU9           \t0x800000e4\t// 80000000, wbregs names: UR9\n#define\tR_ZIPU10          \t0x800000e8\t// 80000000, wbregs names: SR10\n#define\tR_ZIPU11          \t0x800000ec\t// 80000000, wbregs names: SR11\n#define\tR_ZIPU12          \t0x800000f0\t// 80000000, wbregs names: SR12\n#define\tR_ZIPUSP          \t0x800000f4\t// 80000000, wbregs names: USP, UR13\n#define\tR_ZIPUCC          \t0x800000f8\t// 80000000, wbregs names: ZIPUCC, UCC\n#define\tR_ZIPUPC          \t0x800000fc\t// 80000000, wbregs names: ZIPUPC, UPC\n#define\tR_ZIPSYSTEM       \t0x80000100\t// 80000000, wbregs names: ZIPSYSTEM, ZIPSYS\n#define\tR_ZIPWATCHDOG     \t0x80000104\t// 80000000, wbregs names: ZIPWATCHDOG\n#define\tR_ZIPBUSDOG       \t0x80000108\t// 80000000, wbregs names: BUSDOG\n#define\tR_ZIPAPIC         \t0x8000010c\t// 80000000, wbregs names: ZIPAPIC, ALTPIC\n#define\tR_ZIPTIMERA       \t0x80000110\t// 80000000, wbregs names: ZIPTMA, ZIPTIMERA\n#define\tR_ZIPTIMERB       \t0x80000114\t// 80000000, wbregs names: ZIPTMB, ZIPTIMERB\n#define\tR_ZIPTIMERC       \t0x80000118\t// 80000000, wbregs names: ZIPTMC, ZIPTIMERC\n#define\tR_ZIPJIFFIES      \t0x8000011c\t// 80000000, wbregs names: ZIPJIFF\n#define\tR_ZIPMTASK        \t0x80000120\t// 80000000, wbregs names: ZIPMTASK\n#define\tR_ZIPMSTALL       \t0x80000124\t// 80000000, wbregs names: ZIPMSTALL\n#define\tR_ZIPMPSTAL       \t0x80000128\t// 80000000, wbregs names: ZIPMPSTAL\n#define\tR_ZIPMINSN        \t0x8000012c\t// 80000000, wbregs names: ZIPMINSN\n#define\tR_ZIPUTASK        \t0x80000130\t// 80000000, wbregs names: ZIPUTASK\n#define\tR_ZIPUSTALL       \t0x80000134\t// 80000000, wbregs names: ZIPUSTALL\n#define\tR_ZIPUPSTAL       \t0x80000138\t// 80000000, wbregs names: ZIPUPSTAL\n#define\tR_ZIPUINSN        \t0x8000013c\t// 80000000, wbregs names: ZIPUINSN\n#define\tR_ZIPUDMAC        \t0x80000140\t// 80000000, wbregs names: ZIPDMAC\n\n\n//\n// The @REGDEFS.H.DEFNS tag\n//\n// @REGDEFS.H.DEFNS for masters\n#define\tBAUDRATE\t1000000\n#define\tCLKFREQHZ\t100000000\n// @REGDEFS.H.DEFNS for peripherals\n#define\tFLASHBASE\t0x01000000\n#define\tFLASHLEN\t0x01000000\n#define\tFLASHLGLEN\t24\n//\n#define\tFLASH_RDDELAY\t2\n#define\tFLASH_NDUMMY\t6\n//\n#define\tBKRAMBASE\t0x10000000\n#define\tBKRAMLEN\t0x00100000\n#define\tSDRAMBASE\t0x40000000\n#define\tSDRAMLEN\t0x40000000\n// @REGDEFS.H.DEFNS at the top level\n// End of definitions from REGDEFS.H.DEFNS\n//\n// The @REGDEFS.H.INSERT tag\n//\n// @REGDEFS.H.INSERT for masters\n// @REGDEFS.H.INSERT for peripherals\n// Flash control constants\n#define\tQSPI_FLASH\t// This core and hardware support a Quad SPI flash\n#define\tSZPAGEB\t\t256\n#define\tPGLENB\t\t256\n#define\tSZPAGEW\t\t64\n#define\tPGLENW\t\t64\n#define\tNPAGES\t\t256\n#define\tSECTORSZB\t(NPAGES * SZPAGEB)\t// In bytes, not words!!\n#define\tSECTORSZW\t(NPAGES * SZPAGEW)\t// In words\n#define\tNSECTORS\t64\n#define\tSECTOROF(A)\t((A) & (-1<<16))\n#define\tSUBSECTOROF(A)\t((A) & (-1<<12))\n#define\tPAGEOF(A)\t((A) & (-1<<8))\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// ZipCPU register definitions\n// {{{\n\n#define\tCPU_GO\t\t0x0000\n#define\tCPU_HALT\t0x0001\n#define\tCPU_STALL\t0x0002\n#define\tCPU_STEP\t0x0004\n#define\tCPU_RESET\t0x0008\n#define\tCPU_CLRCACHE\t0x0010\n// (Reserved)\t\t0x00e0\n#define\tCPU_SLEEPING\t0x0100\n#define\tCPU_GIE\t\t0x0200\n#define\tCPU_INT\t\t0x0400\n#define\tCPU_BREAK\t0x0800\n#define\tCPU_EXINT\t0xfffff000\n//\n#define\tCPU_sR0\t\t0x0020\n#define\tCPU_sSP\t\t0x002d\n#define\tCPU_sCC\t\t0x002e\n#define\tCPU_sPC\t\t0x002f\n#define\tCPU_uR0\t\t0x0030\n#define\tCPU_uSP\t\t0x003d\n#define\tCPU_uCC\t\t0x003e\n#define\tCPU_uPC\t\t0x003f\n\n#ifdef\tBKROM_ACCESS\n#define\tRESET_ADDRESS\t@$[0x%08x](bkrom.REGBASE)\n#else\n#ifdef\tFLASH_ACCESS\n#define\tRESET_ADDRESS\t0x01600000\n#else\n#define\tRESET_ADDRESS\t0x10000000\n#endif\t// FLASH_ACCESS\n#endif\t// BKROM_ACCESS\n// }}}\n// @REGDEFS.H.INSERT from the top level\ntypedef\tstruct {\n\tunsigned\tm_addr;\n\tconst char\t*m_name;\n} REGNAME;\n\nextern\tconst\tREGNAME\t*bregs;\nextern\tconst\tint\tNREGS;\n// #define\tNREGS\t(sizeof(bregs)/sizeof(bregs[0]))\n\nextern\tunsigned\taddrdecode(const char *v);\nextern\tconst\tchar *addrname(const unsigned v);\n// End of definitions from REGDEFS.H.INSERT\n\n\n#endif\t// REGDEFS_H\n"
  },
  {
    "path": "demo-out/rtl.make.inc",
    "content": "################################################################################\n##\n## Filename:\t../demo-out/rtl.make.inc\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Computer Generated: This file is computer generated by AUTOFPGA. DO NOT EDIT.\n## DO NOT EDIT THIS FILE!\n##\n## CmdLine:\t./autofpga -d -o ../demo-out -I ../auto-data allclocks.txt bkram.txt buserr.txt clkcheck.txt crossbus.txt ddr3.txt edidslvscope.txt edid.txt exconsole.txt flashcfg.txt flash.txt global.txt gpio.txt gps.txt hdmi.txt i2ccpu.txt i2cdma.txt i2saudio.txt icape.txt meganet.txt mdio.txt pic.txt pwrcount.txt rtcdate.txt rtcgps.txt spio.txt sdio.txt vadj33.txt version.txt wboledbw.txt wbpmic.txt wbuarbiter.txt wbubus.txt zipcpu.txt zipmaster.txt\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\nI2CCPUD := wbi2c\nI2CCPU  := $(addprefix $(I2CCPUD)/,wbi2ccpu.v axisi2c.v)\nEXBUSD := exbus\nEXBUS  := $(addprefix $(EXBUSD)/,exbuswb.v excompress.v exdecompress.v exdeword.v exidle.v exmkword.v exwb.v exfifo.v)\nFLASH := qflexpress.v\n\nEDIDD := wbi2c\nEDID  := $(addprefix $(EDIDD)/,wbi2ccpu.v axisi2c.v)\nGPS := gpsclock_tb.v gpsclock.v bigadd.v bigsub.v bigsmpy.v\n\nHDMID := video\nHDMI  := $(addprefix $(HDMID)/,axishdmi.v axisvoverlay.v hdmi2vga.v hdmibitsync.v hdmipixelsync.v sync2stream.v synccount.v tfrstb.v tmdsdecode.v tmdsencode.v vid_empty.v vid_mux.v vidpipe.v vidstream2pix.v vid_wbframebuf.v vid_crop.v xhdmiin_deserdes.v xhdmiin.v xhdmiout.v xpxclk.v)\nI2CSLVD := wbi2c\nI2CSLV  := $(addprefix $(I2CSLVD)/,wbi2cslave.v)\nSCOPCD := wbscope\nSCOPC  := $(addprefix $(SCOPCD)/,wbscopc.v)\nICAP := wbicapetwo.v\n\nBKRAM := memdev.v\n\nDDR3D := ddr3\nDDR3  := $(addprefix $(DDR3D)/,ddr3_controller.v ddr3_phy.v)\nI2CDMAD := wbi2c\nI2CDMA  := $(addprefix $(I2CDMAD)/,wbi2cdma.v)\nAUDIOD := audio\nAUDIO  := $(addprefix $(AUDIOD)/,axisi2s.v lli2s.v)\nENETD := ethernet\nENET  := $(addprefix $(ENETD)/,enetstream.v addecrc.v addemac.v addepad.v addepreamble.v rxecrc.v rxehwmac.v rxeipchk.v rxemin.v rxepacket.v rxepreambl.v axinwidth.v axincdc.v pktgate.v txespeed.v xiddr.v)\nRTCDATED := rtc\nRTCDATE  := $(addprefix $(RTCDATED)/,rtcdate.v)\nRTCGPSD := rtc\nRTCGPS  := $(addprefix $(RTCGPSD)/,rtcgps.v rtcbare.v rtctimer.v rtcstopwatch.v rtcalarm.v rtclight.v)\nGPIO := wbgpio.v\n\nSDIOD := sdspi\nSDIO  := $(addprefix $(SDIOD)/,sdio.v sdfrontend.v sdckgen.v sdwb.v sdtxframe.v sdrxframe.v sdcmd.v sddma.v sddma_mm2s.v sddma_rxgears.v sdfifo.v sddma_txgears.v sddma_s2mm.v xsdddr.v xsdserdes8x.v)\nBUSPICD := cpu\nBUSPIC  := $(addprefix $(BUSPICD)/,icontrol.v)\nENETMDIOD := ethernet\nENETMDIO  := $(addprefix $(ENETMDIOD)/,enetctrl.v)\nWBSPID := wbspi\nWBSPI  := $(addprefix $(WBSPID)/,spicpu.v)\nUPSZ := wbupsz.v\n\nZIPCPUD := cpu\nZIPCPU  := $(addprefix $(ZIPCPUD)/,zipsystem.v zipcore.v zipwb.v cpuops.v pfcache.v pipemem.v dblfetch.v pffifo.v pfcache.v idecode.v wbpriarbiter.v zipsystem.v zipcounter.v zipjiffies.v ziptimer.v icontrol.v wbwatchdog.v busdelay.v zipdma_ctrl.v zipdma_fsm.v zipdma_mm2s.v zipdma_rxgears.v zipdma_s2mm.v zipdma_txgears.v zipdma.v)\nVFLIST := main.v  $(I2CCPU) $(EXBUS) $(FLASH) $(EDID) $(GPS) $(HDMI) $(I2CSLV) $(SCOPC) $(ICAP) $(BKRAM) $(DDR3) $(I2CDMA) $(AUDIO) $(ENET) $(RTCDATE) $(RTCGPS) $(GPIO) $(SDIO) $(BUSPIC) $(ENETMDIO) $(WBSPI) $(UPSZ) $(ZIPCPU)\nAUTOVDIRS :=  -y wbi2c -y exbus -y video -y wbscope -y ddr3 -y audio -y ethernet -y rtc -y sdspi -y cpu -y wbspi\n"
  },
  {
    "path": "demo-out/testb.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\t../demo-out/testb.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Computer Generated: This file is computer generated by AUTOFPGA. DO NOT EDIT.\n// DO NOT EDIT THIS FILE!\n//\n// CmdLine:\t./autofpga -d -o ../demo-out -I ../auto-data allclocks.txt bkram.txt buserr.txt clkcheck.txt crossbus.txt ddr3.txt edidslvscope.txt edid.txt exconsole.txt flashcfg.txt flash.txt global.txt gpio.txt gps.txt hdmi.txt i2ccpu.txt i2cdma.txt i2saudio.txt icape.txt meganet.txt mdio.txt pic.txt pwrcount.txt rtcdate.txt rtcgps.txt spio.txt sdio.txt vadj33.txt version.txt wboledbw.txt wbpmic.txt wbuarbiter.txt wbubus.txt zipcpu.txt zipmaster.txt\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tTESTB_H\n#define\tTESTB_H\n\n// #define TRACE_FST\n\n#include <stdio.h>\n#include <stdint.h>\n#ifdef\tTRACE_FST\n#define\tTRACECLASS\tVerilatedFstC\n#include <verilated_fst_c.h>\n#else // TRACE_FST\n#define\tTRACECLASS\tVerilatedVcdC\n#include <verilated_vcd_c.h>\n#endif\n#include <tbclock.h>\n\n\t//\n\t// The TESTB class is a useful wrapper for interacting with a Verilator\n\t// based design.  Key to its capabilities are the tick() method for\n\t// advancing the simulation timestep, and the opentrace() and\n\t// closetrace() methods for handling VCD tracefile generation.  To\n\t// use a non-VCD trace, redefine TRACECLASS before calling this\n\t// function to the trace class you wish to use.\n//\ntemplate <class VA>\tclass TESTB {\npublic:\n\tVA\t*m_core;\n\tbool\t\tm_changed;\n\tTRACECLASS*\tm_trace;\n\tbool\t\tm_done, m_paused_trace;\n\tuint64_t\tm_time_ps;\n\t// TBCLOCK is a clock support class, enabling multiclock simulation\n\t// operation.\n\tTBCLOCK\tm_clk;\n\tTBCLOCK\tm_pixclk;\n\tTBCLOCK\tm_net_rx_clk;\n\tTBCLOCK\tm_clk_125mhz;\n\n\tTESTB(void) {\n\t\t// {{{\n\t\tm_core = new VA;\n\t\tm_time_ps  = 0ul;\n\t\tm_trace    = NULL;\n\t\tm_done     = false;\n\t\tm_paused_trace = false;\n\t\tVerilated::traceEverOn(true);\n// Set the initial clock periods\n\t\tm_clk.init(10000);\t//  100.00 MHz\n\t\tm_pixclk.init(25000);\t//   40.00 MHz\n\t\tm_net_rx_clk.init(8000);\t//  125.00 MHz\n\t\tm_clk_125mhz.init(8000);\t//  125.00 MHz\n\t}\n\t// }}}\n\n\tvirtual ~TESTB(void) {\n\t\t// {{{\n\t\tif (m_trace) m_trace->close();\n\t\tdelete m_core;\n\t\tm_core = NULL;\n\t}\n\t// }}}\n\n\t//\n\t// opentrace()\n\t// {{{\n\t//\n\t// Useful for beginning a (VCD) trace.  To open such a trace, just call\n\t// opentrace() with the name of the VCD file you'd like to trace\n\t// everything into\n\tvirtual\tvoid\topentrace(const char *vcdname, int depth=99) {\n\t\tif (!m_trace) {\n\t\t\tm_trace = new TRACECLASS;\n\t\t\tm_core->trace(m_trace, 99);\n\t\t\tm_trace->spTrace()->set_time_resolution(\"ps\");\n\t\t\tm_trace->spTrace()->set_time_unit(\"ps\");\n\t\t\tm_trace->open(vcdname);\n\t\t\tm_paused_trace = false;\n\t\t}\n\t}\n\t// }}}\n\n\t//\n\t// trace()\n\t// {{{\n\t// A synonym for opentrace() above.\n\t//\n\tvoid\ttrace(const char *vcdname) {\n\t\topentrace(vcdname);\n\t}\n\t// }}}\n\n\t//\n\t// pausetrace(pause)\n\t// {{{\n\t// Set/clear a flag telling us whether or not to write to the VCD trace\n\t// file.  The default is to write to the file, but this can be changed\n\t// by calling pausetrace.  pausetrace(false) will resume tracing,\n\t// whereas pausetrace(true) will stop all calls to Verilator's trace()\n\t// function\n\t//\n\tvirtual\tbool\tpausetrace(bool pausetrace) {\n\t\tm_paused_trace = pausetrace;\n\t\treturn m_paused_trace;\n\t}\n\t// }}}\n\n\t//\n\t// pausetrace()\n\t// {{{\n\t// Like pausetrace(bool) above, except that pausetrace() will return\n\t// the current status of the pausetrace flag above.  Specifically, it\n\t// will return true if the trace has been paused or false otherwise.\n\tvirtual\tbool\tpausetrace(void) {\n\t\treturn m_paused_trace;\n\t}\n\t// }}}\n\n\t//\n\t// closetrace()\n\t// {{{\n\t// Closes the open trace file.  No more information will be written\n\t// to it\n\tvirtual\tvoid\tclosetrace(void) {\n\t\tif (m_trace) {\n\t\t\tm_trace->close();\n\t\t\tdelete m_trace;\n\t\t\tm_trace = NULL;\n\t\t}\n\t}\n\t// }}}\n\n\t//\n\t// eval()\n\t// {{{\n\t// This is a synonym for Verilator's eval() function.  It evaluates all\n\t// of the logic within the design.  AutoFPGA based designs shouldn't\n\t// need to be calling this, they should call tick() instead.  However,\n\t// in the off chance that your design inputs depend upon combinatorial\n\t// expressions that would be output based upon other input expressions,\n\t// you might need to call this function.\n\tvirtual\tvoid\teval(void) {\n\t\tm_core->eval();\n\t}\n\t// }}}\n\n\t//\n\t// tick()\n\t// {{{\n\t// tick() is the main entry point into this helper core.  In general,\n\t// tick() will advance the clock by one clock tick.  In a multiple clock\n\t// design, this will advance the clocks up until the nearest clock\n\t// transition.\n\tvirtual\tvoid\ttick(void) {\n\t\tunsigned\tmintime = m_clk.time_to_edge();\n\n\t\tif (m_pixclk.time_to_edge() < mintime)\n\t\t\tmintime = m_pixclk.time_to_edge();\n\n\t\tif (m_net_rx_clk.time_to_edge() < mintime)\n\t\t\tmintime = m_net_rx_clk.time_to_edge();\n\n\t\tif (m_clk_125mhz.time_to_edge() < mintime)\n\t\t\tmintime = m_clk_125mhz.time_to_edge();\n\n\t\tassert(mintime > 1);\n\n\t\t// Pre-evaluate, to give verilator a chance to settle any\n\t\t// combinatorial logic thatthat may have changed since the\n\t\t// last clockevaluation, and then record that in the trace.\n\t\teval();\n\t\tif (m_trace && !m_paused_trace) m_trace->dump(m_time_ps+1);\n\n\t\t// Advance each clock\n\t\tm_core->i_clk = m_clk.advance(mintime);\n\t\tm_core->i_pixclk = m_pixclk.advance(mintime);\n\t\tm_core->i_net_rx_clk = m_net_rx_clk.advance(mintime);\n\t\tm_core->i_clk_125mhz = m_clk_125mhz.advance(mintime);\n\n\t\tm_time_ps += mintime;\n\t\teval();\n\t\t// If we are keeping a trace, dump the current state to that\n\t\t// trace now\n\t\tif (m_trace && !m_paused_trace) {\n\t\t\tm_trace->dump(m_time_ps);\n\t\t\tm_trace->flush();\n\t\t}\n\n\t\tif (m_clk.falling_edge()) {\n\t\t\tm_changed = true;\n\t\t\tsim_clk_tick();\n\t\t}\n\t\tif (m_pixclk.falling_edge()) {\n\t\t\tm_changed = true;\n\t\t\tsim_pixclk_tick();\n\t\t}\n\t\tif (m_net_rx_clk.falling_edge()) {\n\t\t\tm_changed = true;\n\t\t\tsim_net_rx_clk_tick();\n\t\t}\n\t\tif (m_clk_125mhz.falling_edge()) {\n\t\t\tm_changed = true;\n\t\t\tsim_clk_125mhz_tick();\n\t\t}\n\t}\n\t// }}}\n\n\tvirtual\tvoid\tsim_clk_tick(void) {\n\t\t// {{{\n\t\t// AutoFPGA will override this method within main_tb.cpp if any\n\t\t// @SIM.TICK key is present within a design component also\n\t\t// containing a @SIM.CLOCK key identifying this clock.  That\n\t\t// component must also set m_changed to true.\n\t\tm_changed = false;\n\t}\n\t// }}}\n\tvirtual\tvoid\tsim_pixclk_tick(void) {\n\t\t// {{{\n\t\t// AutoFPGA will override this method within main_tb.cpp if any\n\t\t// @SIM.TICK key is present within a design component also\n\t\t// containing a @SIM.CLOCK key identifying this clock.  That\n\t\t// component must also set m_changed to true.\n\t\tm_changed = false;\n\t}\n\t// }}}\n\tvirtual\tvoid\tsim_net_rx_clk_tick(void) {\n\t\t// {{{\n\t\t// AutoFPGA will override this method within main_tb.cpp if any\n\t\t// @SIM.TICK key is present within a design component also\n\t\t// containing a @SIM.CLOCK key identifying this clock.  That\n\t\t// component must also set m_changed to true.\n\t\tm_changed = false;\n\t}\n\t// }}}\n\tvirtual\tvoid\tsim_clk_125mhz_tick(void) {\n\t\t// {{{\n\t\t// AutoFPGA will override this method within main_tb.cpp if any\n\t\t// @SIM.TICK key is present within a design component also\n\t\t// containing a @SIM.CLOCK key identifying this clock.  That\n\t\t// component must also set m_changed to true.\n\t\tm_changed = false;\n\t}\n\t// }}}\n\tvirtual bool\tdone(void) {\n\t\t// {{{\n\t\tif (m_done)\n\t\t\treturn true;\n\n\t\tif (Verilated::gotFinish())\n\t\t\tm_done = true;\n\n\t\treturn m_done;\n\t}\n\t// }}}\n\n\t//\n\t// reset()\n\t// {{{\n\t// Sets the i_reset input for one clock tick.  It's really just a\n\t// function for the capabilies shown below.  You'll want to reset any\n\t// external input values before calling this though.\n\tvirtual\tvoid\treset(void) {\n\t\tm_core->i_reset = 1;\n\t\ttick();\n\t\twhile(!m_core->i_clk)\n\t\t\ttick();\n\t\tm_core->i_reset = 0;\n\t\t// printf(\"RESET\\n\");\n\t}\n\t// }}}\n};\n\n#endif\t// TESTB\n\n"
  },
  {
    "path": "demo-out/toplevel.v",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\t../demo-out/toplevel.v\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Computer Generated: This file is computer generated by AUTOFPGA. DO NOT EDIT.\n// DO NOT EDIT THIS FILE!\n//\n// CmdLine:\t./autofpga -d -o ../demo-out -I ../auto-data allclocks.txt bkram.txt buserr.txt clkcheck.txt crossbus.txt ddr3.txt edidslvscope.txt edid.txt exconsole.txt flashcfg.txt flash.txt global.txt gpio.txt gps.txt hdmi.txt i2ccpu.txt i2cdma.txt i2saudio.txt icape.txt meganet.txt mdio.txt pic.txt pwrcount.txt rtcdate.txt rtcgps.txt spio.txt sdio.txt vadj33.txt version.txt wboledbw.txt wbpmic.txt wbuarbiter.txt wbubus.txt zipcpu.txt zipmaster.txt\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n`default_nettype\tnone\n\n\n//\n// Here we declare our toplevel.v (toplevel) design module.\n// All design logic must take place beneath this top level.\n//\n// The port declarations just copy data from the @TOP.PORTLIST\n// key, or equivalently from the @MAIN.PORTLIST key if\n// @TOP.PORTLIST is absent.  For those peripherals that don't need\n// any top level logic, the @MAIN.PORTLIST should be sufficent,\n// so the @TOP.PORTLIST key may be left undefined.\n//\n// The only exception is that any clocks with CLOCK.TOP tags will\n// also appear in this list\n//\nmodule\ttoplevel(i_clk,\n\t\t// Top level Quad-SPI I/O ports\n\t\to_flash_cs_n, io_flash_dat,\n\t\t\tio_scl, io_sda,\n\t\t// UART/host to wishbone interface\n\t\ti_wbu_uart_rx, o_wbu_uart_tx,\n\t\t\tio_hdmitx_scl, io_hdmitx_sda,\n\t\t// The GPS-UART\n\t\ti_gpsu_rx, o_gpsu_tx,\n\t\ti_hdmirx_clk_p, i_hdmirx_clk_n,\n\t\ti_hdmirx_p, i_hdmirx_n,\n\t\to_hdmitx_clk_p, o_hdmitx_clk_n,\n\t\to_hdmitx_p, o_hdmitx_n,\n\t\t// EDID RX definitions\n\t\tio_hdmirx_scl, io_hdmirx_sda,\n\t\t// DDR3 I/O port wires\n\t\to_ddr3_reset_n, o_ddr3_cke, o_ddr3_clk_p, o_ddr3_clk_n,\n\t\t\to_ddr3_vsel,\n\t\to_ddr3_cs_n, o_ddr3_ras_n, o_ddr3_cas_n, o_ddr3_we_n,\n\t\to_ddr3_ba, o_ddr3_a,\n\t\to_ddr3_odt, o_ddr3_dm,\n\t\tio_ddr3_dqs_p, io_ddr3_dqs_n, io_ddr3_dq,\n\t\to_i2s_lrclk, o_i2s_bclk, o_i2s_mclk, o_i2s_dac, i_i2s_adc,\n\t\t// Ethernet control (packets) lines\n\t\to_net_reset_n,\n\t\ti_net_rx_clk, i_net_rx_ctl, i_net_rxd,\n\t\to_net_tx_clk, o_net_tx_ctl, o_net_txd,\n\t\t// SPIO interface\n\t\ti_sw, i_btnc, i_btnd, i_btnl, i_btnr, i_btnu, o_led,\n\t\t// GPIO ports\n\t\to_hdmirx_hpa,\t// Hotplug assert\n\t\to_hdmirx_txen,\n\t\ti_hdmitx_hpd_n, // Hotplug detect\n\t\to_sd_reset,\n\t\ti_gps_3df,\n\t\to_oled_reset_n, o_oled_panel_en, o_oled_logic_en,\n\t\t// SDIO SD Card\n\no_sd_clk,\ni_sd_cd_n,\n\n\t\tio_sd_cmd, io_sd_dat,\n\t\t// VADJ ports\n\t\to_vadj_en, o_vadj,\n\t\t// The GPS 1PPS signal port\n\t\ti_gps_pps,\n\t\t// Toplevel ethernet MDIO ports\n\t\to_eth_mdclk, io_eth_mdio,\n\t\t// OLED control interface (roughly SPI)\n\t\to_oled_sck, o_oled_mosi, o_oled_dcn,\n\t\t// The PMic3 microphone wires\n\t\to_mic_csn, o_mic_sck, i_mic_din);\n\t//\n\t// Declaring any top level parameters.\n\t//\n\t// These declarations just copy data from the @TOP.PARAM key,\n\t// or from the @MAIN.PARAM key if @TOP.PARAM is absent.  For\n\t// those peripherals that don't do anything at the top level,\n\t// the @MAIN.PARAM key should be sufficient, so the @TOP.PARAM\n\t// key may be left undefined.\n\t//\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// EXBUS parameters\n\t// {{{\n\t// Baudrate :   1000000\n\t// Clock    : 100000000\n\tlocalparam [23:0] BUSUART = 24'h64;\t//   1000000 baud\n\tlocalparam\tDBGBUSBITS = $clog2(BUSUART);\n\t// }}}\n\tlocalparam\tICAPE_LGDIV=3;\n\tlocalparam real SDRAMCONTROLLER_CLK_PERIOD = 10_000,  //ps, clock period of the controller interface\n\t\tDDR3_CLK_PERIOD = 2_500; //ps, clock period of the DDR3 RAM device (must be 1/4 of the CONTROLLER_CLK_PERIOD) \n\tlocalparam SDRAMROW_BITS = 14,  // width of row address\n\t\tSDRAMCOL_BITS = 10,  // width of column address\n\t\tSDRAMBA_BITS  =  3,  // width of bank address\n\t\tSDRAMDQ_BITS  =  8,  // Size of one octet\n\t\tSDRAMBYTE_LANES = 2, //8 lanes of DQ\n\t\tSDRAMAUX_WIDTH = 4, //width of aux line (must be >= 4) \n\t\tSDRAMSERDES_RATIO = $rtoi(SDRAMCONTROLLER_CLK_PERIOD/DDR3_CLK_PERIOD),\n\t\t//4 is the width of a single ddr3 command {cs_n, ras_n, cas_n, we_n} plus 3 (ck_en, odt, reset_n) plus bank bits plus row bits\n\t\tSDRAMCMD_LEN = 4 + 3 + SDRAMBA_BITS + SDRAMROW_BITS;\n\n\n\tparameter\t[15:0]\tUDP_DBGPORT  = 6784;\n\n\tlocalparam\t[47:0]\tDEF_HWMAC  = 48'h82_33_48_02_e1_c8;\n\tlocalparam\t[31:0]\tDEF_IPADDR = { 8'd192, 8'd168, 8'd15, 8'd29 };\n\tlocalparam [31:0] GPSCLOCK_DEFAULT_STEP = 32'haabcc771;\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// Variables/definitions/parameters used by the ZipCPU bus master\n\t// {{{\n\t//\n\t// A 32-bit address indicating where the ZipCPU should start running\n\t// from\n`ifdef\tBKROM_ACCESS\n\tlocalparam\tRESET_ADDRESS = @$(/bkrom.BASE);\n`else\n`ifdef\tFLASH_ACCESS\n\tlocalparam\tRESET_ADDRESS = 23068672;\n`else\n\tlocalparam\tRESET_ADDRESS = 268435456;\n`endif\t// FLASH_ACCESS\n`endif\t// BKROM_ACCESS\n\t//\n\t// The number of valid bits on the bus\n\tlocalparam\tZIP_ADDRESS_WIDTH = 27; // Zip-CPU address width\n\t//\n\t// Number of ZipCPU interrupts\n\tlocalparam\tZIP_INTS = 16;\n\t//\n\t// ZIP_START_HALTED\n\t//\n\t// A boolean, indicating whether or not the ZipCPU be halted on startup?\n`ifdef\tBKROM_ACCESS\n\tlocalparam\tZIP_START_HALTED=1'b0;\n`else\n\tlocalparam\tZIP_START_HALTED=1'b1;\n`endif\n\t// }}}\n\t//\n\t// Declaring our input and output ports.  We listed these above,\n\t// now we are declaring them here.\n\t//\n\t// These declarations just copy data from the @TOP.IODECLS key,\n\t// or from the @MAIN.IODECL key if @TOP.IODECL is absent.  For\n\t// those peripherals that don't do anything at the top level,\n\t// the @MAIN.IODECL key should be sufficient, so the @TOP.IODECL\n\t// key may be left undefined.\n\t//\n\t// We start with any @CLOCK.TOP keys\n\t//\n\tinput\twire\t\ti_clk;\n\t// Quad SPI flash\n\toutput\twire\t\to_flash_cs_n;\n\tinout\twire\t[3:0]\tio_flash_dat;\n\tinout\twire\tio_scl, io_sda;\n\tinput\twire\t\ti_wbu_uart_rx;\n\toutput\twire\t\to_wbu_uart_tx;\n\tinout\twire\tio_hdmitx_scl, io_hdmitx_sda;\n\tinput\twire\t\ti_gpsu_rx;\n\toutput\twire\t\to_gpsu_tx;\n\tinput\twire\t\ti_hdmirx_clk_p, i_hdmirx_clk_n;\n\tinput\twire\t[2:0]\ti_hdmirx_p, i_hdmirx_n;\n\toutput\twire\t\to_hdmitx_clk_p, o_hdmitx_clk_n;\n\toutput\twire\t[2:0]\to_hdmitx_p, o_hdmitx_n;\n\t// EDID RX definitions\n\tinout\twire\tio_hdmirx_scl, io_hdmirx_sda;\n\t// I/O declarations for the DDR3 SDRAM\n\t// {{{\n\toutput\twire\t\to_ddr3_reset_n;\n\toutput\twire\t[0:0]\to_ddr3_cke;\n\toutput\twire\t[0:0]\to_ddr3_clk_p, o_ddr3_clk_n;\n\toutput\twire\t[0:0]\to_ddr3_cs_n; // o_ddr3_s_n[1] is set to 0 since controller only support single rank\n\toutput\twire\t\to_ddr3_vsel;\n\toutput\twire\t[0:0]\to_ddr3_ras_n, o_ddr3_cas_n, o_ddr3_we_n;\n\toutput\twire\t[SDRAMBA_BITS-1:0]\to_ddr3_ba;\n\toutput\twire\t[14:0]\to_ddr3_a; //set to max of 16 bits, but only ROW_BITS bits are relevant\n\toutput\twire\t[0:0]\to_ddr3_odt;\n\toutput\twire\t[SDRAMBYTE_LANES-1:0]\to_ddr3_dm;\n\tinout\twire\t[(SDRAMDQ_BITS*SDRAMBYTE_LANES)/8-1:0]\tio_ddr3_dqs_p, io_ddr3_dqs_n;\n\tinout\twire\t[(SDRAMDQ_BITS*SDRAMBYTE_LANES)-1:0]\tio_ddr3_dq;\n\t// }}}\n\n\toutput\twire\to_i2s_lrclk, o_i2s_bclk, o_i2s_mclk, o_i2s_dac;\n\tinput\twire\ti_i2s_adc;\n\t// MegaNet I/O port declarations\n\t// {{{\n\toutput\twire\t\to_net_reset_n;\n\tinput\twire\t\ti_net_rx_clk, i_net_rx_ctl;\n\tinput\twire [3:0]\ti_net_rxd;\n\toutput\twire\t \to_net_tx_clk, o_net_tx_ctl;\n\toutput\twire [3:0]\to_net_txd;\n\t// }}}\n\t// SPIO interface\n\tinput\twire\t[8-1:0]\ti_sw;\n\tinput\twire\t\ti_btnc, i_btnd, i_btnl, i_btnr, i_btnu;\n\toutput\twire\t[8-1:0]\to_led;\n\t// GPIO ports\n\toutput\twire\to_hdmirx_hpa;\n\toutput\twire\to_hdmirx_txen;\n\tinput\twire\ti_hdmitx_hpd_n;\t\t// Hotplug detect\n\toutput\twire\to_sd_reset;\n\tinput\twire\ti_gps_3df;\n\toutput\twire\to_oled_reset_n, o_oled_panel_en, o_oled_logic_en;\n\t// SDIO SD Card\n\t// {{{\n\n\toutput\twire\t\to_sd_clk;\n\n\n\tinput\twire\t\ti_sd_cd_n;\n\n\tinout\twire\t\tio_sd_cmd;\n\tinout\twire\t[4-1:0]\tio_sd_dat;\n\t// }}}\n\t// VADJ wires\n\toutput\twire\t\to_vadj_en;\n\toutput\twire [1:0]\to_vadj;\n\t//The GPS Clock\n\tinput\twire\t\ti_gps_pps;\n\t// Ethernet control (MDIO)\n\toutput\twire\t\to_eth_mdclk;\n\tinout\twire\t\tio_eth_mdio;\n\t// OLEDBW interface\n\toutput\twire\t\to_oled_sck, o_oled_mosi, o_oled_dcn;\n\toutput\twire\t\to_mic_csn, o_mic_sck;\n\tinput\twire\t\ti_mic_din;\n\n\n\t//\n\t// Declaring component data, internal wires and registers\n\t//\n\t// These declarations just copy data from the @TOP.DEFNS key\n\t// within the component data files.\n\t//\n\twire\t\tw_flash_sck, w_flash_cs_n;\n\twire\t[1:0]\tflash_bmod;\n\twire\t[3:0]\tflash_dat;\n\t// I2CCPU definitions\n\t// {{{\n\twire\ti_i2c_sda, i_i2c_scl,\n\t\to_i2c_sda, o_i2c_scl;\n\t// }}}\n\t// I2CCPU definitions\n\t// {{{\n\twire\ti_edid_sda, i_edid_scl,\n\t\to_edid_sda, o_edid_scl;\n\t// }}}\n\twire\t[9:0]\thdmirx_red, hdmirx_grn, hdmirx_blu;\n\twire\t[9:0]\thdmitx_red, hdmitx_grn, hdmitx_blu;\n\twire\t[1:0]\tw_pxclk_cksel;\n\twire\t\thdmirx_clk, hdmi_ck, hdmi_serdes_clk;\n\twire\t\tpxrx_locked, pix_reset_n, hdmirx_reset_n;\n\twire [15-1:0]\tset_hdmi_delay, actual_hdmi_delay;\n\twire\tw_edidslv_scl, w_edidslv_sda;\n\twire\t\ts_clk, s_reset;\n\treg\t[2:0]\tclk_reset_pipe;\n\t// Wires connected to PHY interface of DDR3 controller\n\t// {{{\n\tgenvar ddr3gen_index;\n\n\twire\t[SDRAMDQ_BITS*SDRAMBYTE_LANES*8-1:0] ddr3_iserdes_data;\n\twire\t[SDRAMBYTE_LANES*8-1:0] ddr3_iserdes_dqs,\n\t\t\t\tddr3_iserdes_bitslip_reference;\n\twire    [SDRAMCMD_LEN*SDRAMSERDES_RATIO-1:0]\n\t\t\t\tddr3_cmd;\n\twire    [SDRAMDQ_BITS*SDRAMBYTE_LANES*8-1:0]\n\t\t\t\tddr3_data;\n\twire    [(SDRAMDQ_BITS*SDRAMBYTE_LANES*8)/8-1:0]\n\t\t\t\tddr3_dm;\n\twire    [4:0]\tddr3_odelay_data_cntvaluein,\n\t\t\tddr3_odelay_dqs_cntvaluein,\n\t\t\tddr3_idelay_data_cntvaluein,\n\t\t\tddr3_idelay_dqs_cntvaluein;\n\twire    [SDRAMBYTE_LANES-1:0]\tddr3_odelay_data_ld,\n\t\t\tddr3_odelay_dqs_ld, ddr3_idelay_data_ld,\n\t\t\tddr3_idelay_dqs_ld, ddr3_bitslip,\n\t\t\tddr3_debug_read_dqs_p,\n\t\t\tddr3_debug_read_dqs_n;\n\twire    ddr3_idelayctrl_rdy,\n\t\tddr3_dqs_tri_control, ddr3_dq_tri_control,\n\t\tddr3_toggle_dqs, ddr3_write_leveling_calib,\n\t\tddr3_reset;\n\twire    ddr3_debug_clk_p, ddr3_debug_clk_n;\n\t// }}}\n\twire\t[31:0]\tpxclk_debug;\n\twire\t\tw_pxclk_cyc, w_pxclk_stb, w_pxclk_we,\n\t\t\tw_pxclk_stall, w_pxclk_ack;\n\twire\t[6:0]\tw_pxclk_addr;\n\twire\t[31:0]\tw_pxclk_data, w_pxclk_idata;\n\twire\t[3:0]\tw_pxclk_sel;\n\t// Mega Net definitions\n\t// {{{\n\twire\t[7:0]\t\tw_net_rxd, w_net_txd;\n\twire\t\t\tw_net_rxdv, w_net_rxerr,\n\t\t\t\tw_net_txctl;\n\twire\t[1:0]\t\tw_net_tx_clk;\n\treg\tnet_last_tck;\n\t// }}}\n\twire\t[8-1:0]\tw_led;\n\t// GPIO declarations.  The two wire busses are just virtual lists\n\t// of input (or output) ports.\n\twire\t[8-1:0]\ti_gpio;\n\t// Verilator lint_off UNUSED\n\t// Two of our outputs, o_trace and o_halt, will be unused at the top\n\t// level.\n\twire\t[10-1:0]\to_gpio;\n\t// Verilator lint_on  UNUSED\n\t// SDIO SD Card definitions\n\t// {{{\n\twire\t\tw_sdio_hwreset_n, w_sdio_1p8v;\n\twire\t\tw_sdio_cfg_ddr;\n\twire\t\tw_sdio_cfg_ds, w_sdio_cfg_dscmd;\n\twire\t[4:0]\tw_sdio_cfg_sample_shift;\n\twire\t\tw_sdio_cmd_tristate;\n\twire\t\tw_sdio_data_tristate;\n\t\t//\n\twire\t[7:0]\tw_sdio_sdclk;\n\twire\t\tw_sdio_cmd_en;\n\twire\t[1:0]\tw_sdio_cmd_data;\n\twire\t\tw_sdio_data_en;\n\twire\t\tw_sdio_rx_en;\n\twire\t[31:0]\tw_sdio_tx_data;\n\t\t//\n\twire\t[1:0]\tw_sdio_cmd_strb;\n\twire\t[1:0]\tw_sdio_cmd_idata;\n\twire\t\tw_sdio_cmd_collision;\n\twire\t\tw_sdio_crcack,\n\t\t\tw_sdio_crcnak;\n\twire\t\tw_sdio_card_busy;\n\twire\t[1:0]\tw_sdio_rx_strb;\n\twire\t[15:0]\tw_sdio_rx_data;\n\t\t//\n\twire\t\tw_sdio_ac_valid;\n\twire\t[1:0]\tw_sdio_ac_data;\n\twire\t\tw_sdio_ad_valid;\n\twire\t[31:0]\tw_sdio_ad_data;\n\n\twire\t\tw_sdio_ck;\n\twire\t\tw_sdio_ds;\n\twire\t[31:0]\tw_sdio_debug;\n\t// }}}\n\n\t// Clock/reset definitions\n\t// {{{\n\twire\ts_clk_200mhz,  s_clk_200mhz_unbuffered,\n\t\tsysclk_locked, sysclk_feedback, sysclk_feedback_buffered,\n\t\ts_clk_250mhz,  s_clk_250_unbuffered,\n\t\ts_clk_125mhz,  s_clk_125_unbuffered,\n\t\ts_clk_125d,    s_clk_125d_unbuffered,\n\t\ts_clksync,     s_clksync_unbuffered,\n\t\ts_clk_400mhz,  s_clk_400mhz_unbuffered,\t// Pixclk * 10\n\t\ts_clk_80mhz_unbuffered,\t// 80MHz\n\t\tnetclk_locked, netclk_feedback, netclk_feedback_buffered;\n\twire\ti_clk_buffered;\n\twire\tclocks_locked;\n\twire\tdly_ctrl_ready;\n\treg\t[3:0]\tsysclk_stable, syncd_stable;\n\treg\t[4:0]\tpll_reset_sreg;\n\treg\t\tpll_reset;\n\t// }}}\n\treg\t[4:0]\tvadj33_vadj_counter;\n\t// Ethernet control (MDIO)\n\twire\t\tw_mdio, w_mdwe;\n\t// Verilator lint_off UNUSED\n\twire\t\tign_cpu_stall, ign_cpu_ack;\n\twire\t[31:0]\tign_cpu_idata;\n\t// Verilator lint_on  UNUSED\n\n\n\t//\n\t// Time to call the main module within main.v.  Remember, the purpose\n\t// of the main.v module is to contain all of our portable logic.\n\t// Things that are Xilinx (or even Altera) specific, or for that\n\t// matter anything that requires something other than on-off logic,\n\t// such as the high impedence states required by many wires, is\n\t// kept in this (toplevel.v) module.  Everything else goes in\n\t// main.v.\n\t//\n\t// We automatically place s_clk, and s_reset here.  You may need\n\t// to define those above.  (You did, didn't you?)  Other\n\t// component descriptions come from the keys @TOP.MAIN (if it\n\t// exists), or @MAIN.PORTLIST if it does not.\n\t//\n\n\tmain\tthedesign(s_clk, s_reset,\n\t\t// Quad SPI flash\n\t\tw_flash_cs_n, w_flash_sck, flash_dat, io_flash_dat, flash_bmod,\n\t\t// I2CCPU\n\t\ti_i2c_sda, i_i2c_scl,\n\t\to_i2c_sda, o_i2c_scl,\n\t\t// UART/host to wishbone interface\n\t\ti_wbu_uart_rx, o_wbu_uart_tx,\n\t\t// I2CCPU\n\t\ti_edid_sda, i_edid_scl,\n\t\to_edid_sda, o_edid_scl,\n\t\t// The GPS-UART\n\t\ti_gpsu_rx, o_gpsu_tx,\n\t\t// HDMI control ports\n\t\thdmirx_clk, hdmi_ck,\t// Depending on s_siclk\n\t\thdmirx_red, hdmirx_grn, hdmirx_blu,\n\t\thdmitx_red, hdmitx_grn, hdmitx_blu,\n\t\tset_hdmi_delay, actual_hdmi_delay,\n\t\tpix_reset_n, pxrx_locked, hdmirx_reset_n,\n\t\tw_pxclk_cksel,\n\t// EDID RX definitions\n\tio_hdmirx_scl, io_hdmirx_sda,\n\tw_edidslv_scl,  w_edidslv_sda,\n\t// DDR3 Controller-PHY Interface\n\tddr3_iserdes_data, ddr3_iserdes_dqs,\n\tddr3_iserdes_bitslip_reference,\n\tddr3_idelayctrl_rdy,\n\tddr3_cmd,\n\tddr3_dqs_tri_control, ddr3_dq_tri_control,\n\tddr3_toggle_dqs, ddr3_data, ddr3_dm,\n\tddr3_odelay_data_cntvaluein, ddr3_odelay_dqs_cntvaluein,\n\tddr3_idelay_data_cntvaluein, ddr3_idelay_dqs_cntvaluein,\n\tddr3_odelay_data_ld, ddr3_odelay_dqs_ld,\n\tddr3_idelay_data_ld, ddr3_idelay_dqs_ld,\n\tddr3_bitslip,\n\tddr3_write_leveling_calib,\n\tddr3_reset,\n\t\to_i2s_lrclk, o_i2s_bclk, o_i2s_mclk, o_i2s_dac, i_i2s_adc,\n\t\tw_pxclk_cyc, w_pxclk_stb, w_pxclk_we,\n\t\tw_pxclk_addr, w_pxclk_data, w_pxclk_sel,\n\t\tw_pxclk_stall, w_pxclk_ack, w_pxclk_idata,\n\t\t// Ethernet (RGMII) connections\n\t\to_net_reset_n,\n\t\ti_net_rx_clk, w_net_rxdv,  w_net_rxdv ^ w_net_rxerr, w_net_rxd,\n\t\tw_net_tx_clk, w_net_txctl, w_net_txd,\n\t\ti_sw, i_btnc, i_btnd, i_btnl, i_btnr, i_btnu, w_led,\n\t\t// GPIO wires\n\t\ti_gpio, o_gpio,\n\t\t// SDIO SD Card\n\t\t!i_sd_cd_n,\n\t\t//\n\t\tw_sdio_cfg_ddr,\n\t\tw_sdio_cfg_ds,\n\t\tw_sdio_cfg_dscmd,\n\t\tw_sdio_cfg_sample_shift,\n\t\tw_sdio_cmd_tristate,\n\t\tw_sdio_data_tristate,\n\t\t//\n\t\tw_sdio_sdclk,\n\t\tw_sdio_cmd_en,\n\t\tw_sdio_cmd_data,\n\t\tw_sdio_data_en,\n\t\tw_sdio_rx_en,\n\t\tw_sdio_tx_data,\n\t\t//\n\t\tw_sdio_cmd_strb,\n\t\tw_sdio_cmd_idata,\n\t\tw_sdio_cmd_collision,\n\t\tw_sdio_crcack,\n\t\tw_sdio_crcnak,\n\t\tw_sdio_card_busy,\n\t\tw_sdio_rx_strb,\n\t\tw_sdio_rx_data,\n\t\t//\n\t\tw_sdio_ac_valid,\n\t\tw_sdio_ac_data,\n\t\tw_sdio_ad_valid,\n\t\tw_sdio_ad_data,\n\t\tw_sdio_hwreset_n, w_sdio_1p8v,\n\t\tw_sdio_debug,\n\t\t// PLL generated clocks\n\t\ts_clk_125mhz,\n\t\t// The GPS 1PPS signal port\n\t\ti_gps_pps,\n\t\to_eth_mdclk, w_mdio, w_mdwe, io_eth_mdio,\n\t\t// OLED control interface (roughly SPI)\n\t\to_oled_sck, o_oled_mosi, o_oled_dcn,\n\t\t// The PMic3 microphone wires\n\t\to_mic_csn, o_mic_sck, i_mic_din,\n\t\t// Simulation bus control for the CPU\n\t\t1'b0, 1'b0, 1'b0, 7'h0, 32'h0,\n\t\tign_cpu_stall, ign_cpu_ack, ign_cpu_idata,\n\t\t// Reset wire for the ZipCPU\n\t\ts_reset);\n\n\n\t//\n\t// Our final section to the toplevel is used to provide all of\n\t// that special logic that couldnt fit in main.  This logic is\n\t// given by the @TOP.INSERT tag in our data files.\n\t//\n\n\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// QSPI Flash IO pin handling\n\t// {{{\n\t//\n\t// Wires for setting up the QSPI flash wishbone peripheral\n\t//\n\t//\n\t// QSPI)BMOD, Quad SPI bus mode, Bus modes are:\n\t//\t0?\tNormal serial mode, one bit in one bit out\n\t//\t10\tQuad SPI mode, going out\n\t//\t11\tQuad SPI mode coming from the device (read mode)\n\txqflex #(\n\t\t.OPT_CLOCK(1'b0), .OPT_PHASE(1'b1)\n\t) u_xqflex (\n\t\t.i_clk(s_clk), .i_cs_n(w_flash_cs_n), .i_sck(w_flash_sck),\n\t\t.i_dat(o_flash_dat), .o_dat(i_flash_dat), .i_bmod(flash_bmod),\n\t\t//\n\t\t.o_cs_n(o_flash_cs_n), .o_sck(o_flash_sck), .io_dat(io_flash_dat)\n\t);\n\n\t// The following primitive is necessary in many designs order to gain\n\t// access to the o_flash_sck pin.  It's not necessary on the Arty,\n\t// simply because they provide two pins that can drive the QSPI\n\t// clock pin.\n\twire\t[3:0]\tsu_nc;\t// Startup primitive, no connect\n\tSTARTUPE2 #(\n\t\t// {{{\n\t\t// Leave PROG_USR false to avoid activating the program\n\t\t// event security feature.  Notes state that such a feature\n\t\t// requires encrypted bitstreams.\n\t\t.PROG_USR(\"FALSE\"),\n\t\t// Sets the configuration clock frequency (in ns) for\n\t\t// simulation.\n\t\t.SIM_CCLK_FREQ(0.0)\n\t\t// }}}\n\t) STARTUPE2_inst (\n\t\t// {{{\n\t\t// CFGCLK, 1'b output: Configuration main clock output -- no\n\t\t//\tconnect\n\t\t.CFGCLK(su_nc[0]),\n\t\t// CFGMCLK, 1'b output: Configuration internal oscillator clock\n\t\t//\toutput\n\t\t.CFGMCLK(su_nc[1]),\n\t\t// EOS, 1'b output: Active high output indicating the End Of\n\t\t//\tStartup.\n\t\t.EOS(su_nc[2]),\n\t\t// PREQ, 1'b output: PROGRAM request to fabric output\n\t\t//\tOnly enabled if PROG_USR is set.  This lets the fabric\n\t\t//\tknow that a request has been made (either JTAG or pin\n\t\t//\tpulled low) to program the device\n\t\t.PREQ(su_nc[3]),\n\t\t// CLK, 1'b input: User start-up clock input\n\t\t.CLK(1'b0),\n\t\t// GSR, 1'b input: Global Set/Reset input\n\t\t.GSR(1'b0),\n\t\t// GTS, 1'b input: Global 3-state input\n\t\t.GTS(1'b0),\n\t\t// KEYCLEARB, 1'b input: Clear AES Decrypter Key input from\n\t\t//\tBBRAM\n\t\t.KEYCLEARB(1'b0),\n\t\t// PACK, 1-bit input: PROGRAM acknowledge input\n\t\t//\tThis pin is only enabled if PROG_USR is set.  This\n\t\t//\tallows the FPGA to acknowledge a request for reprogram\n\t\t//\tto allow the FPGA to get itself into a reprogrammable\n\t\t//\tstate first.\n\t\t.PACK(1'b0),\n\t\t// USRCLKO, 1-bit input: User CCLK input -- This is why I am\n\t\t//\tusing this module at all.\n\t\t.USRCCLKO(o_flash_sck),\n\t\t// USRCCLKTS, 1'b input: User CCLK 3-state enable input\n\t\t//\tAn active high here places the clock into a high\n\t\t//\timpedence state.  Since we wish to use the clock as an\n\t\t//\tactive output always, we drive this pin low.\n\t\t.USRCCLKTS(1'b0),\n\t\t// USRDONEO, 1'b input: User DONE pin output control\n\t\t//\tSet this to \"high\" to make sure that the DONE LED pin\n\t\t//\tis high.\n\t\t.USRDONEO(1'b1),\n\t\t// USRDONETS, 1'b input: User DONE 3-state enable output\n\t\t//\tThis enables the FPGA DONE pin to be active.  Setting\n\t\t//\tthis active high sets the DONE pin to high impedence,\n\t\t//\tsetting it low allows the output of this pin to be as\n\t\t//\tstated above.\n\t\t.USRDONETS(1'b1)\n\t\t// }}}\n\t);\n\t// }}}\n\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// I2C IO buffers\n\t// {{{\n\n\t// We need these in order to (properly) ensure the high impedance\n\t// states (pull ups) of the I2C I/O lines.  Our goals are:\n\t//\n\t//\to_i2c_X\tio_i2c_X\t\tDerived:T\n\t//\t1'b0\t\t1'b0\t\t\t1'b0\n\t//\t1'b1\t\t1'bz\t\t\t1'b1\n\t//\n\tIOBUF i2csclp(\n\t\t// {{{\n\t\t.I(1'b0),\n\t\t.T(o_i2c_scl),\n\t\t.O(i_i2c_scl),\n\t\t.IO(io_scl)\n\t\t// }}}\n\t);\n\n\tIOBUF i2csdap(\n\t\t// {{{\n\t\t.I(1'b0),\n\t\t.T(o_i2c_sda),\n\t\t.O(i_i2c_sda),\n\t\t.IO(io_sda)\n\t\t// }}}\n\t);\n\t// }}}\n\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// I2C IO buffers\n\t// {{{\n\n\t// We need these in order to (properly) ensure the high impedance\n\t// states (pull ups) of the I2C I/O lines.  Our goals are:\n\t//\n\t//\to_edid_X\tio_edid_X\t\tDerived:T\n\t//\t1'b0\t\t1'b0\t\t\t1'b0\n\t//\t1'b1\t\t1'bz\t\t\t1'b1\n\t//\n\tIOBUF edidsclp(\n\t\t// {{{\n\t\t.I(1'b0),\n\t\t.T(o_edid_scl),\n\t\t.O(i_edid_scl),\n\t\t.IO(io_hdmitx_scl)\n\t\t// }}}\n\t);\n\n\tIOBUF edidsdap(\n\t\t// {{{\n\t\t.I(1'b0),\n\t\t.T(o_edid_sda),\n\t\t.O(i_edid_sda),\n\t\t.IO(io_hdmitx_sda)\n\t\t// }}}\n\t);\n\t// }}}\n\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// HDMI\n\t// {{{\n\n\t// Ingest the HDMI data lines\n\t// {{{\n\txhdmiin\n\tu_hdmirx_red(\n\t\t.i_clk(hdmi_ck), .i_hsclk(hdmi_serdes_clk),\n\t\t.i_reset_n(hdmirx_reset_n),\n\t\t.i_delay(set_hdmi_delay[14:10]),\n\t\t.o_delay(actual_hdmi_delay[14:10]),\n\t\t.i_hs_wire({ i_hdmirx_p[2], i_hdmirx_n[2] }),\n\t\t.o_word(hdmirx_red)\n\t);\n\n\txhdmiin\n\tu_hdmirx_grn(\n\t\t.i_clk(hdmi_ck), .i_hsclk(hdmi_serdes_clk),\n\t\t.i_reset_n(hdmirx_reset_n),\n\t\t.i_delay(set_hdmi_delay[9:5]),\n\t\t.o_delay(actual_hdmi_delay[9:5]),\n\t\t.i_hs_wire({ i_hdmirx_p[1], i_hdmirx_n[1] }),\n\t\t.o_word(hdmirx_grn)\n\t);\n\n\txhdmiin\n\tu_hdmirx_blu(\n\t\t.i_clk(hdmi_ck), .i_hsclk(hdmi_serdes_clk),\n\t\t.i_reset_n(hdmirx_reset_n),\n\t\t.i_delay(set_hdmi_delay[4:0]),\n\t\t.o_delay(actual_hdmi_delay[4:0]),\n\t\t.i_hs_wire({ i_hdmirx_p[0], i_hdmirx_n[0] }),\n\t\t.o_word(hdmirx_blu)\n\t);\n\t// }}}\n\n\t// Output the HDMI TX data lines\n\t// {{{\n\txhdmiout\n\tu_hdmitx_clk(\n\t\t.i_clk(hdmi_ck), .i_hsclk(hdmi_serdes_clk),\n\t\t.i_reset_n(pix_reset_n), .i_en(1'b1),\n\t\t.i_word(10'b11111_00000),\n\t\t.o_port({ o_hdmitx_clk_p, o_hdmitx_clk_n })\n\t);\n\n\txhdmiout\n\tu_hdmitx_red(\n\t\t.i_clk(hdmi_ck), .i_hsclk(hdmi_serdes_clk),\n\t\t.i_reset_n(pix_reset_n), .i_en(1'b1),\n\t\t.i_word(hdmitx_red),\n\t\t.o_port({ o_hdmitx_p[2], o_hdmitx_n[2] })\n\t);\n\n\txhdmiout\n\tu_hdmitx_grn(\n\t\t.i_clk(hdmi_ck), .i_hsclk(hdmi_serdes_clk),\n\t\t.i_reset_n(pix_reset_n), .i_en(1'b1),\n\t\t.i_word(hdmitx_grn),\n\t\t.o_port({ o_hdmitx_p[1], o_hdmitx_n[1] })\n\t);\n\n\txhdmiout\n\tu_hdmitx_blu(\n\t\t.i_clk(hdmi_ck), .i_hsclk(hdmi_serdes_clk),\n\t\t.i_reset_n(pix_reset_n), .i_en(1'b1),\n\t\t.i_word(hdmitx_blu),\n\t\t.o_port({ o_hdmitx_p[0], o_hdmitx_n[0] })\n\t);\n\t// }}}\n\n\t// }}}\n\n\tassign\tio_hdmirx_scl = w_edidslv_scl ? 1'bz : 1'b0;\n\tassign\tio_hdmirx_sda = w_edidslv_sda ? 1'bz : 1'b0;\n\n\tassign\ts_clk = s_clksync;\n\tassign\to_ddr3_vsel = 1'bz;\n\n\talways @(posedge s_clk or negedge clocks_locked)\n\tif (!clocks_locked)\n\t\tclk_reset_pipe <= 3'h7;\n\telse\n\t\tclk_reset_pipe <= { clk_reset_pipe[1:0], 1'b0 };\n\n\tassign\ts_reset = clk_reset_pipe[2];\n\n\t// DDR3 PHY Instantiation\n\tddr3_phy #(\n\t\t// {{{\n\t\t.ROW_BITS(SDRAMROW_BITS),\t//width of row address\n\t\t.BA_BITS(SDRAMBA_BITS),\t//width of bank address\n\t\t.DQ_BITS(SDRAMDQ_BITS),\t//width of DQ\n\t\t.LANES(SDRAMBYTE_LANES), //8 lanes of DQ\n\t\t.CONTROLLER_CLK_PERIOD(SDRAMCONTROLLER_CLK_PERIOD), //ns, period of clock input to this DDR3 controller module\n\t\t.DDR3_CLK_PERIOD(DDR3_CLK_PERIOD), //ns, period of clock input to DDR3 RAM device\n\t\t.ODELAY_SUPPORTED(1)\n\t\t// }}}\n\t) ddr3_phy_inst (\n\t\t// {{{\n\t\t// clock and reset\n\t\t.i_controller_clk(s_clksync),\n\t\t.i_ddr3_clk(s_clk_400mhz),\n\t\t.i_ref_clk(s_clk_200mhz),\n\t\t.i_ddr3_clk_90(0), //required only when ODELAY_SUPPORTED is zero\n\t\t.i_rst_n(!s_reset),\n\t\t// Controller Interface\n\t\t.i_controller_reset(ddr3_reset),\n\t\t.i_controller_cmd(ddr3_cmd),\n\t\t.i_controller_dqs_tri_control(ddr3_dqs_tri_control),\n\t\t.i_controller_dq_tri_control(ddr3_dq_tri_control),\n\t\t.i_controller_toggle_dqs(ddr3_toggle_dqs),\n\t\t.i_controller_data(ddr3_data),\n\t\t.i_controller_dm(ddr3_dm),\n\t\t.i_controller_odelay_data_cntvaluein(ddr3_odelay_data_cntvaluein),\n\t\t.i_controller_odelay_dqs_cntvaluein(ddr3_odelay_dqs_cntvaluein),\n\t\t.i_controller_idelay_data_cntvaluein(ddr3_idelay_data_cntvaluein),\n\t\t.i_controller_idelay_dqs_cntvaluein(ddr3_idelay_dqs_cntvaluein),\n\t\t.i_controller_odelay_data_ld(ddr3_odelay_data_ld),\n\t\t.i_controller_odelay_dqs_ld(ddr3_odelay_dqs_ld),\n\t\t.i_controller_idelay_data_ld(ddr3_idelay_data_ld),\n\t\t.i_controller_idelay_dqs_ld(ddr3_idelay_dqs_ld),\n\t\t.i_controller_bitslip(ddr3_bitslip),\n\t\t.i_controller_write_leveling_calib(ddr3_write_leveling_calib),\n\t\t.o_controller_iserdes_data(ddr3_iserdes_data),\n\t\t.o_controller_iserdes_dqs(ddr3_iserdes_dqs),\n\t\t.o_controller_iserdes_bitslip_reference(ddr3_iserdes_bitslip_reference),\n\t\t.o_controller_idelayctrl_rdy(ddr3_idelayctrl_rdy),\n\t\t// DDR3 I/O Interface\n\t\t.o_ddr3_clk_p(o_ddr3_clk_p),\n\t\t.o_ddr3_clk_n(o_ddr3_clk_n),\n\t\t.o_ddr3_reset_n(o_ddr3_reset_n),\n\t\t.o_ddr3_cke(o_ddr3_cke[0]), // CKE\n\t\t.o_ddr3_cs_n(o_ddr3_cs_n[0]), // chip select signal (controls rank 1 only)\n\t\t.o_ddr3_ras_n(o_ddr3_ras_n), // RAS#\n\t\t.o_ddr3_cas_n(o_ddr3_cas_n), // CAS#\n\t\t.o_ddr3_we_n(o_ddr3_we_n), // WE#\n\t\t.o_ddr3_addr(o_ddr3_a[SDRAMROW_BITS-1:0]),\n\t\t.o_ddr3_ba_addr(o_ddr3_ba),\n\t\t.io_ddr3_dq(io_ddr3_dq),\n\t\t.io_ddr3_dqs(io_ddr3_dqs_p),\n\t\t.io_ddr3_dqs_n(io_ddr3_dqs_n),\n\t\t.o_ddr3_dm(o_ddr3_dm),\n\t\t.o_ddr3_odt(o_ddr3_odt[0]), // on-die termination\n\t\t// DEBUG PHY\n\t\t.o_ddr3_debug_read_dqs_p(ddr3_debug_read_dqs_p),\n\t\t.o_ddr3_debug_read_dqs_n(ddr3_debug_read_dqs_n)\n\t\t// }}}\n\t);\n\n\tgenerate for(ddr3gen_index = SDRAMROW_BITS;\n\t\t\tddr3gen_index < 15;\n\t\t\tddr3gen_index = ddr3gen_index + 1)\n\tbegin : GEN_UNUSED_SDRAM_ASSIGN\n\t\tassign o_ddr3_a[ddr3gen_index] = 0;\n\tend endgenerate\n\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// HDMI Clock generation\n\t// {{{\n\n\txpxclk\n\tu_xpxclk (\n\t\t.i_sysclk(s_clk),\t\t// System clock\n\t\t.i_cksel(w_pxclk_cksel),\t\t// Clock select switch\n\t\t//\n\t\t.i_hdmirx_clk_p(i_hdmirx_clk_p),\t// HDMI RX input clock\n\t\t.i_hdmirx_clk_n(i_hdmirx_clk_n),\n\t\t.i_lcl_pixclk(s_clk_80mhz_unbuffered),\t// Locally generated clk\n\t\t.i_siclk(s_clk_80mhz_unbuffered),\n\t\t//\n\t\t.o_hdmick_locked(pxrx_locked),\n\t\t.o_hdmirx_clk(hdmirx_clk),\t// Clk for measurement only\n\t\t.o_pixclk(hdmi_ck),\t\t// Pixel clock\n\t\t.o_hdmick(hdmi_serdes_clk),\t// HS pixel clock\n\t\t//\n\t\t.i_wb_clk(s_clk),\n\t\t//\n\t\t.i_wb_cyc(w_pxclk_cyc), .i_wb_stb(w_pxclk_stb),\n\t\t\t.i_wb_we(w_pxclk_we),\n\t\t\t.i_wb_addr(w_pxclk_addr[7-1:0]),\n\t\t\t.i_wb_data(w_pxclk_data), // 32 bits wide\n\t\t\t.i_wb_sel(w_pxclk_sel),  // 32/8 bits wide\n\t\t.o_wb_stall(w_pxclk_stall),.o_wb_ack(w_pxclk_ack),\n\t\t\t.o_wb_data(w_pxclk_idata),\n\t\t//\n\t\t.o_debug(pxclk_debug)\n\t);\n\t// }}}\n\n\t// RGMII control\n\t// {{{\n\txiddr\tnetrx0(i_net_rx_clk, i_net_rxd[0], { w_net_rxd[4], w_net_rxd[0] });\n\txiddr\tnetrx1(i_net_rx_clk, i_net_rxd[1], { w_net_rxd[5], w_net_rxd[1] });\n\txiddr\tnetrx2(i_net_rx_clk, i_net_rxd[2], { w_net_rxd[6], w_net_rxd[2] });\n\txiddr\tnetrx3(i_net_rx_clk, i_net_rxd[3], { w_net_rxd[7], w_net_rxd[3] });\n\txiddr\tnetrxc(i_net_rx_clk, i_net_rx_ctl, { w_net_rxdv,   w_net_rxerr });\n\n\t//\n\t// All of the below is about delaying the clock 90 degrees from the data\n\t//\n\txoserdes\tnettx0(s_clk_125mhz, pll_reset, s_clk_250mhz, { {(2){w_net_txd[0]}}, {(2){w_net_txd[4]}} }, o_net_txd[0]);\n\txoserdes\tnettx1(s_clk_125mhz, pll_reset, s_clk_250mhz, { {(2){w_net_txd[1]}}, {(2){w_net_txd[5]}} }, o_net_txd[1]);\n\txoserdes\tnettx2(s_clk_125mhz, pll_reset, s_clk_250mhz, { {(2){w_net_txd[2]}}, {(2){w_net_txd[6]}} }, o_net_txd[2]);\n\txoserdes\tnettx3(s_clk_125mhz, pll_reset, s_clk_250mhz, { {(2){w_net_txd[3]}}, {(2){w_net_txd[7]}} }, o_net_txd[3]);\n\n\talways @(posedge s_clk_125mhz)\n\t\tnet_last_tck <= w_net_tx_clk[0];\n\n\txoserdes\tnettxc(s_clk_125mhz, pll_reset, s_clk_250mhz, {(4){w_net_txctl}}, o_net_tx_ctl );\n\n\txoserdes\tnettxck(s_clk_125mhz, pll_reset, s_clk_250mhz, {net_last_tck, {(2){w_net_tx_clk[1]}},w_net_tx_clk[0]},o_net_tx_clk);\n\t// xoserdes\tnettxck(s_clk_125mhz, pll_reset, s_clk_250mhz, { {(2){w_net_tx_clk[1]}},{(2){w_net_tx_clk[0]}} }, o_net_tx_clk);\n\t// }}}\n\n\tassign\to_led = { w_led[8-1:3],\n\t\t\t(w_led[2] || !syncd_stable[3]),\n\t\t\t(w_led[1] || !clocks_locked),\n\t\t\t(w_led[0] || s_reset) };\n\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// GPIO adjustments\n\t// {{{\n\tassign\ti_gpio = { 8'h0,\n\t\t\tpxrx_locked,\n\t\t\tsysclk_locked,\n`ifdef\tGPSTRK_ACCESS\n\t\t\ti_gps_3df,\n`else\n\t\t\t1'b0,\n`endif\n\t\t\t!i_hdmitx_hpd_n,\t// Hotplug detect\n\t\t\t!i_sd_cd_n,\n\t\t\t1'b0,\n\t\t\ti_hdmitx_cec, i_hdmirx_cec };\n\tassign\to_hdmirx_txen = o_gpio[2];\n\tassign\to_hdmirx_hpa  = o_gpio[3];\t// Hotplug assert\n\tassign\to_sd_reset  = !w_sdio_hwreset_n;\n\tassign\to_oled_reset_n  = !o_gpio[5];\n\tassign\to_oled_panel_en =  o_gpio[6];\n\tassign\to_oled_logic_en =  o_gpio[7];\n\t// These two pins are only used in simulation, and only within the\n\t// MAIN RTL component.\n\t// assign o_trace     = o_gpio[8];\n\t// assign o_halt      = o_gpio[9];\n\n\t// }}}\n\n\tsdfrontend #(\n\t\t.OPT_SERDES(1'b1),\n\t\t.OPT_DDR(1'b1),\n\t\t.NUMIO(4),\n\t\t.BUSY_CLOCKS(16),\n\t\t.OPT_CRCTOKEN(1)\n\t) u_sdio_frontend (\n\t\t// {{{\n\t\t.i_clk(s_clk), .i_hsclk(s_clk_400mhz), .i_reset(s_reset),\n\t\t// Configuration\n\t\t.i_cfg_ddr(w_sdio_cfg_ddr),\n\t\t.i_cfg_ds(w_sdio_cfg_ds),\n\t\t.i_cfg_dscmd(w_sdio_cfg_dscmd),\n\t\t.i_sample_shift(w_sdio_cfg_sample_shift),\n\t\t.i_cmd_tristate(w_sdio_cmd_tristate),\n\t\t.i_data_tristate(w_sdio_data_tristate),\n\t\t// Run-time inputs\n\t\t.i_sdclk(w_sdio_sdclk),\n\t\t.i_cmd_en(w_sdio_cmd_en),\n\t\t.i_cmd_data(w_sdio_cmd_data),\n\t\t.i_data_en(w_sdio_data_en),\n\t\t.i_rx_en(w_sdio_rx_en),\n\t\t.i_tx_data(w_sdio_tx_data),\n\t\t// Return values\n\t\t.o_cmd_strb(w_sdio_cmd_strb),\n\t\t.o_cmd_data(w_sdio_cmd_idata),\n\t\t.o_cmd_collision(w_sdio_cmd_collision),\n\t\t.o_crcack(w_sdio_crcack),\n\t\t.o_crcnak(w_sdio_crcnak),\n\t\t.o_data_busy(w_sdio_card_busy),\n\t\t.o_rx_strb( w_sdio_rx_strb),\n\t\t.o_rx_data( w_sdio_rx_data),\n\t\t//\n\t\t.MAC_VALID(w_sdio_ac_valid),\n\t\t.MAC_DATA( w_sdio_ac_data),\n\t\t.MAD_VALID(w_sdio_ad_valid),\n\t\t.MAD_DATA( w_sdio_ad_data),\n\t\t// IO ports\n\t\t.o_ck(w_sdio_ck),\n\t\t.i_ds(w_sdio_ds),\n\t\t.io_cmd(io_sd_cmd),\n\t\t.io_dat(io_sd_dat),\n\t\t.o_debug(w_sdio_debug)\n\t\t// }}}\n\t);\n\n\n\tassign\to_sd_clk = w_sdio_ck;\n\n\tassign\tw_sdio_ds    = 1'b0;\n\n\n\t// Buffer the incoming clock\n\tBUFG masterclkclkbufi(.I(i_clk), .O(i_clk_buffered));\n\n\t// pll_reset\n\tinitial\t{ pll_reset, pll_reset_sreg } = -1;\n\talways @(posedge i_clk_buffered)\n\t\t{ pll_reset, pll_reset_sreg } <= { pll_reset_sreg, 1'b0 };\n\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// PLL #1: 100MHz, 200MHz, 400MHz, and 80MHz\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t//\n\n\t// But ... the delay controller requires a 200 MHz reference clock,\n\t// the generic clock generator requires a 400MHz clock and a clock\n\t// synchronized to it\n\tPLLE2_BASE #(\n\t\t// {{{\n\t\t.CLKFBOUT_MULT(8),\n\t\t.CLKFBOUT_PHASE(0.0),\n\t\t.CLKIN1_PERIOD(10),\n\t\t.CLKOUT0_DIVIDE(4),\t// 200 MHz\n\t\t.CLKOUT1_DIVIDE(2),\t// 400 MHz\n\t\t.CLKOUT2_DIVIDE(8),\t// 100 MHz\n\t\t.CLKOUT3_DIVIDE(10)\t//  80 MHz\n\t\t// }}}\n\t) gen_sysclk(\n\t\t// {{{\n\t\t.CLKIN1(i_clk_buffered),\n\t\t.CLKOUT0(s_clk_200mhz_unbuffered),\n\t\t.CLKOUT1(s_clk_400mhz_unbuffered),\n\t\t.CLKOUT2(s_clksync_unbuffered),\n\t\t.CLKOUT3(s_clk_80mhz_unbuffered),\n\t\t// .CLKOUT4(),\n\t\t// .CLKOUT5(),\n\t\t.PWRDWN(1'b0), .RST(pll_reset),\n\t\t.CLKFBOUT(sysclk_feedback),\n\t\t.CLKFBIN(sysclk_feedback_buffered),\n\t\t.LOCKED(sysclk_locked)\n\t\t// }}}\n\t);\n\n\tBUFG\tsysbuf(     .I(s_clk_200mhz_unbuffered),.O(s_clk_200mhz));\n\tBUFG\tclksync_buf(.I(s_clksync_unbuffered),   .O(s_clksync));\n\tBUFG\tclk4x_buf(  .I(s_clk_400mhz_unbuffered),.O(s_clk_400mhz));\n\tBUFG\tsys_feedback(.I(sysclk_feedback),.O(sysclk_feedback_buffered));\n\n\t// }}}\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// PLL #2: 125MHz, 250MHz\n\t// {{{\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t//\n\n\t// The ethernet MAC requires a 125MHz clock\n\t//   We can't trust the RX 125MHz clock for this, since there's a\n\t//   possibility the RX 125MHz clock might arrive at a different rate.\n\t//\n\tPLLE2_BASE #(\n\t\t// {{{\n\t\t.CLKFBOUT_MULT(10),\n\t\t.CLKFBOUT_PHASE(0.0),\n\t\t.CLKIN1_PERIOD(10),\n\t\t.CLKOUT0_DIVIDE(8),\t// 125 MHz\n\t\t.CLKOUT0_PHASE(0),\n\t\t.CLKOUT1_DIVIDE(4),\t// 250 MHz\n\t\t.CLKOUT1_PHASE(0)\n\t\t// }}}\n\t) gen_netclk(\n\t\t// {{{\n\t\t.CLKIN1(i_clk_buffered),\n\t\t.CLKOUT0(s_clk_125_unbuffered),\n\t\t.CLKOUT1(s_clk_250_unbuffered),\n\t\t// .CLKOUT2(),\n\t\t// .CLKOUT3(),\n\t\t// .CLKOUT4(),\n\t\t// .CLKOUT5(),\n\t\t.PWRDWN(1'b0), .RST(pll_reset),\n\t\t.CLKFBOUT(netclk_feedback),\n\t\t.CLKFBIN(netclk_feedback_buffered),\n\t\t.LOCKED(netclk_locked)\n\t\t// }}}\n\t);\n\n\tBUFG\tnetbuf(.I(s_clk_125_unbuffered), .O(s_clk_125mhz));\n\tBUFG\tnetbf5(.I(s_clk_250_unbuffered), .O(s_clk_250mhz));\n\tBUFG\tnetfb(.I(netclk_feedback), .O(netclk_feedback_buffered));\n\n\tassign\tclocks_locked = (netclk_locked && sysclk_locked && dly_ctrl_ready);\n\n\t// }}}\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// reg\t[3:0]\tsysclk_stable;\n\t// {{{\n\tinitial\tsysclk_stable = 0;\n\talways @(posedge i_clk_buffered or negedge clocks_locked)\n\tif (!clocks_locked)\n\t\tsysclk_stable <= 0;\n\telse\n\t\tsysclk_stable <= { sysclk_stable[2:0], 1'b1 };\n\n\tinitial\tsyncd_stable = 0;\n\talways @(posedge i_clk_buffered)\n\tif (!sysclk_stable[3])\n\t\tsyncd_stable <= 0;\n\telse\n\t\tsyncd_stable <= { syncd_stable[2:0], 1'b1 };\n\n\t// }}}\n\t////////////////////////////////////////////////////////////////////////\n\t//\n\t// IDELAYCTRL\n\tIDELAYCTRL\n\tu_delay_control (\n\t\t.REFCLK(s_clk_200mhz),\n\t\t.RST(!sysclk_locked),\n\t\t.RDY(dly_ctrl_ready)\n\t);\n\n\n\tassign\to_vadj = 2'b11;\n\tinitial\tvadj33_vadj_counter = 0;\n\talways @(posedge i_clk_buffered)\n\tif (!vadj33_vadj_counter[4])\n\t\tvadj33_vadj_counter[4] <= vadj33_vadj_counter[4] + 1;\n\tassign\to_vadj_en = vadj33_vadj_counter[4];\n\n\tassign\tio_eth_mdio = (w_mdwe)?w_mdio : 1'bz;\n\n\n\nendmodule // end of toplevel.v module definition\n"
  },
  {
    "path": "doc/Makefile",
    "content": "################################################################################\n##\n## Filename:\tdoc/Makefile\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\tTo coordinate the build of documentation PDFs from their\n##\t\tLaTeX sources.\n##\n##\tTargets include:\n##\t\tall\t\tBuilds all documents\n##\n##\t\tgpl-3.0.pdf\tBuilds the GPL license these files are released\n##\t\t\t\t\tunder.\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2015-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\nall:\tgpl\npdf:\tgpl spec\nDSRC := src\n\n.PHONY: gpl\n## {{{\ngpl: gpl-3.0.pdf\n\ngpl-3.0.pdf: $(DSRC)/gpl-3.0.tex\n\tlatex $(DSRC)/gpl-3.0.tex\n\tlatex $(DSRC)/gpl-3.0.tex\n\tdvips -q -z -t letter -P pdf -o gpl-3.0.ps gpl-3.0.dvi\n\tps2pdf -dAutoRotatePages=/All gpl-3.0.ps gpl-3.0.pdf\n\trm gpl-3.0.dvi gpl-3.0.log gpl-3.0.aux gpl-3.0.ps\n## }}}\n\n.PHONY: spec\n## {{{\nspec: spec.pdf\n\nspec.pdf: $(DSRC)/spec.tex $(DSRC)/gqtekspec.cls $(DSRC)/GT.eps\n\tcd $(DSRC)/; latex spec.tex\n\tcd $(DSRC)/; latex spec.tex\n\tcd $(DSRC)/; dvips -q -z -t letter -P pdf -o ../spec.ps spec.dvi\n\tps2pdf -dAutoRotatePages=/All spec.ps spec.pdf\n\t-grep -i warning $(DSRC)/spec.log\n\t@rm -f $(DSRC)/spec.dvi $(DSRC)/spec.log\n\t@rm -f $(DSRC)/spec.aux $(DSRC)/spec.toc\n\t@rm -f $(DSRC)/spec.lot $(DSRC)/spec.lof\n\t@rm -f $(DSRC)/spec.out spec.ps\n## }}}\n\n.PHONY: clean\n## {{{\nclean:\n\trm -f $(DSRC)/spec.dvi $(DSRC)/spec.log\n\trm -f $(DSRC)/spec.aux $(DSRC)/spec.toc\n\trm -f $(DSRC)/spec.lot $(DSRC)/spec.lof\n\trm -f $(DSRC)/spec.out spec.ps spec.pdf\n\trm -f gpl-3.0.pdf\n## }}}\n"
  },
  {
    "path": "doc/bus.md",
    "content": "## Bus Declarations\n\nBefore creating any bus-based components, you'll want to declare the bus\nthat these components will connect to.  This is primarily done through\nthe `BUS.NAME`, `BUS.TYPE`, `BUS.CLOCK`, and `BUS.WIDTH` tags.\n\n`BUS.NAME` gives the bus a short-hand name that you can then use to reference\nit within other design components.\n\n`BUS.TYPE` names the protocol used by the bus.  As of this writing, AutoFPGA\nsupports three bus types: `wb` for Wishbone (B4 pipeline), `axil` for\nAXIr-Lite, and `axi` for the AXI4 bus types.\n\n`BUS.WIDTH` defines the data width of the bus.\n\nThe bus address width will be defined internally based upon the minimum\naddress width required to address all of your components.  Once addresses\nhave been assigned, `BUS.AWID` may be used to reference the number of\naddressing wires used and defined by this bus.  This is separate from the\nper-component `AWID` tag which may be used to reference the number of\naddress bits used an individual component.\n\nAs with the clocks, you can define as many buses as you want within your\ndesign.  However, only one bus can be defined per component, i.e. per\n`@PREFIX` tag, lest the `@BUS` tags overwrite each other.\n\nAs an example, the following defines a 32-bit Wishbone bus,\n\n```text\n@PREFIX=mywb_definition\n@BUS.NAME=mywb\n@BUS.TYPE=wb\n@BUS.CLOCK=clk\n@BUS.WIDTH=32\n```\n\n"
  },
  {
    "path": "doc/clocks.md",
    "content": "## Defining clocks\n\nThe first item you'll want to define within your design is a clock.  You may\ndefine more than one in your design, and design elements may use them at\nwill, but you may only define one clock within any component.  For this\nreason, I typically create a component for each of my clock definitions.\n\n```text\n@CLOCK.NAME=clk\n@CLOCK.WIRE=i_clk\n@CLOCK.FREQUENCY=100000000\n```\n\nThis defines a clock known to AutoFPGA as `clk`.  Within your `main.v`\ndesign file it will be known as `i_clk`.\n\n## Associating a reset\n\nOften clock domains also have a reset associated with them.  For this reason,\nAutoFPGA allows the definition of an associated reset.\n\n```text\n@CLOCK.RESET=i_reset\n```\n\nThis is primarily a convenience definition that you can use if you wish.\nIt may also be used by the bus composer, by any design whose bus doesn't\nhave an associated reset.  This will then be used as the reset for that bus,\notherwise AutoFPGA may generate an error that the bus has no associated\nreset wire.\n\n## Default clock and reset\n\nThe clock named `i_clk` is special.\nIt is automatically passed to the `main` module for you.  To make this work,\nyou'll need a clock in your top level named `s_clk`, that will then be\nforwarded directly to your main module.\n\nFrom the top level, AutoFPGA's generated code will look like,\n\n```verilog\nmodule toplevel(i_clk, /* ... */);\n   input wire i_clk;\n\n   /* Your code here */\n\n   main themain(s_clk, s_reset, ...\n```\n\nFor this reason, you'll want to define a clock named `s_clk` in your\ntop level.  You'll also want to define `s_reset`.  These can be as simple\nas defining these two wires,\n\n```text\n@TOP.DEFNS=\n    wire s_clk, s_reset;\n```\n\nand then adding the `TOP.INSERT` tag to your clock definition,\n\n```text\n@TOP.INSERT=\n    assign s_clk = i_clk;\n    assign s_reset = 1'b0;\n```\n\nIf your external clock needs to have a top level port assigned to it, then\nyou'll want to use the `CLOCK.TOP` tag to specify its name.  For example,\nthe following defines a 50MHz input clock, transformed via logic to become the\n50MHz top level clock.  (Normally I'd recommend using a PLL, but due to a\nmistake during board design, the PLL wasn't available for this pin.)\n\n```text\n@PREFIX=clk\n@CLOCK.TOP=i_clk\n@CLOCK.NAME=clk\n@CLOCK.RESET=i_reset\n@TOP.DEFNS=\n\treg\tclk_50mhz;\n\twire\ts_clk, s_reset;\n@TOP.INSERT=\n\tassign\ts_reset = 1'b0;\n\n\tinitial\tclk_50mhz = 1'b0;\n\talways @(posedge i_clk)\n\t\tclk_50mhz <= !clk_50mhz;\n\n\tSB_GB global_buffer(clk_50mhz, s_clk);\n\n@CLOCK.FREQUENCY= 50000000\n```\n"
  },
  {
    "path": "doc/constraints.md",
    "content": "## Adjusting Constraint files\n\nOne of the challenges associated with adding and removing components from a\ndesign is that the constraint files also need to be adjusted as well.\nAutoFPGA provides some support for doing this across several architectures.\n\nThe basic idea is that you would declare an original constraint file\nto AutoFPGA.  This needs to be done at the top level of your design, before\nany PREFIX tags in a given file.\n\n```text\nXDC.FILE=../nexysv.xdc\n```\n\nAutoFPGA will then reference that file when building a new XDC file.\n\n## XDC file support\n\nFor example, if you give AutoFPGA an `XDC.FILE` tag, as shown above,\nthen AutoFPGA will create a new XDC file based upon it.  Specifically,\nit will uncomment any lines in your XDC file defining ports used by your\ncomponent, and it will also insert any `XDC.INSERT` tags required by your\ncomponent into the newly produced XDC file.  All you need to do then is to\nmaintain a master XDC file where all of the various I/O port definitions\nare commented. AutoFPGA will then uncomment only the ports defined in your\n`TOP.PORTLIST` tag--or alternatively your `MAIN.PORTLIST` tag if no\n`TOP.PORTLIST` tag is defined.\n\nFor example, in my ethernet component, I need to define a series of false\npaths.  These are only used if the ethernet component is included into the\ndesign.  Therefore, they are placed into the `XDC.INSERT` tag.\n\n```\n@XDC.INSERT=\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *netctrl/tx*}]              -to [get_cells -hier -filter {NAME=~*netctrl/n_tx*}]               8.0\nset_max_delay -datapath_only -from [get_cells -hier -filter {NAME=~ *netctrl/hw_mac*}]          -to [get_cells -hier -filter {NAME=~*netctrl/txmaci/r_hw*}]        8.0\n```\n\n## Other Constraint Files\n\nAutoFPGA has similar support for UCF and PCF files.\n\n"
  },
  {
    "path": "doc/double.md",
    "content": "# Double Slave Definitions\n\nAutoFPGA defines two special classes of slaves, `SINGLE` and `DOUBLE`.  These\nclasses are used to help AutoFPGA coalesce bus logic together, while\nsimplifying your design.\n\nThe `DOUBLE` slave describes a slave that may have many registers, that\nnever stalls, and whose register values may be read with a single\nclock cycle delay.  It's almost as simple as the `SINGLE` slave to\ncreate.\n\n```text\n@PREFIX=wb_double_example\n@SLAVE.NADDR=2\n@SLAVE.BUS=wbbus\n@SLAVE.TYPE=DOUBLE\n@MAIN.DEFNS=\n\treg\t[31:0]\tr_@$(PREFIX)_0, r_@$(PREFIX)_b, r_@$(PREFIX)_rdata;\n@MAIN.INSERT=\n\tinitial\tr_@$(PREFIX)_0 = 0;\n\talways @(posedge i_clk)\n\tif (@$(SLAVE.PREFIX)_stb && !@$(SLAVE.PREFIX)_addr[0])\n\t\tr_@$(PREFIX)_0 <= @$(SLAVE.PREFIX)_data;\n\telse if (r_@$(PREFIX)_0 > 0)\n\t\tr_@$(PREFIX)_0 <= r_@$(PREFIX)_0 - 1;\n\n\tinitial\tr_@$(PREFIX)_1 = 0;\n\talways @(posedge i_clk)\n\tif (@$(SLAVE.PREFIX)_stb && @$(SLAVE.PREFIX)_addr[0])\n\t\tr_@$(PREFIX)_1 <= @$(SLAVE.PREFIX)_data;\n\telse if (r_@$(PREFIX)_1 > 0)\n\t\tr_@$(PREFIX)_1 <= r_@$(PREFIX)_1 - 1;\n\n\talways @(posedge i_clk)\n\tcase (@$(SLAVE.PREFIX)_addr[0])\n\t1'b0:\tr_@$(PREFIX)_data <= r_@$(PREFIX)_0;\n\t1'b1:\tr_@$(PREFIX)_data <= r_@$(PREFIX)_1;\n\tendcase\n\n\tassign @$(SLAVE.PREFIX)_idata = r_@$(PREFIX)_rdata;\n```\n\nThis will create your slave and connect it to the bus named `wbbus`.  Any\nattempt to read from your slave will return the value `r_@$(PREFIX)_rdata`,\nwhich was itself calculated from the bus address given to it one clock prior.\n\nBuilding this same example for an AXI or AXI-Lite bus is almost the\nsame, only that you also need to define values for `@$(SLAVE.PREFIX)_bresp`\nand `@$(SLAVE.PREFIX)_rresp`.  Further, AXI slave addresses are octet based,\nwhereas Wishbone addresses are word based.  Hence we'll check awaddr[2]\ninstead of addr[0].\n\n```text\n@PREFIX=wb_double_example\n@SLAVE.NADDR=2\n@SLAVE.BUS=axilbus\n@SLAVE.TYPE=DOUBLE\n@MAIN.INSERT=\n\tinitial\tr_@$(PREFIX)_0 = 0;\n\talways @(posedge i_clk)\n\tif (@$(SLAVE.PREFIX)_awvalid && !@$(SLAVE.PREFIX)_awaddr[2])\n\t\tr_@$(PREFIX)_0 <= @$(SLAVE.PREFIX)_data;\n\telse if (r_@$(PREFIX)_0 > 0)\n\t\tr_@$(PREFIX)_0 <= r_@$(PREFIX)_0 - 1;\n\n\tinitial\tr_@$(PREFIX)_1 = 0;\n\talways @(posedge i_clk)\n\tif (@$(SLAVE.PREFIX)_stb && @$(SLAVE.PREFIX)_addr[2])\n\t\tr_@$(PREFIX)_1 <= @$(SLAVE.PREFIX)_data;\n\telse if (r_@$(PREFIX)_1 > 0)\n\t\tr_@$(PREFIX)_1 <= r_@$(PREFIX)_1 - 1;\n\n\talways @(posedge i_clk)\n\tcase (@$(SLAVE.PREFIX)_addr[0])\n\t1'b0:\tr_@$(PREFIX)_data <= r_@$(PREFIX)_0;\n\t1'b1:\tr_@$(PREFIX)_data <= r_@$(PREFIX)_1;\n\tendcase\n\n\tassign @$(SLAVE.PREFIX)_rdata = r_@$(PREFIX)_rdata;\n```\n\nWhen creating an AXI or AXI-Lite `DOUBLE` slave, AutoFPGA will use one of the\nbus simplifiers found in the [WB2AXIP](https://github.com/ZipCPU/wb2axip)\nrepository, either\n[AXIDOUBLE](https://github.com/ZipCPU/wb2axip/blob/master/rtl/axisingle.v) or\n[AXILDOUBLE](https://github.com/ZipCPU/wb2axip/blob/master/rtl/axilsingle.v).\nThese drivers will guarantee for you that the respective `xREADY` lines remain\nhigh, and that `AWVALID == WVALID` (and more).  All you therefore need to do\nis to check `WVALID` to know when to adjust your counter.\n\nFor more information about these bus drivers, please see their internal\ndocumentation.\n\nAs with the `SINGLE` slaves, AutoFPGA defines a `@SLAVE.PORTLIST` tag that\nexpands into a list of all of your design ports.  This makes it easier to\ndesign an AXI slave from a submodule.\n\n```text\n@MAIN.INSERT=\n\tmymodule @$(PREFIX)i (i_axi_aclk, i_axi_aresetn,\n\t\t@$(SLAVE.PORTLIST));\n```\n"
  },
  {
    "path": "doc/goals.txt",
    "content": "1. Be able to create a project from a series of configuration files, where each\n\tfile specifies a component of the ultimate project.\n2. Maintain the look/feel of an open source project\n\tAll source should be readable, and maintainable.  This includes any\n\tcomponent configuration/description files\n3. Turn into a full Verilog/C/C++ project\n\tCode should be \"added\" at appropriate points down stream\n\tRemoving a component should just take appropriate code sections out\n\tlater.\n\n\tConfiguration files should consist of those data portions necessary\n\tto cut/copy/paste into a project to get it up and running.  The\n\tresult should therefore be as though someone had configured the project\n\tby hand and included the new component, only that the auto-component\n\tcompiler had done the configuration work instead.\n4. Preserve the ability to have comments in the ultimate source code.  Such\n\tcomments should be able to pass through the configuration files\n"
  },
  {
    "path": "doc/icd.txt",
    "content": "AutoFPGA does all of its work based upon KEY/VALUE pairs.  Key/value pairs\nare organized into a hierarchical, but unordered, structure which is then\nreferenced by the logic that follows.  The values themselves are either strings\nor numbers.\n\nLines defining keys may begin as:\n@KEY=\tDefining a given key\n@$KEY=\tDefines a numeric key value that may need to be evaluated\n@KEY+=\tConcatenates the following onto the pre-existing string key.  If the\n\tkey does not (yet) exist, it is created and initialized to this value.\n@/KEY=\tReferences a global key\n@/KEY+=\tConcatenates onto a global key\n\n\nLines not defining keys are either comment lines (lines beginning with either\n## or # and a space), or lines appended to the value of the last key.\n\nAutoFPGA document lines starting with @ specify a key name.  Lines starting with\na @$ specify an integer valued expression.  The key is given by the string\nbetween the @ (or @$) and the ='s (minus any white space at the end, white\nspace at the beginning is not allowed).  KEYs are case sensitive.  By\nconvention, KEYs are in all caps, although keys with lower case letters are\nallowed and used as names of particular file components.  For the discussion \nbelow, any keys will be identified by prefixing the key name with an @ sign.\n\nComments.  Lines beginning with either two hash marks, ##, or a single hash\nfollowed by a space, as in \"# \", are comment lines.  Other lines beginning\nwith \"#\", such as #define, are not comments, neither do lines containing \"#\"\nin any location other than the first location contain comments.\n\nKEYs are by convention all capitals.  They are also hierarchical.  Hence,\na key BDEFS.IONAME references the BDEFS set of key-value pairs, with the keyname\nIONAME within that set.\n\nEvery device or bus master *must* contain a @PREFIX key.  This key will be used\nas a unique string to identify the device.  As parsing takes place, all of the\nkeys for a given device will be placed into a key-value set prefixed by the\n@PREFIX key.  Hence, for a device with name @PREFIX=uart, a definition such as\n@NADDR=4 creates a key named @uart.NADDR and gives it the value 4. \n\nKeys defined prior to the first @PREFIX key are global keys, and are not given\nany @PREFIX in front of them prior to being inserted into the master key-value\nmapping.\n\nKey definitions beginning with @$ are integer expressions that will be evaluated\nbefore use.\n\nFurther, strings may reference other parts of the key-value mapping by placing\na @$ in front of a key name.  This value will then be replaced by the value\nonce that value is known.  Expressions may also be used when assigning to\nthings such as @$KEY, as in ...\n@$KEY.EXPR=(1<<20)\n@KEY.FORMAT=0x%08x\n@KEY.VAL will be created with the calculated value\n@KEY.STR will be created with the value formated as desired into a string\nOnce this expression has a value, a new key will be created, KEY.VAL, having\nthe integer value of this expression.  This value may be referenced via the\nbase @KEY.  Further, this value will be substituted wherever @$KEY exists\nwithin any other VALUE's.  Which value it gets, either the number or the\nstring, is dependent upon the context and how it is referenced.\n\nPeripheral devices *must* also contain a @SLAVE.TYPE key.  This key can have\none of the following values:\n\tSINGLE\tA peripheral with no internal address decoding, but\n\t\twhose output value (@PREFIX_data) is valid on any given clock.\n\t\tThese peripherals are not allowed to stall the bus.\n\t\tThese peripherals will be collected together.\n\tDOUBLE\tA peripheral with internal address decoding, but no delays.\n\t\tHence, the data value for this peripheral will always be valid\n\t\tone clock after the select line goes high.\n\t\tThese peripherals are not allowed to stall the bus.\n\t\tThese peripherals will also be collected together.\n\tMEMORY\tA peripheral including information that needs to be placed into\n\t\ta linker script.  Examples of MEMORY can be block RAM's,\n\t\tSDRAM, or even FLASH.  MEMORY that fits the criteria for DOUBLE\n\t\tis also best given the MEMORY attribute instead.\n\tBUS\tThis slave is a bus translator.  It acts as a slave on its\n\t\tgiven bus, but has a bus (MASTER) interface beneath it\n\tOTHER\tAny peripheral that doesn't match the above.\n\n\nOther tags include\nACCESS\tThis is a STRING that will be turned into a DEFINE and a couple IFDEFs\n\tin the main.v file.  The idea is, if this string is defined, then the\n\tcomponents logic will be included, otherwise not.\n\nDEPENDS\tIf the logic of one component is dependent upon another, set the\n\tDEPENDS tag to be a list of ACCESS parameters upon which this component\n\tdepends upon.  The ACCESS item for this parameter will then be\n\tturned off if it's dependencies are not met.\n\n\tDependencies beginning with a \"!\" are negative dependencies.  Hence, the\n\tACCESS tag will only be true if the dependency ifdef is *not* defined.\n\t(No spaces are allowed between the ! and the dependency ID)\n\nNADDR\tThe number of uniquely addressable registers/ports this device has\nERROR.WIRE\tThe name of a wire set by the module, which (if set) will cause\n\ta bus error.  Components should only set this if they are being\n\taccessed.\nINCLUDEFILE\n\tDefines a file with default key values within it.  If those key values\n\tare then not defined in the main file, the include file will be checked\n\tfor default values.  The include path searched can be controlled via\n\tthe '-I' command line option.\nTOP.PORTLIST\n\tThis string gets added into the toplevel( portlist ) declaration,\n\tallowing each peripheral to control external wires.  If not specified,\n\tthis is given by MAIN.PORTLIST.\n\nTOP.IODECL\n\tThis string includes the declarations for the portlist above, such as\n\toutput wire o_value.  If not specified, this is given by MAIN.IODECL.\n\nTOP.DEFNS\n\tDefines variables in toplevel.v\nTOP.MAIN\n\tThis string gets added into the main module instantiation, between\n\tthe ( parentheses ).\nTOP.INSERT\n\tSome peripherals need some cleanup.  Hence, after instantiating main,\n\tthese need to do some logic.  Any variables needed here need to have\n\tbeen declared in TOP.DEFNS.\n\nMAIN.INCLUDE\n\tSpecicies logic to be placed before module main in main.v\nMAIN.PARAM\n\tLogic placed after the PORTLIST in main.v, used to define parameters\nMAIN.PORTLIST\n\tSame as TOP.PORTLIST, only as applied to the main.v file\nMAIN.IODECL\n\tSame as TOP.IODECL, only as applied to the main.v file\nMAIN.DEFNS\n\tLogic defined after PARAM, PORTLIST, and IODECL.  Used to define\n\tglobal registers or wires used by this component\nMAIN.INSERT\nMAIN.ALT\n\nBASE\t(Created and used internally)\n\tThis is the base address of the given peripheral within its current\n\tbus\nREGBASE (Created and used internally)\n\tThis is the base address of the given peripheral from an external\n\tbus address reference.\nMASK\t(Created and used internally)\nAWID\tAddress width, in terms of # of address lines, used by this component\n\nREGDEFS.H.INCLUDE\tPlaced at the top of the regdefs.h file\nREGS.NOTE\tA comment to be placed at the beginning of the register list\n\t\tfor this peripheral\nREGS.N\t\tThe number of registers this peripheral has.  AutoFPGA will then\n\t\tlook for keys of the form REGS.0 through REGS.(REGS.N-1).\nREGS.0...?\tDescribes a register by name.  The first value is the offset\n\t\twithin the address space of this device.  The second token\n\t\tis a string defining a C #def'd constant.  The third and\n\t\tsubsequent tokens represent human readable names that may be\n\t\tassociated with this register.\nREGDEFS.H.DEFNS\tPlaced with other definitions within regdefs.h\nREGDEFS.H.INSERT Placed in regdefs.h following all of the definitions\nI may change this to the following notation, though:\nREGSDEFS.NOTE\nREGS.<name>.ADDR\t# Offset within the peripheral\nREGS.<name>.UNAME(s)\t# User-readable name\nREGS.<name>.DESC(ription for LaTeX)\n\n\nBDEF.INCLUDE\tGets placed at the top of the board definitions file, and\n\t\tis used to insert references for any particular include files\n\t\tinto the board file.  Include files are not ordered by\n\t\tdependency, so they should either be independent of each other,\n\t\tor they should reference any other component they use.\n\nBDEF.DEFN\tA list of lines defining anything that needs to be defined\n\t\tinside the board component description.  This might include,\n\t\tfor example, a type for the component or particular defines\n\t\tthat define things associated with the component\nBDEF.IONAME\tThe name given to this component in the board.h file\nBDEF.IOTYPE\tThe name of a type, describing the structure of the memory\n\t\tbegin pointed to.\nBDEF.OSDEF\tContains the name of a value that will be #define'd if this\n\t\tcomponent is included in the design, and not otherwise\nBDEF.OSVAL\tA definition line, to be placed into the board definitions file,\n\t\tthat is then used to define a pointer to this type of object\n// Likely to default, in the future, to static volatile @BDEF.IOTYPE *const @BDEF.IONAME = &((@BDEF.IOTYPE *)@BASE);\n(deprecated) IONAME (not BDEF.IONAME)\n(deprecated) CSTRUCT (now BDEF.DEFN)\n\nXDC.FILE\tIf present, autofpga will open this file and look through it\n\t\tfor commented lines defining pins that exist in our top\n\t\tlevel port list.  Lines beginning with a #, but not ##, will\n\t\tbe uncommented and added the build.xdc file.  If no XDC.FILE\n\t\tkey is given, then the build.xdc file will not be created.\nXDC.INSERT\tThis line, if present, gets inserted verbatim at the bottom of\n\t\tthe generated XDC file\nUCF.FILE\tDoes the same thing with a UCF file as was done with the\n\t\tXDC.FILE, creating a build.ucf file when done.\nUCF.INSERT\tAdds lines to the UCF file, just as with the XDC.INSERT tag\n\t\tdoes for the XDC file.\n\nPCF.FILE\tDoes the same thing with a UCF file as was done with the\n\t\tXDC.FILE, creating a build.pcf file when done.\nPCF.INSERT\tAdds lines to the PCF file, just as with the XDC.INSERT tag\n\t\tdoes for the XDC file.\n\nLD.FILE\t\tName of the linker script to generate.  The linker script\n\t\twill reflect memory components found beneath the component\n\t\tcontaining this file.\nLD.SCRIPT\tContains a customized script\nLD.ENTRY\tThe name of the entry symbol in the linker script.\nLD.DEFNS\t(Any definitions to be added to the linker script)\n\n\t\tIf the peripheral has an LD.FILE attribute,  the LD.DEFNS\n\t\twill not be included in any other linker scripts\nLD.PERM\t\tThe permissions a memory region has before the linker.\n\t\tThis is either r, rx, or wx.  See the documentation for\n\t\tbinutils/ld for more details of this field\nLD.NAME\t\tThe name of this peripheral, as it appears in the linker script\n\nPIC.BUS\t\tThe name of a parameter to hold all of the interrupt wires\nPIC.MAX\t\tThe maximum number of interrutps this one can have\n\nINT.NAME.WIRE\tSpecifies that an interrupt with C #define name NAME is\n\t\tconnected to the internal wire with its name given by this key\nINT.NAME.PIC\tIdentifies which PIC this wire is connected to.  Any particular\n\t\tinterrupt may be assigned to multipl PICs.  If so, these\n\t\tare listed on this line and separated by white space\nINT.NAME.ID\tIdentifies which interrupt wire this device it connected to\n\nOUT.FILE\tCreates an output file by this name\nOUT.DATA\tPlaces this information within the data file\n\nRTL.MAKE.GROUP\tA make variable name which will contain the file list for this\n\t\tcomponent\nRTL.MAKE.FILES\tThe files composing this component\nRTL.MAKE.SUBD\tThe location of the Verilog files for this component\n\nSIM.DEFINES\t#define's follow any #includes.  You can place those here.\nSIM.DEFNS\tAny variables necessary in the Verilog simulation class can\n\t\tbe defined within this tag.\nSIM.INCLUDE\tPlace any #includes here.  #includes will be included before\n\t\tanything else\nSIM.INIT\tIf variables need to be initialized when the verilog simulation\n\t\tobject is initialized, place that initialization code within\n\t\tthis tag\nSIM.CLRRESET\tCLRRESET code goes in the same block as the reset method, but\n\t\tgets called after the reset tick.\nSIM.CLOCK\tSpecifies the clock that is used for the SIM.TICK method.  Only\n\t\tone clock is allowed.  If you need another, make another\n\t\tcomponent using the other clock.\nSIM.DBGCONDITION\tIf you might need to debug your component, you can\n\t\tput a debug condition here.  The condition code should set\n\t\tthe bool \"writeout\" to true, or leave it as it is.\nSIM.DEBUG\tIf you are doing debug by printf, place any of your printf\n\t\tdebug lines in this tag\nSIM.LOAD\tIf your component is a memory that might need to be loaded\n\t\twhen your program is loaded into the simulation, you'll need\n\t\tto define this component.  Your code will be passed a\n\t\t\"start\" offset into your address region, a buffer pointer, buf,\n\t\tan \"offset\" into that buffer, and a length (wlen) to copy\n\t\tfrom the buffer into your memory area.\n\nSIM.METHODS\tIf your code requires the definition of methods to be used\n\t\twithin the Verilator simulator class, place those definitions\n\t\there.\nSIM.SETRESET\tIf your component has specific simulation actions that need\n\t\tto take place when the reset pin is set high, place that code\n\t\tin this block.\nSIM.TICK\tIf you want your simulation software to be called as part of\n\t\ta simulation tick, place that code within this tag\n\nCLOCK.NAME\tA list of the clocks used by this component\nCLOCK.WIRE\tA list of the clock names used by this component.  These\n\t\tnames should already be defined in either the main I/O ports\n\t\tlist, or the main definitions.  If no wire is given for a clock,\n\t\tthe clock's name with a i_ prepended to the beginning is\n\t\tused instead.  For this reason, the CLOCK.WIRE field may not\n\t\tbe necessary for your application.\nCLOCK.FREQUENCY\tA list of frequencies in Hz corresponding to each of the clocks\n\t\tlisted in the CLOCK.NAME tag\nCLOCK.CLASS\tA list containing the names of clock support classes used for\n\t\tthese clocks.  If no class is given, TBCLOCK is assumed as a\n\t\tdefault.  The clock class must have a time_to_edge() function,\n\t\tan advance(int ps) function, and rising_edge() and\n\t\tfalling_edge() indicators.  Likewise, an init(ps) function\n\t\twill be called to define the period of the clock.\nCLOCK.RESET\tOptionally contains the name of a reset wire, synchronous to\n\t\tthe given clock.\n\nSLAVE.TYPE\tIndicates the type of peripheral\nSLAVE.BUS\tIndicates the name of the bus used by this slave\nSLAVE.BUS.NAME\tAn alternate form of entering a SLAVE.BUS.  This version\n\t\tallows you to specify other parameters of the SLAVE.BUS at the\n\t\tsame time.\nSLAVE.ORDER\tSlaves are naturally ordered from fewest addresses to largest.\n\t\tYou can use the SLAVE.ORDER to impose a particular order on\n\t\tbus slaves going through address assignment.\n\n\t\tThis is not the same as creating constant addressing.  Constant\n\t\taddresses are not (yet) supported by AutoFPGA.\n\nSLAVE.PREFIX\tAutoFPGA will assign a bus prefix to every slave.  Typically\n\t\tthis will be the slave's name followed by the name of the bus\n\t\t(or vice versa).  You can use the SLAVE.PREFIX key to override\n\t\tthis, or otherwise to know what the value has been set to.\n\t\tBus connections will be made to wires having names of the form,\n\t\t@$(SLAVE.PREFIX)_buswire.\n\n(SLAVE.OPTIONS)\t(When implemented) will indicate if a slave can be accessed as\n\t\teither read-only (RO) or write-only (WO).\n\nSLAVE.PORTLIST\tA helper string that you can use (or not) as you prefer.  This\n\t\tstring is created by the bus logic generator, and contains\n\t\tall of the wires you will need to connect to the bus.\n\nSLAVE.ANSIPORTLIST\tSame as SLAVE.PORTLIST, but assumes ANSI naming.\n\nMASTER.BUS\tIndicates that this component acts as a bus master, and\n\t\tidentifies (names) the bus it is a master of\nMASTER.TYPE\tOne of CPU, HOST, BUS, SUBBUS, ARBITER, or XCLOCK.\n\tCPU\twill cause board.ld to be created.  Depends upon RESET_ADDRESS\n\t\tbeing defined.\n\tDMA\tHas a control SLAVE port, and an unrelated MASTER port--one\n\t\tthat cannot be accessed through the slave\n\tHOST\tControls the bus from an external interface.\n\n\tBUS, SUBBUS,\n\tARBITER,\n\tXCLOCK\tThese define a series of bridges, whereby the master of one\n\t\tbus can control another bus.  All of these therefore need to\n\t\thave both a master and a slave bus.  Requests come in on the\n\t\tslave bus, go out on the master, get returns to the master,\n\t\tget sent back out on as returns on the slave bus.\n\n\t\tMany bus masters of type ARBITER can master the same bus.\n\t\tIn this way, slaves of one bus can also be ARBITER masters\n\t\tof another.  Further, some busses may have multiple masters,\n\t\tif all of those masters are of type ARBITER.\n\n\tSCRIPT\tDoesn't connect to the bus at all, but identifies to the linker\n\t\tscript generator the bus-master perspective to write the linker\n\t\tscript from.\n\nMASTER.OPTIONS\tA list of options used to describe this master.  Possible\n\t\toptions include: RO (read only) and WO (write only) currently.\n\nMASTER.PORTLIST\tAnalogous to SLAVE.PORTLIST, expands into a string describing\n\t\tall of the bus connections to be made to a given slave.\n\nMASTER.ANSIPORTLIST\tThis is the same as MASTER.PORTLIST, save using ANSI\n\t\tdeclarations for the bus port.  Again, this is an optional\n\t\tstring, generated by the bus compositor, that you may use\n\t\t(or not) at your desire.\n\nBUS.NAME\twb - master wishbone bus, dbg the debug port (wbu),\n\t\tzip - the ZipCPU bus master\n\t\tsdram - the MIG generated bus master\nBUS.PREFIX\t$(BUS.NAME)_\nBUS.TYPE\tOne of WB, (b4 assumed), WB/B4, WB/B3, WB/C(lassic), or AXI\n\nBUS.WIDTH\t32 (common), could also be 8, 16, 64, 128, 256, etc.\n\nBUS.AWID\tWidth of the address bus, also known as the number of\n\t\taddress lines used to address items on this bus.  The bus\n\t\tcan address (2^BUS.AWID)*(BUS.WIDTH/8) bytes of memory.\n\nBUS.NULLSZ\tThe number of addresses consumed by the null pointer address\n\nBUS.CLOCK\tThe name of a previously defined clock from which this bus\n\t\truns on\n\nBUS.RESET\tThe name of a reset wire associated with this bus.\n\nBUS.(OPTIONS)\n  BUS.OPT_LOWPOWER\tWhen set, any unused bus wires will be set to zero.\n\t\tSince bus wires can potentially have high fan out, this wire\n\t\thelps to keep all those wires from toggling if they don't need\n\t\tto.  If this isn't set, the crossbar's will be tuned for lowest\n\t\tlogic, which isn't necessarily lowest power..\n  BUS.OPT_LINGER\tUsed by the AXI-lite master to indicate the number of\n\t\tidle clock cycles to wait before releasing the bus.  This will\n\t\tpotentially speed up a given masters access to the same slave\n\t\tover and over again, while slowing down accesses to other\n\t\tslaves.\n  BUS.OPT_LGMAXBURST\tThe number of bits necessary to count the maximum number\n\t\tof outstanding transactions at any given instant in time.\n\n  BUS.OPT_TIMEOUT\tUsed by the WB crossbar to indicate a maximum amount\n\t\tof time to wait for a given slave.  Set this to zero to ignore\n\t\tthe timeout, otherwise it defaults to the value in wbxbar.v.\n\n  BUS.OPT_STARVATION_TIMEOUT\t(Currently ignored, eventually to be used by\n\t\tthe Wishbone crossbar to indicate that the OPT_TIMEOUT is to\n\t\tbe applied to starvation, where the slave is valid and active\n\t\tbut responding to a different master, as well as slave timeouts)\n  BUS.OPT_DBLBUFFER\tUsed by the wishbone crossbar, wbxbar\n\nDEFAULT.BUS\tThe name of the default bus, which we spend most of our time on.\n\t\tThis bus gets the null device, for example\n\nREGISTER.BUS\tThe name of the bus global register addresses are calculated\n\t\tfrom\n\nREGISTER.BUS.NAME\tAn alternative form of REGISTER.BUS\n\nCACHABLE.FILE\tCreates a Verilog module of this name containing a\n\t\tcombinatorial check of whether a given address beneath it is\n\t\ta cachable address (i.e., is it a memory or other type of\n\t\tperipheral).  Walks the address tree below the containing\n\t\tmaster peripheral to find memories that may be some number\n\t\tof arbiters removed from the current file.\n\n.... GOALS ...\nBuild S/W to collect all busses together\nAllow someone to inherit from the arbiters in such a manner that they can\nconnect busses together simply\nRedo the address assignments, so as to be on a bus-by-bus basis\nSet the peripherals up in such a way that, if you have to walk from one bus to\n  the next, you can still figure out what the adderss of the peripheral is--even\n  if it is a couple busses deep\n"
  },
  {
    "path": "doc/ioports.md",
    "content": "## Getting Access to External I/O Ports\n\nAccessing external I/O has a couple parts.  First, you'll want to declare your\nneed for accessing external I/O in the first place.  For example, a serial\nport (uart) might have an input and an output port.  Since AutoFPGA (currently)\nuses the older Verilog portlist syntax, defining these ports comes in two\nparts.  First, you'd define the `MAIN.PORTLIST` tag, listing all of the ports\nin your design, and then the `MAIN.IODECL` tag declaring the various ports.\nFurther, to avoid name collision, I typically use the `@$(PREFIX)` tag as\npart of any component I/O names--it's convenient, although not technically\nrequired.\n\n```text\n@PREFIX=uart\n@NADDR=4\n@SLAVE.BUS=wb\n@SLAVE.TYPE=DOUBLE\n@MAIN.PORTLIST=\n\t// Serial port wires\n\ti_@$(PREFIX)_uart, o_@$(PREFIX)_uart\n@MAIN.IODECL=\n\tinput\twire\ti_@$(PREFIX)_uart;\n\toutput\twire\to_@$(PREFIX)_uart;\n@MAIN.INSERT=\n\twbuart @$(PREFIX)i (i_clk,\n\t\t@$(SLAVE.PORTLIST),\n\t\ti_@$(PREFIX)_uart, o_@$(PREFIX)_uart);\n```\n\nBy default, these ports will automatically be promoted to the top level.\nTo keep from promoting them to the top level, or to adjust their names and\ndefinitions at the top level, simply override the `TOP.PORTLIST` and/or\n`TOP.IODECL` tags.\n"
  },
  {
    "path": "doc/single.md",
    "content": "# Single Slave Definitions\n\nAutoFPGA defines two special classes of slaves, `SINGLE` and `DOUBLE`.  These\nclasses are used to help AutoFPGA coalesce bus logic together, while\nsimplifying your design.\n\nThe `SINGLE` slave describes a slave with only one register, which register\ncan be accessed on every cycle without stalling.  It is the easiest slave\nto create.\n\n```text\n@PREFIX=wbexample\n@SLAVE.NADDR=1\n@SLAVE.BUS=wbbus\n@SLAVE.TYPE=SINGLE\n@MAIN.INSERT=\n\tassign @$(SLAVE.PREFIX)_idata = value;\n```\n\nThis will create your slave and connect it to the bus named `wb`.  Any\nattempt to read from your slave will return the value `value`, having a\nwidth specified by the `wb` bus width.  (You'll still need to define\n`value` yourself somewhere within your design.)\n\nBuilding this same example for an AXI or AXI-Lite bus is almost the\nsame, only that you also need to define values for `@$(SLAVE.PREFIX)_bresp`\nand `@$(SLAVE.PREFIX)_rresp`.\n\n```text\n@PREFIX=axilexample\n@SLAVE.NADDR=1\n@SLAVE.BUS=axilbus\n@SLAVE.TYPE=SINGLE\n@MAIN.INSERT=\n\tassign @$(SLAVE.PREFIX)_bresp = 2'b00;\n\tassign @$(SLAVE.PREFIX)_rresp = 2'b00;\n\tassign @$(SLAVE.PREFIX)_rdata = value;\n```\n\nThe neat thing about `SINGLE` slaves, is that the logic can be created\nhowever within your design.  For example, you might decide to declare a\ncounter that could then be read from your design.\n\n```text\n@SLAVE.BUS=wbbus\n@MAIN.DEFNS=\n\treg\t[31:0]\tr_counter;\n@MAIN.INSERT=\n\tinitial\tr_counter = 0;\n\talways @(posedge i_clk)\n\t\tr_counter <= r_counter + 1;\n\n\tassign\t@$(SLAVE.PREFIX)_idata = r_counter;\n```\n\nIndeed, I often create a startup counter that I use within my designs--one\nthat just counts the number of clock ticks since startup, but that\nsaturates the top bit.  I can then use this to time things in startup sequences,\nor for relative (30-bit) timing ever afterwards.\n\n```text\n@SLAVE.BUS=axilbus\n@MAIN.DEFNS=\n\treg\t[31:0]\tr_pwrcount;\n@MAIN.INSERT=\n\tinitial\tr_pwrcount = 0;\n\talways @(posedge i_clk)\n\tif (r_pwrcount[31])\n\t\tr_pwrcount[30:0] <= r_pwrcount[30:0] + 1;\n\telse\n\t\tr_pwrcount <= r_pwrcount + 1;\n\n\tassign\t@$(SLAVE.PREFIX)_idata = r_pwrcount;\n```\n\nWe could also give our counter a value as well.  How you might do this\nis somewhat dependent upon the bus protocol in question.  For example,\nwhen using Wishbone, this would look like:\n\n```text\n@SLAVE.BUS=wbbus\n@MAIN.DEFNS=\n\treg\t[31:0]\tr_pwrcount;\n@MAIN.INSERT=\n\tinitial\tr_pwrcount = 0;\n\talways @(posedge i_clk)\n\tif (@$(SLAVE.PREFIX)_stb && @$(SLAVE.PREFIX)_we)\n\t\tr_pwrcount <= @$(SLAVE.PREFIX)_data;\n\telse if (r_pwrcount[31])\n\t\tr_pwrcount[30:0] <= r_pwrcount[30:0] + 1;\n\telse\n\t\tr_pwrcount <= r_pwrcount + 1;\n\n\tassign\t@$(SLAVE.PREFIX)_idata = r_pwrcount;\n```\n\nWhen creating an AXI or AXI-Lite slave, AutoFPGA will use one of the bus\nsimplifiers found in the [WB2AXIP](https://github.com/ZipCPU/wb2axip)\nrepository, either\n[AXISINGLE](https://github.com/ZipCPU/wb2axip/blob/master/rtl/axisingle.v) or\n[AXILSINGLE](https://github.com/ZipCPU/wb2axip/blob/master/rtl/axilsingle.v)\nThese drivers will guarantee for you that the respective `xREADY` lines remain\nhigh.  All you therefore need to do is to check `WVALID` to know when to adjust\nyour counter.\n\n```text\n@SLAVE.BUS=axilbus\n@MAIN.DEFNS=\n\treg\t[31:0]\tr_pwrcount;\n@MAIN.INSERT=\n\tinitial\tr_pwrcount = 0;\n\talways @(posedge i_clk)\n\tif (@$(SLAVE.PREFIX)_awvalid)\n\t\tr_pwrcount <= @$(SLAVE.PREFIX)_data;\n\telse if (r_pwrcount[31])\n\t\tr_pwrcount[30:0] <= r_pwrcount[30:0] + 1;\n\telse\n\t\tr_pwrcount <= r_pwrcount + 1;\n\n\tassign\t@$(SLAVE.PREFIX)_rdata = r_pwrcount;\n```\n\nIdeally, the `@PREFIX` tag should be unique to your slave.  This makes it\npossible to name wires uniquely between bus components, although doing\nso isn't required.\n\n```text\n@PREFIX=renamed\n@MAIN.DEFNS=\n\treg\t[31:0]\tr_@$(PREFIX);\n@MAIN.INSERT=\n\t// Follows as before from above, but now with a new name\n```\n\nRemember, the `@MAIN.INSERT` tag will be copied directly into your `main.v``\nfile.  Therefore, you can place anything into it you wish.  For example, you\nmight wish to reference a submodule of your own instead of placing your\nlogic within the global scope of `main.v`.  To make this easier, AutoFPGA\nwill define a `@SLAVE.PORTLIST` tag that expands into a list of all of\nyour design ports--just to make connections easier.\n\n```text\n@MAIN.INSERT=\n\tmymodule @$(PREFIX)i (i_clk\n\t\t@$(SLAVE.PORTLIST));\n```\n\nI like naming my modules as `@$(PREFIX)i` to avoid name contention, but this\nis only a convention--it's not required at all.\n\nThe `@SLAVE.PORTLIST` tag doesn't include either clock or reset.  You can\neither include these as I did above, or reference them from other names\nwithin your design--such as `@SLAVE.BUS.CLOCK.WIRE`.\n\n```text\n@MAIN.INSERT=\n\tmymodule @$(PREFIX)i (@$(SLAVE.BUS.CLOCK.WIRE),\n\t\t@$(SLAVE.PORTLIST));\n```\n\nSince this can get tedious, and since my designs rarely use more than one\nclock for the bus, I often just use `i_clk`.\n\n"
  },
  {
    "path": "doc/slaves.md",
    "content": "## Creating a Generic Slave\n\nNow that you know how to create `SINGLE` and `DOUBLE` slaves, generic\nslaves really aren't that much more difficult.  These are typically of type\n`OTHER`, and just reference your design.\n\n```text\n@PREFIX=wbslave\n@SLAVE.BUS=wb\n@SLAVE.TYPE=OTHER\n@SLAVE.NADDR=32\n@MAIN.INSERT=\n\tbusslave @$(PREFIX)i (i_clk, i_reset,\n\t\t@$(SLAVE.PORTLIST));\n```\n\nUnlike `SINGLE` or `DOUBLE` slaves which are not allowed to stall the bus,\n`OTHER` slaves can exploit the full bus protocol.\n"
  },
  {
    "path": "doc/src/gpl-3.0.tex",
    "content": "\\documentclass[11pt]{article}\n\n\\title{GNU GENERAL PUBLIC LICENSE}\n\\date{Version 3, 29 June 2007}\n\n\\begin{document}\n\\maketitle\n\n\\begin{center}\n{\\parindent 0in\n\nCopyright \\copyright\\  2007 Free Software Foundation, Inc. \\texttt{http://fsf.org/}\n\n\\bigskip\nEveryone is permitted to copy and distribute verbatim copies of this\n\nlicense document, but changing it is not allowed.}\n\n\\end{center}\n\n\\renewcommand{\\abstractname}{Preamble}\n\\begin{abstract}\nThe GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\nThe licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\nWhen we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\nTo protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\nFor example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\nDevelopers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\nFor the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\nSome devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\nFinally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\nThe precise terms and conditions for copying, distribution and\nmodification follow.\n\\end{abstract}\n\n\\begin{center}\n{\\Large \\sc Terms and Conditions}\n\\end{center}\n\n\n\\begin{enumerate}\n\n\\addtocounter{enumi}{-1}\n\n\\item Definitions.\n\n``This License'' refers to version 3 of the GNU General Public License.\n\n``Copyright'' also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n``The Program'' refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as ``you''.  ``Licensees'' and\n``recipients'' may be individuals or organizations.\n\nTo ``modify'' a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a ``modified version'' of the\nearlier work or a work ``based on'' the earlier work.\n\nA ``covered work'' means either the unmodified Program or a work based\non the Program.\n\nTo ``propagate'' a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\nTo ``convey'' a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\nAn interactive user interface displays ``Appropriate Legal Notices''\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n\\item Source Code.\n\nThe ``source code'' for a work means the preferred form of the work\nfor making modifications to it.  ``Object code'' means any non-source\nform of a work.\n\nA ``Standard Interface'' means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\nThe ``System Libraries'' of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n``Major Component'', in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\nThe ``Corresponding Source'' for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\nThe Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\nThe Corresponding Source for a work in source code form is that\nsame work.\n\n\\item Basic Permissions.\n\nAll rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\nYou may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\nConveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n\\item Protecting Users' Legal Rights From Anti-Circumvention Law.\n\nNo covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\nWhen you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n\\item Conveying Verbatim Copies.\n\nYou may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\nYou may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n\\item Conveying Modified Source Versions.\n\nYou may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n  \\begin{enumerate}\n  \\item The work must carry prominent notices stating that you modified\n  it, and giving a relevant date.\n\n  \\item The work must carry prominent notices stating that it is\n  released under this License and any conditions added under section\n  7.  This requirement modifies the requirement in section 4 to\n  ``keep intact all notices''.\n\n  \\item You must license the entire work, as a whole, under this\n  License to anyone who comes into possession of a copy.  This\n  License will therefore apply, along with any applicable section 7\n  additional terms, to the whole of the work, and all its parts,\n  regardless of how they are packaged.  This License gives no\n  permission to license the work in any other way, but it does not\n  invalidate such permission if you have separately received it.\n\n  \\item If the work has interactive user interfaces, each must display\n  Appropriate Legal Notices; however, if the Program has interactive\n  interfaces that do not display Appropriate Legal Notices, your\n  work need not make them do so.\n\\end{enumerate}\nA compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n``aggregate'' if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n\\item Conveying Non-Source Forms.\n\nYou may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n  \\begin{enumerate}\n  \\item Convey the object code in, or embodied in, a physical product\n  (including a physical distribution medium), accompanied by the\n  Corresponding Source fixed on a durable physical medium\n  customarily used for software interchange.\n\n  \\item Convey the object code in, or embodied in, a physical product\n  (including a physical distribution medium), accompanied by a\n  written offer, valid for at least three years and valid for as\n  long as you offer spare parts or customer support for that product\n  model, to give anyone who possesses the object code either (1) a\n  copy of the Corresponding Source for all the software in the\n  product that is covered by this License, on a durable physical\n  medium customarily used for software interchange, for a price no\n  more than your reasonable cost of physically performing this\n  conveying of source, or (2) access to copy the\n  Corresponding Source from a network server at no charge.\n\n  \\item Convey individual copies of the object code with a copy of the\n  written offer to provide the Corresponding Source.  This\n  alternative is allowed only occasionally and noncommercially, and\n  only if you received the object code with such an offer, in accord\n  with subsection 6b.\n\n  \\item Convey the object code by offering access from a designated\n  place (gratis or for a charge), and offer equivalent access to the\n  Corresponding Source in the same way through the same place at no\n  further charge.  You need not require recipients to copy the\n  Corresponding Source along with the object code.  If the place to\n  copy the object code is a network server, the Corresponding Source\n  may be on a different server (operated by you or a third party)\n  that supports equivalent copying facilities, provided you maintain\n  clear directions next to the object code saying where to find the\n  Corresponding Source.  Regardless of what server hosts the\n  Corresponding Source, you remain obligated to ensure that it is\n  available for as long as needed to satisfy these requirements.\n\n  \\item Convey the object code using peer-to-peer transmission, provided\n  you inform other peers where the object code and Corresponding\n  Source of the work are being offered to the general public at no\n  charge under subsection 6d.\n  \\end{enumerate}\n\nA separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\nA ``User Product'' is either (1) a ``consumer product'', which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, ``normally used'' refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n``Installation Information'' for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\nIf you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\nThe requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\nCorresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n\\item Additional Terms.\n\n``Additional permissions'' are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\nWhen you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\nNotwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n  \\begin{enumerate}\n  \\item Disclaiming warranty or limiting liability differently from the\n  terms of sections 15 and 16 of this License; or\n\n  \\item Requiring preservation of specified reasonable legal notices or\n  author attributions in that material or in the Appropriate Legal\n  Notices displayed by works containing it; or\n\n  \\item Prohibiting misrepresentation of the origin of that material, or\n  requiring that modified versions of such material be marked in\n  reasonable ways as different from the original version; or\n\n  \\item Limiting the use for publicity purposes of names of licensors or\n  authors of the material; or\n\n  \\item Declining to grant rights under trademark law for use of some\n  trade names, trademarks, or service marks; or\n\n  \\item Requiring indemnification of licensors and authors of that\n  material by anyone who conveys the material (or modified versions of\n  it) with contractual assumptions of liability to the recipient, for\n  any liability that these contractual assumptions directly impose on\n  those licensors and authors.\n  \\end{enumerate}\n\nAll other non-permissive additional terms are considered ``further\nrestrictions'' within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\nIf you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\nAdditional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n\\item Termination.\n\nYou may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\nHowever, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\nMoreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\nTermination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n\\item Acceptance Not Required for Having Copies.\n\nYou are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n\\item Automatic Licensing of Downstream Recipients.\n\nEach time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\nAn ``entity transaction'' is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\nYou may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n\\item Patents.\n\nA ``contributor'' is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's ``contributor version''.\n\nA contributor's ``essential patent claims'' are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, ``control'' includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\nEach contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\nIn the following three paragraphs, a ``patent license'' is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To ``grant'' such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\nIf you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  ``Knowingly relying'' means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\nIf, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\nA patent license is ``discriminatory'' if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\nNothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n\\item No Surrender of Others' Freedom.\n\nIf conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n\\item Use with the GNU Affero General Public License.\n\nNotwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n\\item Revised Versions of this License.\n\nThe Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License ``or any later version'' applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\nIf the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\nLater license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n\\item Disclaimer of Warranty.\n\n\\begin{sloppypar}\n THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\n APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE\n COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS''\n WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,\n INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE\n RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.\n SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL\n NECESSARY SERVICING, REPAIR OR CORRECTION.\n\\end{sloppypar}\n\n\\item Limitation of Liability.\n\n IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\n WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES\n AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR\n DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL\n DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM\n (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED\n INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE\n OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH\n HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\n DAMAGES.\n\n\\item Interpretation of Sections 15 and 16.\n\nIf the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n\\begin{center}\n{\\Large\\sc End of Terms and Conditions}\n\n\\bigskip\nHow to Apply These Terms to Your New Programs\n\\end{center}\n\nIf you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\nTo do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe ``copyright'' line and a pointer to where the full notice is found.\n\n{\\footnotesize\n\\begin{verbatim}\n<one line to give the program's name and a brief idea of what it does.>\n\nCopyright (C) <textyear>  <name of author>\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program.  If not, see <http://www.gnu.org/licenses/>.\n\\end{verbatim}\n}\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n{\\footnotesize\n\\begin{verbatim}\n<program>  Copyright (C) <year>  <name of author>\n\nThis program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\nThis is free software, and you are welcome to redistribute it\nunder certain conditions; type `show c' for details.\n\\end{verbatim}\n}\n\nThe hypothetical commands {\\tt show w} and {\\tt show c} should show\nthe appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an ``about box''.\n\nYou should also get your employer (if you work as a programmer) or\nschool, if any, to sign a ``copyright disclaimer'' for the program, if\nnecessary.  For more information on this, and how to apply and follow\nthe GNU GPL, see \\texttt{http://www.gnu.org/licenses/}.\n\nThe GNU General Public License does not permit incorporating your\nprogram into proprietary programs.  If your program is a subroutine\nlibrary, you may consider it more useful to permit linking proprietary\napplications with the library.  If this is what you want to do, use\nthe GNU Lesser General Public License instead of this License.  But\nfirst, please read \\texttt{http://www.gnu.org/philosophy/why-not-lgpl.html}.\n\n\\end{enumerate}\n\n\\end{document}\n"
  },
  {
    "path": "sw/.gitignore",
    "content": "autofpga\nrunme.sh\nexpr.tab.h\nexpr.tab.cpp\nlex.yy.h\nlex.yy.cpp\n*tmp.txt\ntmp*.txt\ndemo-out\n"
  },
  {
    "path": "sw/Makefile",
    "content": "################################################################################\n##\n## Filename:\tsw/Makefile\n##\n## Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n## {{{\n## Purpose:\t\n##\n## Creator:\tDan Gisselquist, Ph.D.\n##\t\tGisselquist Technology, LLC\n##\n################################################################################\n## }}}\n## Copyright (C) 2017-2024, Gisselquist Technology, LLC\n## {{{\n## This program is free software (firmware): you can redistribute it and/or\n## modify it under the terms of the GNU General Public License as published\n## by the Free Software Foundation, either version 3 of the License, or (at\n## your option) any later version.\n##\n## This program is distributed in the hope that it will be useful, but WITHOUT\n## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n## for more details.\n##\n## You should have received a copy of the GNU General Public License along\n## with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n## target there if the PDF file isn't present.)  If not, see\n## <http://www.gnu.org/licenses/> for a copy.\n## }}}\n## License:\tGPL, v3, as defined and found on www.gnu.org,\n## {{{\n##\t\thttp://www.gnu.org/licenses/gpl.html\n##\n##\n################################################################################\n##\n## }}}\nall:\nPROGRAMS := autofpga demo\nOBJDIR:= obj-pc\nYYMMDD:= `date +%Y%m%d`\nCXX:= g++\nSED:= sed\nCFLAGS:= -std=c++11 -g -Wall -I bus/\nSOURCES := autofpga.cpp parser.cpp kveval.cpp keys.cpp mapdhash.cpp ast.cpp \\\n\tlegalnotice.cpp ifdefs.cpp bldregdefs.cpp expr.tab.cpp lex.yy.cpp   \\\n\tbitlib.cpp bldtestb.cpp bldsim.cpp predicates.cpp\t\t    \\\n\tclockinfo.cpp subbus.cpp globals.cpp gather.cpp\t\t\t    \\\n\tbldboardld.cpp bldrtlmake.cpp msgs.cpp bldcachable.cpp\t\t    \\\n\tbusinfo.cpp plist.cpp mlist.cpp genbus.cpp $(wildcard bus/*.cpp)\n\nPOSSHDRS:= $(subst .c,.h,$(subst .cpp,.h,$(SOURCES)))\nHEADERS := $(foreach header,$(POSSHDRS),$(wildcard $(header)))\nOBJECTS := $(addprefix $(OBJDIR)/,$(subst bus/,,$(subst .c,.o,$(subst .cpp,.o,$(SOURCES)))))\n\nall: $(PROGRAMS)\n\n$(OBJDIR)/autofpga.o: autofpga.cpp\n\t$(mk-objdir)\n\t$(CXX) -DBUILDDATE=0x$(YYMMDD) $(CFLAGS) -c $< -o $@\n\n$(OBJDIR)/lex.yy.o: lex.yy.cpp\n\t$(mk-objdir)\n\t$(CXX) $(CFLAGS) -Wno-sign-compare -Wno-unused-function -c $< -o $@\n\n$(OBJDIR)/%.o: %.cpp\n\t$(mk-objdir)\n\t$(CXX) $(CFLAGS) -c $< -o $@\n\n$(OBJDIR)/%.o: bus/%.cpp\n\t$(mk-objdir)\n\t$(CXX) $(CFLAGS) -I. -c $< -o $@\n\n$(OBJDIR)/%.o: %.c\n\t$(mk-objdir)\n\t$(CXX) $(CFLAGS) -c $< -o $@\n\nexpr.tab.h: expr.ypp\n\tbison --defines=expr.tab.h expr.ypp\nexpr.tab.cpp: expr.tab.h\n$(OBJDIR)/expr.tab.o: lex.yy.h\n\nlex.yy.cpp lex.yy.h: expr.l expr.tab.h\n\tflex --header-file=lex.yy.h -o lex.yy.cpp expr.l\n\nautofpga: $(OBJECTS)\n\techo $(OBJECTS)\n\t$(CXX) $(CFLAGS) $(OBJECTS) -o $@\n\nVDATA := allclocks.txt bkram.txt buserr.txt clkcheck.txt crossbus.txt\t\\\n\tddr3.txt edidslvscope.txt edid.txt exconsole.txt flashcfg.txt\t\\\n\tflash.txt global.txt gpio.txt gps.txt hdmi.txt i2ccpu.txt\t\\\n\ti2cdma.txt i2saudio.txt icape.txt meganet.txt mdio.txt pic.txt\t\\\n\tpwrcount.txt rtcdate.txt rtcgps.txt spio.txt sdio.txt\t\t\\\n\tvadj33.txt version.txt wboledbw.txt wbpmic.txt wbuarbiter.txt\t\\\n\twbubus.txt zipcpu.txt zipmaster.txt\n\n.PHONY: demo\ndemo: runme.sh\n\tbash runme.sh\n\n.PHONY: runme.sh\t# Force a rebuild of this file every time\nrunme.sh: autofpga $(addprefix ../auto-data/,$(VDATA))\n\t@echo \"#!/bin/bash\" > $@\n\t@echo >> $@\n\t@echo >> $@\n\t@echo ./autofpga -d -o ../demo-out -I ../auto-data $(VDATA)  >> $@\n\t@echo >> $@\n\t@echo \"echo \\\"exit code \\\" \\$$?\" >> $@\n\ndefine\tmk-objdir\n\t@bash -c \"if [ ! -e $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi\"\nendef\n\ndefine\tbuild-depends\n\t@echo \"Building dependency file\"\n\t$(CXX) $(CFLAGS) -MM $(SOURCES) > $(OBJDIR)/xdep.txt\n\t$(SED) -e 's/^.*.o: /$(OBJDIR)\\/&/' < $(OBJDIR)/xdep.txt > $(OBJDIR)/depends.txt\nendef\n\n.PHONY: depends\ndepends: tags\n\t$(mk-objdir)\n\t$(build-depends)\n\ntags: $(SOURCES) $(HEADERS)\n\t@echo \"Generating tags\"\n\t@ctags $(SOURCES) $(HEADERS)\n\n.PHONY: clean\nclean:\n\trm -rf $(OBJDIR)/ $(PROGRAMS)\n\trm -rf lex.yy.cpp lex.yy.h expr.tab.cpp expr.tab.h expr.output\n\n-include $(OBJDIR)/depends.txt\n"
  },
  {
    "path": "sw/ast.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/ast.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\t\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"ast.h\"\n#include \"keys.h\"\n\nbool\tAST_BRANCH::isdefined(void) {\n\treturn ((m_left)&&(m_right)&&(m_left->isdefined())\n\t\t\t&&(m_right->isdefined()));\n}\n\nlong AST_BRANCH::eval(void) {\n\tlong\tlft = m_left->eval(), rht = m_right->eval();\n\tswitch(m_op) {\n\t\tcase '+':\treturn lft + rht;\tbreak;\n\t\tcase '-':\treturn lft - rht;\tbreak;\n\t\tcase '*':\treturn lft * rht;\tbreak;\n\t\tcase '/':\treturn lft / rht;\tbreak;\n\t\tcase '%':\treturn lft % rht;\tbreak;\n\t\t//\n\t\tcase 'u':\treturn lft << rht;\tbreak;\n\t\tcase 'd':\treturn lft >> rht;\tbreak;\n\t\t//\n\t\tcase '|':\treturn lft | rht;\tbreak;\n\t\tcase '&':\treturn lft & rht;\tbreak;\n\t\tcase '^':\treturn lft ^ rht;\tbreak;\n\t\t// ~ ??\n\t\t//\n\t\tcase 'o':\treturn ((lft)||(rht))?1:0;\tbreak;\n\t\tcase 'a':\treturn ((lft)&&(rht))?1:0;\tbreak;\n\t\tcase 'e':\treturn ((lft)==(rht))?1:0;\tbreak;\n\t\t// ! ??\n\t\tcase 'N':\treturn (lft != rht)? 1:0;\tbreak;\n\t\tcase 'L':\treturn (lft <= rht)? 1:0;\tbreak;\n\t\tcase 'G':\treturn (lft >= rht)? 1:0;\tbreak;\n\t\tcase '<':\treturn (lft <  rht)? 1:0;\tbreak;\n\t\tcase '>':\treturn (lft >  rht)? 1:0;\tbreak;\n\t\t//\n\t\t//\n\t\tdefault:\tfprintf(stderr, \"ERR: AST Unknown operation, %c\", m_op);\n\t\t\treturn lft;\n\t}\n}\nbool\tAST_BRANCH::define(MAPSTACK &stack, MAPDHASH &here) {\n\tbool\tv;\n\tv =  m_left->define(stack, here);\n\tv = m_right->define(stack, here) || v;\n\treturn v;\n}\nvoid\tAST_BRANCH::dump(FILE *fp, int offset) {\n\tfprintf(fp, \"%*s%c\\n\", offset, \"\", m_op);\n\tm_left->dump(fp, offset+2);\n\tm_right->dump(fp, offset+2);\n}\n\nAST\t*AST_BRANCH::copy(void) {\n\treturn new AST_BRANCH(m_op, ::copy(m_left), ::copy(m_right));\n}\n\nbool\tAST_SINGLEOP::isdefined(void) {\n\t\treturn (m_val->isdefined()); }\nlong\tAST_SINGLEOP::eval(void) {\n\tif (m_op == '~')\n\t\treturn ~m_val->eval();\n\telse\n\t\treturn (m_val->eval())?0:1;\n}\nbool\tAST_SINGLEOP::define(MAPSTACK &stack, MAPDHASH &here) {\n\treturn m_val->define(stack, here);\n}\nvoid\tAST_SINGLEOP::dump(FILE *fp, int offset) {\n\tfprintf(fp, \"%*s%c\\n\", offset, \"\", m_op);\n\tm_val->dump(fp, offset+2);\n}\n\nAST\t*AST_SINGLEOP::copy(void) {\n\treturn new AST_SINGLEOP(m_op, ::copy(m_val));\n}\n\nbool\tAST_TRIOP::isdefined(void) {\n\treturn (m_cond->isdefined())&&(m_left->isdefined())\n\t\t\t&&(m_right->isdefined());\n}\nlong\tAST_TRIOP::eval(void) {\n\treturn (m_cond->eval())\n\t\t? m_left->eval() : m_right->eval();\n}\nbool\tAST_TRIOP::define(MAPSTACK &stack, MAPDHASH &here) {\n\tbool\tv = false;\n\tv =  (m_cond->define(stack, here)) || v;\n\tv =  (m_left->define(stack, here)) || v;\n\tv = (m_right->define(stack, here)) || v;\n\treturn v;\n}\nvoid\tAST_TRIOP::dump(FILE *fp, int offset) {\n\tfprintf(fp, \"%*sTRIPL:\\n\", offset, \"\");\n\tm_cond->dump(fp, offset+2);\n\tm_left->dump(fp, offset+2);\n\tm_right->dump(fp, offset+2);\n}\nAST\t*AST_TRIOP::copy(void) {\n\treturn new AST_TRIOP(::copy(m_cond), ::copy(m_left), ::copy(m_right));\n}\n\n\nbool\tAST_NUMBER::isdefined(void) { return true; }\nlong\tAST_NUMBER::eval(void) { return m_val; }\nbool\tAST_NUMBER::define(MAPSTACK &stack, MAPDHASH &here) { return false; }\nvoid\tAST_NUMBER::dump(FILE *fp, int offset) {\n\tfprintf(fp, \"%*s%ld\\n\", offset, \"\", m_val);\n}\nAST\t*AST_NUMBER::copy(void) {\n\treturn new AST_NUMBER(m_val);\n}\n\n\nbool\tAST_IDENTIFIER::isdefined(void) { return m_def; }\nlong\tAST_IDENTIFIER::eval(void) { return m_v; }\nbool\tAST_IDENTIFIER::define(MAPSTACK &stack, MAPDHASH &here) {\n\tif (m_def)\n\t\treturn false; // No change\n\tif (get_named_value(stack, here, m_id, m_v)) {\n\t\t// GOT IT!!!!  We now know our value, so ... set it and\n\t\t// report that things have changed.\n\t\tm_def = true;\n\t\treturn true;\t// Things have changed!\n\t} return false;\t// Nothing changed, we still don't know our value\n}\nvoid\tAST_IDENTIFIER::dump(FILE *fp, int offset) {\n\tif (m_def)\n\t\tfprintf(fp, \"%*s%s (= %d)\\n\", offset, \"\", m_id.c_str(), m_v);\n\telse\n\t\tfprintf(fp, \"%*s%s (Undefined)\\n\", offset, \"\", m_id.c_str());\n}\nAST\t*AST_IDENTIFIER::copy(void) {\n\treturn new AST_IDENTIFIER(m_id.c_str());\n}\n"
  },
  {
    "path": "sw/ast.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/ast.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\t\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tAST_H\n#define\tAST_H\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"parser.h\"\n#include \"kveval.h\"\n\nclass AST {\npublic:\n\tvirtual ~AST(void) {}\n\tchar\tm_node_type;\n\tvirtual bool\tisdefined(void) = 0;\n\tvirtual long\teval(void) = 0;\n\tvirtual bool\tdefine(MAPSTACK &stack, MAPDHASH &comp) = 0;\n\tvirtual void\tdump(FILE *fp, int offset) = 0;\n\tvirtual\tAST\t*copy(void) = 0;\n};\n\nclass AST_BRANCH : public AST {\npublic:\n\tint\tm_op;\n\tAST\t*m_left, *m_right;\n\tAST_BRANCH(int op, AST *l, AST *r)\n\t\t: m_op(op), m_left(l), m_right(r) {\n\t\tm_node_type = 'B';}\n\t~AST_BRANCH(void) {\n\t\tif (m_left)\n\t\t\tdelete m_left;\n\t\tif (m_right)\n\t\t\tdelete m_right;\n\t}\n\n\tvirtual\tbool\tisdefined(void);\n\tvirtual\tlong\teval(void);\n\tvirtual\tbool\tdefine(MAPSTACK &stack, MAPDHASH &here);\n\tvirtual\tvoid\tdump(FILE *fp, int offset);\n\tvirtual\tAST\t*copy(void);\n};\n\nclass\tAST_SINGLEOP : public AST {\n  public:\n\tint\tm_op;\n\tAST\t*m_val;\n\tAST_SINGLEOP(int op, AST *v)\n\t\t: m_op(op), m_val(v) { m_node_type = 'S'; }\n\t~AST_SINGLEOP(void) {\tdelete m_val; }\n\n\tvirtual\tbool\tisdefined(void);\n\tvirtual\tlong\teval(void);\n\tvirtual\tbool\tdefine(MAPSTACK &stack, MAPDHASH &here);\n\tvirtual\tvoid\tdump(FILE *fp, int offset);\n\tvirtual\tAST\t*copy(void);\n};\n\nclass\tAST_TRIOP : public AST {\npublic:\n\tAST\t*m_cond, *m_left, *m_right;\n\tAST_TRIOP(AST *c, AST *l, AST *r)\n\t\t\t: m_cond(c), m_left(l), m_right(r) {\n\t\tm_node_type = 'T';\n\t}\n\t~AST_TRIOP(void) {\n\t\tdelete m_cond; delete m_left; delete m_right;\n\t}\n\n\tvirtual\tbool\tisdefined(void);\n\tvirtual\tlong\teval(void);\n\tvirtual\tbool\tdefine(MAPSTACK &stack, MAPDHASH &here);\n\tvirtual\tvoid\tdump(FILE *fp, int offset);\n\tvirtual\tAST\t*copy(void);\n};\n\nclass\tAST_NUMBER : public AST {\npublic:\n\tlong\tm_val;\n\tAST_NUMBER(long val) : m_val(val) { m_node_type = 'N'; }\n\n\tvirtual\tbool\tisdefined(void);\n\tvirtual\tlong\teval(void);\n\tvirtual\tbool\tdefine(MAPSTACK &stack, MAPDHASH &here);\n\tvirtual\tvoid\tdump(FILE *fp, int offset);\n\tvirtual\tAST\t*copy(void);\n};\n\nclass\tAST_IDENTIFIER : public AST {\npublic:\n\tSTRING\tm_id;\n\tbool\tm_def;\n\tint\tm_v;\n\tAST_IDENTIFIER(const char *id) : m_id(id) {\n\t\tm_node_type = 'I';\n\t\tm_def=false;\n\t\tm_v = 0;\n\t}\n\n\tvirtual\tbool\tisdefined(void);\n\tvirtual\tlong\teval(void);\n\tvirtual\tbool\tdefine(MAPSTACK &stack, MAPDHASH &here);\n\tvirtual\tvoid\tdump(FILE *fp, int offset);\n\tvirtual\tAST\t*copy(void);\n};\n\nextern AST\t*parse_ast(const STRING &str);\ninline\tAST *copy(AST *a) { return a->copy(); }\n\n#endif\t// AST_H\n"
  },
  {
    "path": "sw/autofpga.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/autofpga.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tThis is the main/master program for the autofpga project.  All\n//\t\tother components server this one.\n//\n//\tThe purpose of autofpga.cpp is to read a group of configuration files\n//\t(.txt currently), and to generate code from those files to connect\n//\tthe various parts and pieces within them into a design.\n//\n//\tCurrently that design is dependent upon the Wishbone B4/Pipelined\n//\tbus, but that's likely to change in the future.\n//\n//\tDesign files produced include:\n//\n//\ttoplevel.v\n//\tmain.v\n//\tregdefs.h\n//\tiscachable.h\n//\tregdefs.cpp\n//\tboard.h\n//\tboard.ld\n//\tmain_tb.cpp\n//\ttestb.h\n//\t* dev.tex\t(Not yet included)\n//\t* kernel device tree file\n//\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <string.h>\n#include <unistd.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <limits.h>\n#include <ctype.h>\n\n#include \"parser.h\"\n#include \"keys.h\"\n#include \"kveval.h\"\n#include \"legalnotice.h\"\n#include \"bldtestb.h\"\n#include \"bldboardld.h\"\n#include \"bldrtlmake.h\"\n#include \"bitlib.h\"\n#include \"plist.h\"\n#include \"bldregdefs.h\"\n#include \"ifdefs.h\"\n#include \"bldsim.h\"\n#include \"predicates.h\"\n#include \"businfo.h\"\n#include \"globals.h\"\n#include \"msgs.h\"\n#include \"bldcachable.h\"\n\n// class INFINFO\n// The ILIST, a list of interrupt lines within the design\n// {{{\n//\nclass INTINFO {\npublic:\n\tSTRINGP\t\ti_name;\n\tSTRINGP\t\ti_wire;\n\tunsigned\ti_id;\n\tMAPDHASH\t*i_hash;\n\tINTINFO(void) { i_name = NULL; i_wire = NULL; i_id = 0; }\n\tINTINFO(STRINGP nm, STRINGP wr, unsigned id)\n\t\t: i_name(nm), i_wire(wr), i_id(id) {}\n\tINTINFO(STRING &nm, STRING &wr, unsigned id) : i_id(id) {\n\t\ti_name = new STRING(nm);\n\t\ti_wire = new STRING(wr);\n\t}\n};\ntypedef\tINTINFO\tINTID, *INTP;\ntypedef\tstd::vector<INTP>\tILIST;\n// }}}\n\n// class PICINFO\n// {{{\n// The PICINFO structure, one that keeps track of all of the information used\n// by a given Programmable Interrupt Controller (PIC)\n//\n//\nclass PICINFO {\npublic:\n\tSTRINGP\t\ti_name,\t// The name of this PIC\n\t\t\t// i_bus is the name of a vector, that is ... a series\n\t\t\t// of wires, composed of the interrupts going to this\n\t\t\t// controller\n\t\t\ti_bus;\n\tunsigned\ti_max,\t// Max # of interrupts this controller can handle\n\t\t\t// i_nassigned is the number of interrupts that have\n\t\t\t// been given assignments (positions) to our interrupt\n\t\t\t// vector\n\t\t\ti_nassigned,\n\t\t\t// i_nallocated references the number of interrupts that\n\t\t\t// this controller knows about.  This is separate from\n\t\t\t// the number of interrupts that have positions assigned\n\t\t\t// to them\n\t\t\ti_nallocated;\n\t//\n\t// The list of all interrupts this controller can handle\n\t//\n\tILIST\t\ti_ilist;\n\t//\n\t// The list of assigned interrupts\n\tINTID\t\t**i_alist;\n\tPICINFO(MAPDHASH &pic) {\n\t\ti_max = 0;\n\t\tint\tmx = 0;\n\t\ti_name = getstring(pic, KYPREFIX);\n\t\tassert(i_name);\n\t\ti_bus  = getstring(pic, KYPIC_BUS);\n\t\tif (getvalue( pic, KYPIC_MAX, mx)) {\n\t\t\ti_max = mx;\n\t\t\ti_alist = new INTID *[mx];\n\t\t\tfor(int i=0; i<mx; i++)\n\t\t\t\ti_alist[i] = NULL;\n\t\t} else {\n\t\t\tgbl_msg.error(\"ERR: Cannot find PIC.MAX, the maximum number of interrupts %s can take on\\n\", (i_name) ? i_name->c_str() : \"(No name)\");\n\t\t\tgbl_msg.dump(pic);\n\t\t\ti_max = 0;\n\t\t\ti_alist = NULL;\n\t\t}\n\t\ti_nassigned  = 0;\n\t\ti_nallocated = 0;\n\t}\n\n\t// Add an interrupt with the given name, and hash source, to the table\n\tvoid add(MAPDHASH &psrc, STRINGP iname) {\n\t\tif (!iname)\n\t\t\treturn;\n\t\tif (i_nallocated >= i_max) {\n\t\t\tgbl_msg.warning(\"Interrupt %s not assigned, PIC %s is full\\n\",\n\t\t\t\tiname->c_str(), i_name->c_str());\n\t\t\treturn;\n\t\t}\n\n\t\tINTP\tip = new INTID();\n\t\ti_ilist.push_back(ip);\n\n\t\t// Initialize the table entry with the name of this interrupt\n\t\tassert(iname);\n\t\tip->i_name = trim(*iname);\n\t\tassert(ip->i_name->size() > 0);\n\t\t// The wire from the rest of the design to connect to this\n\t\t// interrupt bus\n\t\tip->i_wire = getstring(psrc, KY_WIRE);\n\t\t// We'll set the ID of this interrupt to MAX, to indicate that\n\t\t// the interrupt has not been assigned yet\n\t\tip->i_id   = i_max;\n\t\tip->i_hash = &psrc;\n\t\ti_nallocated++;\n\t}\n\n\t// This is identical to the add function above, save that we are adding\n\t// an interrupt with a known position assignment within the controller.\n\tvoid add(unsigned id, MAPDHASH &psrc, STRINGP iname) {\n\t\tif (!iname) {\n\t\t\tgbl_msg.warning(\"No name given for interrupt\\n\");\n\t\t\treturn;\n\t\t} else if (id >= i_max) {\n\t\t\tgbl_msg.error(\"ERR: Interrupt ID %d out of bounds [0..%d]\\n\",\n\t\t\t\tid, i_max);\n\t\t\treturn;\n\t\t} else if (i_nassigned+1 > i_max) {\n\t\t\tgbl_msg.error(\"ERR: Too many interrupts assigned to %s\\n\", i_name->c_str());\n\t\t\treturn;\n\t\t}\n\n\t\t// Check to see if any other interrupt already has this\n\t\t// identifier, and write an error out if so.\n\t\tif (i_alist[id]) {\n\t\t\tgbl_msg.error(\"%s and %s are both competing for the same interrupt ID, #%d\\n\",\n\t\t\t\ti_alist[id]->i_name->c_str(),\n\t\t\t\tiname->c_str(), id);\n\t\t\tgbl_msg.error(\"interrupt %s dropped\\n\", iname->c_str());\n\t\t\treturn;\n\t\t}\n\n\t\t// Otherwise, add the interrupt to our list\n\t\tINTP\tip = new INTID();\n\t\ti_ilist.push_back(ip);\n\t\tassert(iname);\n\t\tip->i_name = trim(*iname);\n\t\tassert(ip->i_name->size() > 0);\n\t\tip->i_wire = getstring(psrc, KY_WIRE);\n\t\tip->i_id   = id;\n\t\tip->i_hash = &psrc;\n\t\ti_nassigned++;\n\t\ti_nallocated++;\n\n\t\ti_alist[id] = ip;\n\t}\n\n\t// Let's look through our list of interrupts for unassigned interrupt\n\t// values, and ... assign them\n\tvoid assignids(void) {\n\t\tfor(unsigned iid=0; iid<i_max; iid++) {\n\t\t\tif (i_alist[iid])\n\t\t\t\tcontinue;\n\t\t\tunsigned mx = (i_ilist.size());\n\t\t\tunsigned\tuid = mx;\n\t\t\tfor(unsigned jid=0; jid < i_ilist.size(); jid++) {\n\t\t\t\tif (i_ilist[jid]->i_id >= i_max) {\n\t\t\t\t\tuid = jid;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (uid < mx) {\n\t\t\t\t// Assign this interrupt\n\t\t\t\t// 1. Give it an interrupt ID\n\t\t\t\ti_ilist[uid]->i_id = iid;\n\t\t\t\t// 2. Place it in our numbered interrupt list\n\t\t\t\ti_alist[iid] = i_ilist[uid];\n\t\t\t\ti_nassigned++;\n\t\t\t} else\n\t\t\t\tcontinue; // All interrupts assigned\n\t\t}\n\t\tif (i_max < i_ilist.size()) {\n\t\t\tgbl_msg.warning(\"Too many interrupts assigned to PIC %s\\n\", i_name->c_str());\n\t\t}\n\n\t\t// Write the interrupt assignments back into the map\n\t\tfor(unsigned iid=0; iid<i_ilist.size(); iid++) {\n\t\t\tif (i_ilist[iid]->i_id < i_max) {\n\t\t\t\tSTRING\tky = (*i_name) + \".ID\";\n\t\t\t\tsetvalue(*i_ilist[iid]->i_hash, ky, i_ilist[iid]->i_id);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Given an interrupt number associated with this PIC, lookup the\n\t// interrupt having that number, returning NULL on error or if not\n\t// found.\n\tINTP\tgetint(unsigned iid) {\n\t\tif ((iid < i_max)&&(NULL != i_alist[iid]))\n\t\t\treturn i_alist[iid];\n\t\treturn NULL;\n\t}\n};\ntypedef\tPICINFO\tPICI, *PICP;\ntypedef\tstd::vector<PICP>\tPICLIST;\n\n// A list of all of our interrupt controllers\nPICLIST\tpiclist;\nunsigned\tunusedmsk;\n// }}}\n\n// Return the number of interrupt controllers within this design.  If no such\n// field/tag exists, count the number and add it to the hash.\nint count_pics(MAPDHASH &info) {\n\t// {{{\n\tMAPDHASH::iterator\tkvpair, kvpic;\n\tint\tnpics=0;\n\n\tif (getvalue(info, KYNPIC, npics))\n\t\treturn npics;\n\n\tfor(kvpair = info.begin(); kvpair != info.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tkvpic = kvpair->second.u.m_m->find(KYPIC);\n\t\tif (kvpic != kvpair->second.u.m_m->end())\n\t\t\tnpics++;\n\t}\n\n\tsetvalue(info, KYNPIC, npics);\n\treturn npics;\n}\n// }}}\n\nvoid\tassign_int_to_pics(const STRING &iname, MAPDHASH &ihash) {\n\t// {{{\n\tSTRINGP\tpicname;\n\tint inum;\n\n\t// Now, we need to map this to a PIC\n\tif (NULL==(picname=getstring(ihash, KYPIC))) {\n\t\treturn;\n\t}\n\n\tchar\t*tok, *cpy, *sr;\n\tcpy = strdup(picname->c_str());\n\ttok = strtok_r(cpy, \", \\t\\n\", &sr);\n\twhile(tok) {\n\t\tunsigned pid;\n\t\tfor(pid = 0; pid<piclist.size(); pid++)\n\t\t\tif (piclist[pid]->i_name->compare(tok)==0)\n\t\t\t\tbreak;\n\t\tif (pid >= piclist.size()) {\n\t\t\tgbl_msg.error(\"PIC NOT FOUND: %s\\n\", tok);\n\t\t} else if (getvalue(ihash, KY_ID, inum)) {\n\t\t\tpiclist[pid]->add((unsigned)inum, ihash, (STRINGP)&iname);\n\t\t} else {\n\t\t\tpiclist[pid]->add(ihash, (STRINGP)&iname);\n\t\t}\n\t\ttok = strtok_r(NULL, \", \\t\\n\", &sr);\n\t} free(cpy);\n}\n// }}}\n\n//\n// assign_interrupts\n//\n// Find all the interrup controllers, and then find all the interrupts, and map\n// interrupts to controllers.  Individual interrupt wires may be mapped to\n// multiple interrupt controllers.\n//\nvoid\tassign_interrupts(MAPDHASH &master) {\n\t// {{{\n\tMAPDHASH::iterator\tkvpair, kvint, kvline;\n\tMAPDHASH\t*submap, *intmap;\n\tSTRINGP\t\tsintlist;\n\n\t// First step, gather all of our PIC's together\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (ispic(kvpair->second)) {\n\t\t\tPICP npic = new PICI(*kvpair->second.u.m_m);\n\t\t\tpiclist.push_back(npic);\n\t\t}\n\t}\n\n\t// Okay, now we need to gather all of our interrupts together and to\n\t// assign them to PICs.\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\n\t\t// submap now points to a component.  It can be any component.\n\t\t// We now need to check if it has an INT. hash.\n\t\tsubmap = kvpair->second.u.m_m;\n\t\tkvint = submap->find(KY_INT);\n\t\tif (kvint == submap->end()) {\n\t\t\tcontinue;\n\t\t} if (kvint->second.m_typ != MAPT_MAP) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Now, let's look to see if it has a list of interrupts\n\t\tif (NULL != (sintlist = getstring(kvint->second,\n\t\t\t\t\tKYINTLIST))) {\n\t\t\tconst char DELIMITERS[] = \" \\t\\n,\";\n\t\t\tchar\t*scpy = strdup(sintlist->c_str());\n\t\t\tchar\t*tok, *stoksv=NULL;\n\t\t\ttok = strtok_r(scpy, DELIMITERS, &stoksv);\n\t\t\twhile(tok) {\n\t\t\t\tSTRING\tstok = STRING(tok);\n\n\t\t\t\tkvline = findkey(*kvint->second.u.m_m, stok);\n\t\t\t\tif (kvline != kvint->second.u.m_m->end()) {\n\t\t\t\t\tassign_int_to_pics(stok,\n\t\t\t\t\t\t*kvline->second.u.m_m);\n\t\t\t\t} else\n\t\t\t\t\tgbl_msg.warning(\"INT %s not found, not connected\\n\", tok);\n\n\t\t\t\ttok = strtok_r(NULL, DELIMITERS, &stoksv);\n\t\t\t} free(scpy);\n\t\t} else {\n\t\t\t// NAME is now @comp.INT.\n\n\t\t\t// Yes, an INT hash exists within this component.\n\t\t\t// Hence the component has one (or more) interrupts.\n\t\t\t// Let's loop over those interrupts\n\t\t\tintmap = kvint->second.u.m_m;\n\t\t\tfor(kvline=intmap->begin(); kvline != intmap->end();\n\t\t\t\t\t\tkvline++) {\n\t\t\t\tif (kvline->second.m_typ != MAPT_MAP)\n\t\t\t\t\tcontinue;\n\t\t\t\tassign_int_to_pics(kvline->first,\n\t\t\t\t\t*kvline->second.u.m_m);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Now, let's assign everything that doesn't yet have any definitions\n\tfor(unsigned picid=0; picid<piclist.size(); picid++)\n\t\tpiclist[picid]->assignids();\n\treeval(master);\n}\n// }}}\n\nvoid\twriteout(FILE *fp, MAPDHASH &master, const STRING &ky) {\n\t// {{{\n\tMAPDHASH::iterator\tkvpair;\n\tSTRINGP\tstr;\n\n\t// fprintf(fp, \"// Looking for string: %s\\n\", ky.c_str());\n\n\tstr = getstring(master, ky);\n\tif (NULL != str) {\n\t\tfprintf(fp, \"%s\", str->c_str());\n\t}\n\n\tfor(kvpair = master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\t\tcontinue;\n\t\tstr = getstring(kvpair->second, ky);\n\t\tif (str == NULL)\n\t\t\tcontinue;\n\n\t\tfprintf(fp, \"%s\", str->c_str());\n\t}\n}\n// }}}\n\nvoid\tbuild_board_h(    MAPDHASH &master, FILE *fp, STRING &fname) {\n\t// {{{\n\tconst\tchar\tDELIMITERS[] = \" \\t\\n\";\n\tMAPDHASH::iterator\tkvpair;\n\tSTRING\tstr, astr;\n\tSTRINGP\tdefns;\n\n\tlegal_notice(master, fp, fname);\n\tfprintf(fp, \"#ifndef\tBOARD_H\\n#define\\tBOARD_H\\n\");\n\tfprintf(fp, \"\\n\");\n\tfprintf(fp, \"// And, so that we can know what is and isn\\'t defined\\n\");\n\tfprintf(fp, \"// from within our main.v file, let\\'s include:\\n\");\n\tfprintf(fp, \"#include <design.h>\\n\\n\");\n\n\tdefns = getstring(master, KYBDEF_INCLUDE);\n\tif (defns)\n\t\tfprintf(fp, \"%s\\n\\n\", defns->c_str());\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tdefns = getstring(kvpair->second, KYBDEF_INCLUDE);\n\t\tif (defns)\n\t\t\tfprintf(fp, \"%s\\n\\n\", defns->c_str());\n\t}\n\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tdefns = getstring(kvpair->second, KYBDEF_DEFN);\n\t\tif (defns)\n\t\t\tfprintf(fp, \"%s\\n\\n\", defns->c_str());\n\t}\n\n\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tchar\t*dup, *tok;\n\t\tSTRINGP\tosdef, osval, access;\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tosdef = getstring(*kvpair->second.u.m_m, KYBDEF_OSDEF);\n\t\tosval = getstring(*kvpair->second.u.m_m, KYBDEF_OSVAL);\n\n\t\tif ((!osdef)&&(!osval))\n\t\t\tcontinue;\n\t\taccess= getstring(kvpair->second, KYACCESS);\n\t\tdup = NULL;\n\t\ttok = NULL;\n\n\t\tif (access) {\n\t\t\tdup = strdup(access->c_str());\n\t\t\ttok = strtok(dup, DELIMITERS);\n\t\t\tif (tok[0] == '!')\n\t\t\t\ttok++;\n\t\t} else\ttok = NULL;\n\t\tif (tok)\n\t\t\tfprintf(fp, \"#ifdef\\t%s\\n\", tok);\n\t\tif (osdef)\n\t\t\tfprintf(fp, \"#define\\t%s\\n\", osdef->c_str());\n\t\tif (osval) {\n\t\t\tfputs(osval->c_str(), fp);\n\t\t\tif (osval->c_str()[strlen(osval->c_str())-1] != '\\n')\n\t\t\t\tfputc('\\n', fp);\n\t\t} if (tok)\n\t\t\tfprintf(fp, \"#endif\\t// %s\\n\", tok);\n\t}\n\n\tfprintf(fp, \"//\\n// Interrupt assignments (%ld PICs)\\n//\\n\", piclist.size());\n\tfor(unsigned pid = 0; pid<piclist.size(); pid++) {\n\t\tPICLIST::iterator picit = piclist.begin() + pid;\n\t\tPICP\tpic = *picit;\n\t\tfprintf(fp, \"// PIC: %s\\n\", pic->i_name->c_str());\n\t\tfor(unsigned iid=0; iid< pic->i_max; iid++) {\n\t\t\tINTP\tip = pic->getint(iid);\n\t\t\tif (NULL == ip)\n\t\t\t\tcontinue;\n\t\t\tif (NULL == ip->i_name)\n\t\t\t\tcontinue;\n\t\t\tchar\t*buf = strdup(pic->i_name->c_str()), *ptr;\n\t\t\tfor(ptr = buf; (*ptr); ptr++)\n\t\t\t\t*ptr = toupper(*ptr);\n\t\t\tfprintf(fp, \"#define\\t%s_%s\\t%s(%d)\\n\",\n\t\t\t\tbuf, ip->i_name->c_str(), buf, iid);\n\t\t\tfree(buf);\n\t\t}\n\t}\n\n\tdefns = getstring(master, KYBDEF_INSERT);\n\tif (defns)\n\t\tfprintf(fp, \"%s\\n\\n\", defns->c_str());\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tdefns = getstring(*kvpair->second.u.m_m, KYBDEF_INSERT);\n\t\tif (defns)\n\t\t\tfprintf(fp, \"%s\\n\\n\", defns->c_str());\n\t}\n\n\tfprintf(fp, \"#endif\\t// BOARD_H\\n\");\n}\n// }}}\n\nvoid\tbuild_latex_tbls( MAPDHASH &master) {\n\t// {{{\n\t// legal_notice(master, fp, fname);\n#ifdef\tNEW_FILE_FORMAT\n\tprintf(\"\\n\\n\\n// TO BE PLACED INTO doc/src\\n\");\n\n\tfor(int i=0; i<np; i++) {\n\t\tprintf(\"\\n\\n\\n// TO BE PLACED INTO doc/src/%s.tex\\n\",\n\t\t\tbus[i].b_data.);\n\t}\n\tprintf(\"\\n\\n\\n// TO BE PLACED INTO doc/src\\n\");\n#endif\n}\n// }}}\n\n//\n// void\tbuild_device_tree(MAPDHASH &master)\n//\nvoid\tbuild_toplevel_v( MAPDHASH &master, FILE *fp, STRING &fname) {\n\t// {{{\n\tMAPDHASH::iterator\tkvpair, kvaccess, kvsearch;\n\tSTRING\tstr = \"ACCESS\", astr;\n\tint\tfirst;\n\n\tlegal_notice(master, fp, fname);\n\tfprintf(fp, \"`default_nettype\\tnone\\n\");\n\t// Include a legal notice\n\t// Build a set of ifdefs to turn things on or off\n\tfprintf(fp, \"\\n\\n\");\n\n\t// Define our external ports within a port list\n\tfprintf(fp, \"//\\n\"\n\t\"// Here we declare our toplevel.v (toplevel) design module.\\n\"\n\t\"// All design logic must take place beneath this top level.\\n\"\n\t\"//\\n\"\n\t\"// The port declarations just copy data from the @TOP.PORTLIST\\n\"\n\t\"// key, or equivalently from the @MAIN.PORTLIST key if\\n\"\n\t\"// @TOP.PORTLIST is absent.  For those peripherals that don't need\\n\"\n\t\"// any top level logic, the @MAIN.PORTLIST should be sufficent,\\n\"\n\t\"// so the @TOP.PORTLIST key may be left undefined.\\n\"\n\t\"//\\n\"\n\t\"// The only exception is that any clocks with CLOCK.TOP tags will\\n\"\n\t\"// also appear in this list\\n\"\n\t\"//\\n\");\n\tfprintf(fp, \"module\\ttoplevel(\");\n\tint\tnclocks_at_top = 0;\n\tfor(unsigned ck=0; ck<cklist.size(); ck++) {\n\t\tif (cklist[ck].m_top) {\n\t\t\tfprintf(fp, \"%s%s,\", (nclocks_at_top > 0)?\" \":\"\",\n\t\t\t\tcklist[ck].m_top->c_str());\n\t\t\tnclocks_at_top++;\n\t\t}\n\t} fprintf(fp, \"\\n\");\n\n\tfirst = 1;\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tSTRINGP\tstrp;\n\n\t\tstrp = getstring(*kvpair->second.u.m_m, KYTOP_PORTLIST);\n\t\tif (!strp)\n\t\t\tstrp = getstring(*kvpair->second.u.m_m, KYMAIN_PORTLIST);\n\t\tif (!strp)\n\t\t\tcontinue;\n\n\t\tSTRING\ttmps(*strp);\n\t\tSTRING::iterator si;\n\t\tfor(si=tmps.end()-1; si>=tmps.begin(); si--)\n\t\t\tif (isspace(*si))\n\t\t\t\t*si = '\\0';\n\t\t\telse\n\t\t\t\tbreak;\n\t\tif (tmps.size() == 0)\n\t\t\tcontinue;\n\t\tif (!first)\n\t\t\tfprintf(fp, \",\\n\");\n\t\tfirst=0;\n\t\tfprintf(fp, \"%s\", tmps.c_str());\n\t} fprintf(fp, \");\\n\");\n\n\t// External declarations (input/output) for our various ports\n\tfprintf(fp, \"\\t//\\n\"\n\t\"\\t// Declaring any top level parameters.\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// These declarations just copy data from the @TOP.PARAM key,\\n\"\n\t\"\\t// or from the @MAIN.PARAM key if @TOP.PARAM is absent.  For\\n\"\n\t\"\\t// those peripherals that don't do anything at the top level,\\n\"\n\t\"\\t// the @MAIN.PARAM key should be sufficient, so the @TOP.PARAM\\n\"\n\t\"\\t// key may be left undefined.\\n\"\n\t\"\\t//\\n\");\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\n\t\tSTRINGP strp = getstring(*kvpair->second.u.m_m, KYTOP_PARAM);\n\t\tif (!strp)\n\t\t\tstrp = getstring(*kvpair->second.u.m_m, KYMAIN_PARAM);\n\t\tif (strp)\n\t\t\tfprintf(fp, \"%s\", strp->c_str());\n\t}\n\n\tfprintf(fp, \"\\t//\\n\"\n\t\"\\t// Declaring our input and output ports.  We listed these above,\\n\"\n\t\"\\t// now we are declaring them here.\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// These declarations just copy data from the @TOP.IODECLS key,\\n\"\n\t\"\\t// or from the @MAIN.IODECL key if @TOP.IODECL is absent.  For\\n\"\n\t\"\\t// those peripherals that don't do anything at the top level,\\n\"\n\t\"\\t// the @MAIN.IODECL key should be sufficient, so the @TOP.IODECL\\n\"\n\t\"\\t// key may be left undefined.\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// We start with any @CLOCK.TOP keys\\n\"\n\t\"\\t//\\n\");\n\tfor(unsigned ck=0; ck<cklist.size(); ck++) {\n\t\tif (cklist[ck].m_top) {\n\t\t\tfprintf(fp, \"\\tinput\\twire\\t\\t%s;\\n\",\n\t\t\t\tcklist[ck].m_top->c_str());\n\t\t}\n\t} for(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\n\t\tSTRINGP strp = getstring(*kvpair->second.u.m_m, KYTOP_IODECL);\n\t\tif (!strp)\n\t\t\tstrp = getstring(*kvpair->second.u.m_m, KYMAIN_IODECL);\n\t\tif (strp)\n\t\t\tfprintf(fp, \"%s\", strp->c_str());\n\t}\n\n\t// Declare peripheral data\n\tfprintf(fp, \"\\n\\n\");\n\tfprintf(fp, \"\\t//\\n\"\n\t\"\\t// Declaring component data, internal wires and registers\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// These declarations just copy data from the @TOP.DEFNS key\\n\"\n\t\"\\t// within the component data files.\\n\"\n\t\"\\t//\\n\");\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tSTRINGP\tstrp = getstring(*kvpair->second.u.m_m, KYTOP_DEFNS);\n\t\tif (strp)\n\t\t\tfprintf(fp, \"%s\", strp->c_str());\n\t}\n\n\tfprintf(fp, \"\\n\\n\");\n\tfprintf(fp, \"\"\n\t\"\\t//\\n\"\n\t\"\\t// Time to call the main module within main.v.  Remember, the purpose\\n\"\n\t\"\\t// of the main.v module is to contain all of our portable logic.\\n\"\n\t\"\\t// Things that are Xilinx (or even Altera) specific, or for that\\n\"\n\t\"\\t// matter anything that requires something other than on-off logic,\\n\"\n\t\"\\t// such as the high impedence states required by many wires, is\\n\"\n\t\"\\t// kept in this (toplevel.v) module.  Everything else goes in\\n\"\n\t\"\\t// main.v.\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// We automatically place s_clk, and s_reset here.  You may need\\n\"\n\t\"\\t// to define those above.  (You did, didn't you?)  Other\\n\"\n\t\"\\t// component descriptions come from the keys @TOP.MAIN (if it\\n\"\n\t\"\\t// exists), or @MAIN.PORTLIST if it does not.\\n\"\n\t\"\\t//\\n\");\n\tfprintf(fp, \"\\n\\tmain\\tthedesign(s_clk, s_reset,\\n\");\n\tfirst = 1;\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\n\t\tSTRINGP strp = getstring(*kvpair->second.u.m_m, KYTOP_MAIN);\n\t\tif (!strp)\n\t\t\tstrp = getstring(*kvpair->second.u.m_m, KYMAIN_PORTLIST);\n\t\tif (!strp)\n\t\t\tcontinue;\n\n\t\tSTRING\ttmps(*strp);\n\t\tSTRING::iterator si;\n\t\tfor(si=tmps.end()-1; si>=tmps.begin(); si--) {\n\t\t\tif (isspace(*si))\n\t\t\t\t*si = '\\0';\n\t\t\telse\n\t\t\t\tbreak;\n\t\t} if (tmps.size() == 0)\n\t\t\tcontinue;\n\t\tif (!first)\n\t\t\tfprintf(fp, \",\\n\");\n\t\tfirst=0;\n\t\tfprintf(fp, \"%s\", tmps.c_str());\n\t} fprintf(fp, \");\\n\");\n\n\tfprintf(fp, \"\\n\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// Our final section to the toplevel is used to provide all of\\n\"\n\t\"\\t// that special logic that couldnt fit in main.  This logic is\\n\"\n\t\"\\t// given by the @TOP.INSERT tag in our data files.\\n\"\n\t\"\\t//\\n\\n\\n\");\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tSTRINGP strp = getstring(*kvpair->second.u.m_m, KYTOP_INSERT);\n\t\tif (!strp)\n\t\t\tcontinue;\n\t\tfprintf(fp, \"%s\\n\", strp->c_str());\n\t}\n\n\tfprintf(fp, \"\\n\\nendmodule // end of toplevel.v module definition\\n\");\n\n}\n// }}}\n\nvoid\tbuild_main_v(     MAPDHASH &master, FILE *fp, STRING &fname) {\n\t// {{{\n\tchar\tDELIMITERS[] = \", \\t\\n\";\n\tMAPDHASH::iterator\tkvpair, kvaccess, kvsearch;\n\tSTRING\tstr, astr, sellist, acklist, siosel_str, diosel_str;\n\tint\t\tfirst;\n\n\tfprintf(fp, \"`timescale\\t1ps / 1ps\\n\");\n\tlegal_notice(master, fp, fname);\n\n\t// Include a legal notice\n\t// Build a set of ifdefs to turn things on or off\n\tfprintf(fp, \"`default_nettype\\tnone\\n\");\n\n\tfprintf(fp,\n\t\t\"////////////////////////////////////////////////////////////////////////////////\\n\"\n\t\t\"//\\n\" \"// Macro defines\\n\" \"// {{{\\n\");\n\tbuild_access_ifdefs_v(master, fp);\n\tfprintf(fp, \"// }}}\\n\");\n\n\tfprintf(fp,\n\t\t\"////////////////////////////////////////////////////////////////////////////////\\n\"\n\t\t\"//\\n\"\n\t\t\"// Any include files\\n// {{{\\n\"\n\t\t\"// These are drawn from anything with a MAIN.INCLUDE definition.\\n\");\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tSTRINGP\tstrp = getstring(kvpair->second, KYMAIN_INCLUDE);\n\t\tif (!strp)\n\t\t\tcontinue;\n\t\tfprintf(fp, \"%s\", strp->c_str());\n\t}\n\n\n\tfprintf(fp, \"// }}}\\n//\\n\");\n\tfprintf(fp,\n\"// Finally, we define our main module itself.  We start with the list of\\n\"\n\"// I/O ports, or wires, passed into (or out of) the main function.\\n\"\n\"//\\n\"\n\"// These fields are copied verbatim from the respective I/O port lists,\\n\"\n\"// from the fields given by @MAIN.PORTLIST\\n\"\n\"//\\n\");\n\n\t// Define our external ports within a port list\n\tfprintf(fp, \"module\\tmain(i_clk, i_reset,\\n\\t// {{{\\n\");\n\tstr = \"MAIN.PORTLIST\";\n\tfirst = 1;\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tSTRINGP\tstrp = getstring(*kvpair->second.u.m_m, str);\n\t\tif (!strp)\n\t\t\tcontinue;\n\n\t\tSTRING\ttmps(*strp);\n\t\tSTRING::iterator si;\n\t\tfor(si=tmps.end()-1; si>=tmps.begin(); si--) {\n\t\t\tif (isspace(*si))\n\t\t\t\t*si = '\\0';\n\t\t\telse\n\t\t\t\tbreak;\n\t\t} if (tmps.size() == 0)\n\t\t\tcontinue;\n\t\tif (!first)\n\t\t\tfprintf(fp, \",\\n\");\n\t\tfirst=0;\n\t\tfprintf(fp, \"%s\", tmps.c_str());\n\t} fprintf(fp, \"\\n\\t// }}}\\n\\t);\\n\");\n\n\tfprintf(fp,\n\t\t\"////////////////////////////////////////////////////////////////////////////////\\n\"\n\t\t\"//\\n\" \"// Any parameter definitions\\n// {{{\\n\"\n\t\t\"// These are drawn from anything with a MAIN.PARAM definition.\\n\"\n\t\t\"// As they aren\\'t connected to the toplevel at all, it would\\n\"\n\t\t\"// be best to use localparam over parameter, but here we don\\'t\\n\"\n\t\t\"// check\\n\");\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tSTRINGP\tstrp = getstring(kvpair->second, KYMAIN_PARAM);\n\t\tif (!strp)\n\t\t\tcontinue;\n\t\tfprintf(fp, \"%s\", strp->c_str());\n\t}\n\n\tfprintf(fp, \"// }}}\\n\"\n\"////////////////////////////////////////////////////////////////////////////////\\n\"\n\"//\\n\"\n\"// Port declarations\\n\"\n\"// {{{\\n\"\n\"// The next step is to declare all of the various ports that were just\\n\"\n\"// listed above.\\n\"\n\"//\\n\"\n\"// The following declarations are taken from the values of the various\\n\"\n\"// @MAIN.IODECL keys.\\n\"\n\"//\\n\");\n\n// #warning \"How do I know these will be in the same order?\n//\tThey have been--because the master always reads its subfields in the\n//\tsame order.\n//\n\t// External declarations (input/output) for our various ports\n\tfprintf(fp, \"\\tinput\\twire\\t\\ti_clk;\\n\\t// verilator lint_off UNUSED\\n\\tinput\\twire\\t\\ti_reset;\\n\\t// verilator lint_on UNUSED\\n\");\n\tstr = \"MAIN.IODECL\";\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tSTRINGP\tstrp;\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tstrp = getstring(*kvpair->second.u.m_m, str);\n\t\tif (strp)\n\t\t\tfprintf(fp, \"%s\", strp->c_str());\n\t}\n\tfprintf(fp, \"// }}}\\n\");\n\n\tfprintf(fp,\n\"\\t// Make Verilator happy\\n\"\n\"\\t// {{{\\n\"\n\"\\t// Defining bus wires for lots of components often ends up with unused\\n\"\n\"\\t// wires lying around.  We'll turn off Ver1lator\\'s lint warning\\n\"\n\"\\t// here that checks for unused wires.\\n\"\n\"\\t// }}}\\n\"\n\"\\t// verilator lint_off UNUSED\\n\");\n\n\tfprintf(fp,\n\t\"\\t////////////////////////////////////////////////////////////////////////\\n\"\n\t\"\\t//\\n\\t// Declaring interrupt lines\\n\\t// {{{\\n\"\n\t\"\\t// These declarations come from the various components values\\n\"\n\t\"\\t// given under the @INT.<interrupt name>.WIRE key.\\n\\t//\\n\");\n\t// Define any interrupt wires\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tMAPDHASH::iterator\tkvint, kvsub, kvwire;\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tkvint = kvpair->second.u.m_m->find(KY_INT);\n\t\tif (kvint == kvpair->second.u.m_m->end())\n\t\t\tcontinue;\n\t\tif (kvint->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tfor(kvsub=kvint->second.u.m_m->begin();\n\t\t\t\tkvsub != kvint->second.u.m_m->end(); kvsub++) {\n\t\t\tif (kvsub->second.m_typ != MAPT_MAP)\n\t\t\t\tcontinue;\n\n\n\t\t\t// Cant use getstring() here, 'cause we need the name of\n\t\t\t// the wire below\n\t\t\tkvwire = kvsub->second.u.m_m->find(KY_WIRE);\n\t\t\tif (kvwire == kvsub->second.u.m_m->end())\n\t\t\t\tcontinue;\n\t\t\tif (kvwire->second.m_typ != MAPT_STRING)\n\t\t\t\tcontinue;\n\t\t\tif (kvwire->second.u.m_s->size() == 0)\n\t\t\t\tcontinue;\n\t\t\tfprintf(fp, \"\\twire\\t%s;\\t// %s.%s.%s.%s\\n\",\n\t\t\t\tkvwire->second.u.m_s->c_str(),\n\t\t\t\tkvpair->first.c_str(),\n\t\t\t\tkvint->first.c_str(),\n\t\t\t\tkvsub->first.c_str(),\n\t\t\t\tkvwire->first.c_str());\n\t\t}\n\t}\n\tfprintf(fp, \"\\t// }}}\\n\");\n\n\tfprintf(fp,\n\t\"\\t////////////////////////////////////////////////////////////////////////\\n\"\n\t\"\\t//\\n\\t// Component declarations\\n\\t// {{{\\n\"\n\t\"\\t// These declarations come from the @MAIN.DEFNS keys found in the\\n\"\n\t\"\\t// various components comprising the design.\\n\\t//\\n\");\n\twriteout(fp, master, KYMAIN_DEFNS);\n\n\t// Declare interrupt vector wires.\n\tfprintf(fp,\n\t\"\\n// }}}\\n\"\n\t\"\\t////////////////////////////////////////////////////////////////////////\\n\"\n\t\"\\t//\\n\\t// Declaring interrupt vector wires\\n\\t// {{{\\n\"\n\t\"\\t// These declarations come from the various components having\\n\"\n\t\"\\t// PIC and PIC.MAX keys.\\n\\t//\\n\");\n\tfor(unsigned picid=0; picid < piclist.size(); picid++) {\n\t\tSTRINGP\tdefnstr, vecstr;\n\t\tMAPDHASH *picmap;\n\n\t\tif (piclist[picid]->i_max <= 0)\n\t\t\tcontinue;\n\t\tpicmap = getmap(master, *piclist[picid]->i_name);\n\t\tif (!picmap)\n\t\t\tcontinue;\n\t\tvecstr = getstring(*picmap, KYPIC_BUS);\n\t\tif (vecstr) {\n\t\t\tfprintf(fp, \"\\twire\\t[%d:0]\\t%s;\\n\",\n\t\t\t\t\tpiclist[picid]->i_max-1,\n\t\t\t\t\tvecstr->c_str());\n\t\t} else {\n\t\t\tdefnstr = piclist[picid]->i_name;\n\t\t\tif (defnstr)\n\t\t\t\tfprintf(fp, \"\\twire\\t[%d:0]\\t%s_int_vec;\\n\",\n\t\t\t\t\tpiclist[picid]->i_max-1,\n\t\t\t\t\tdefnstr->c_str());\n\t\t}\n\t}\n\tfprintf(fp, \"\\t// }}}\\n\");\n\twriteout_bus_defns_v(fp);\n\n\t// Define the select lines\n\tfprintf(fp, \"\\t////////////////////////////////////////////////////////////////////////\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// Peripheral address decoding, bus handling\\n\\t// {{{\\n\");\n\n\twriteout_bus_logic_v(fp);\n\n\tfprintf(fp, \"\\t// }}}\\n\"\n\t\"\\t////////////////////////////////////////////////////////////////////////\\n\"\n\t\"\\t//\\n\\t// Declare the interrupt busses\\n\\t// {{{\\n\"\n\"\\t// Interrupt busses are defined by anything with a @PIC tag.\\n\"\n\"\\t// The @PIC.BUS tag defines the name of the wire bus below,\\n\"\n\"\\t// while the @PIC.MAX tag determines the size of the bus width.\\n\"\n\"\\t//\\n\"\n\"\\t// For your peripheral to be assigned to this bus, it must have an\\n\"\n\"\\t// @INT.NAME.WIRE= tag to define the wire name of the interrupt line,\\n\"\n\"\\t// and an @INT.NAME.PIC= tag matching the @PIC.BUS tag of the bus\\n\"\n\"\\t// your interrupt will be assigned to.  If an @INT.NAME.ID tag also\\n\"\n\"\\t// exists, then your interrupt will be assigned to the position given\\n\"\n\"\\t// by the ID# in that tag.\\n\"\n\"\\t//\\n\");\n\tfor(unsigned picid=0; picid < piclist.size(); picid++) {\n\t\tSTRINGP\tdefnstr, vecstr;\n\t\tMAPDHASH *picmap;\n\n\t\tif (piclist[picid]->i_max <= 0)\n\t\t\tcontinue;\n\t\tpicmap = getmap(master, *piclist[picid]->i_name);\n\t\tif (!picmap)\n\t\t\tcontinue;\n\t\tvecstr = getstring(*picmap, KYPIC_BUS);\n\t\tif (vecstr) {\n\t\t\tfprintf(fp, \"\\tassign\\t%s = {\\n\",\n\t\t\t\t\tvecstr->c_str());\n\t\t} else {\n\t\t\tdefnstr = piclist[picid]->i_name;\n\t\t\tif (defnstr)\n\t\t\t\tfprintf(fp, \"\\tassign\\t%s_int_vec = {\\n\",\n\t\t\t\t\tdefnstr->c_str());\n\t\t\telse {\n\t\t\t\tgbl_msg.error(\"PIC has no associated name\\n\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tfor(int iid=piclist[picid]->i_max-1; iid>=0; iid--) {\n\t\t\tINTP\tiip = piclist[picid]->getint(iid);\n\t\t\tif ((iip == NULL)||(iip->i_wire == NULL)\n\t\t\t\t\t||(iip->i_wire->size() == 0)) {\n\t\t\t\tfprintf(fp, \"\\t\\t1\\'b0%s\\n\",\n\t\t\t\t\t(iid != 0)?\",\":\"\");\n\t\t\t\tcontinue;\n\t\t\t} fprintf(fp, \"\\t\\t%s%s\\n\",\n\t\t\t\tiip->i_wire->c_str(),\n\t\t\t\t(iid == 0)?\"\":\",\");\n\t\t}\n\t\tfprintf(fp, \"\\t};\\n\");\n\t}\n\tfprintf(fp, \"\\t// }}}\\n\");\n\n\tfprintf(fp,\n\t\t\"\\t////////////////////////////////////////////////////////////////////////\\n\"\n\t\t\"\\t////////////////////////////////////////////////////////////////////////\\n\"\n\t\t\"\\t//\\n\\t// @MAIN.INSERT and @MAIN.ALT\\n\"\n\t\t\"\\t// {{{\\n\"\n\t\t\"\\t////////////////////////////////////////////////////////////////////////\\n\"\n\t\t\"\\t////////////////////////////////////////////////////////////////////////\\n\");\n\tfprintf(fp,\n\t\"\\t//\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// Now we turn to defining all of the parts and pieces of what\\n\"\n\t\"\\t// each of the various peripherals does, and what logic it needs.\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// This information comes from the @MAIN.INSERT and @MAIN.ALT tags.\\n\"\n\t\"\\t// If an @ACCESS tag is available, an ifdef is created to handle\\n\"\n\t\"\\t// having the access and not.  If the @ACCESS tag is `defined above\\n\"\n\t\"\\t// then the @MAIN.INSERT code is executed.  If not, the @MAIN.ALT\\n\"\n\t\"\\t// code is exeucted, together with any other cleanup settings that\\n\"\n\t\"\\t// might need to take place--such as returning zeros to the bus,\\n\"\n\t\"\\t// or making sure all of the various interrupt wires are set to\\n\"\n\t\"\\t// zero if the component is not included.\\n\"\n\t\"\\t//\\n\");\n\n\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t// MAPDHASH::iterator\tkvpair, kvaccess, kvsearch;\n\t\tMAPDHASH::iterator\tkvint, kvsub, kvwire;\n\t\tbool\t\t\tnomain, noaccess, noalt;\n\t\tSTRINGP\t\t\tinsert, alt, access;\n\t\tchar\t\t\t*accessdup, *accesstok;\n\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tinsert = getstring(kvpair->second, KYMAIN_INSERT);\n\t\taccess = getstring(kvpair->second, KYACCESS);\n\t\talt    = getstring(kvpair->second, KYMAIN_ALT);\n\n\t\tnomain   = false;\n\t\tnoaccess = false;\n\t\tnoalt    = false;\n\t\taccessdup= NULL;\n\t\tif (NULL == insert)\n\t\t\tnomain = true;\n\t\tif (NULL == access) {\n\t\t\tnoaccess= true;\n\t\t} else {\n\t\t\taccessdup = strdup(access->c_str());\n\t\t\taccesstok = strtok(accessdup, DELIMITERS);\n\t\t\tif (accesstok[0] == '!')\n\t\t\t\taccesstok++;\n\t\t}\n\t\tif (NULL == alt)\n\t\t\tnoalt = true;\n\n\t\tif (noaccess) {\n\t\t\tif (!nomain)\n\t\t\t\tfputs(insert->c_str(), fp);\n\t\t} else if ((!nomain)||(!noalt)) {\n\t\t\tif (nomain) {\n\t\t\t\tfprintf(fp, \"`ifndef\\t%s\\n\", accesstok);\n\t\t\t} else {\n\t\t\t\tfprintf(fp, \"`ifdef\\t%s\\n\", accesstok);\n\t\t\t\tfprintf(fp, \"\\t// {{{\\n\");\n\t\t\t\tfputs(insert->c_str(), fp);\n\t\t\t\tfprintf(fp, \"\\t// }}}\\n\");\n\t\t\t\tfprintf(fp, \"`else\\t// %s\\n\", accesstok);\n\t\t\t}\n\t\t\tfprintf(fp, \"\\t// {{{\\n\");\n\n\t\t\tif (!noalt) {\n\t\t\t\tfputs(alt->c_str(), fp);\n\t\t\t}\n\n\t\t\tif (isbusmaster(kvpair->second)) {\n\t\t\t\t// {{{\n\t\t\t\tSTRINGP\tpfx = getstring(*kvpair->second.u.m_m,\n\t\t\t\t\t\t\tKYPREFIX);\n\t\t\t\tif (pfx) {\n\t\t\t\t\tSTRINGP\tbusname = getstring(\n\t\t\t\t\t\t\t*kvpair->second.u.m_m,\n\t\t\t\t\t\t\tKYMASTER_BUS_NAME);\n\t\t\t\t\tif (busname) {\n\t\t\t\t\t\tBUSINFO *bus = find_bus(busname);\n\t\t\t\t\t\tif (bus) {\n\t\t\t\t\t\t\tfprintf(fp, \"\\t// Null bus master\\n\\t// {{{\\n\");\n\t\t\t\t\t\t\tbus->writeout_no_master_v(fp);\n\t\t\t\t\t\t\tfprintf(fp, \"\\t// }}}\\n\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// }}}\n\t\t\t}\n\n\t\t\tif (isperipheral(kvpair->second)) {\n\t\t\t\t// {{{\n\t\t\t\tBUSINFO *bi = find_bus_of_peripheral(kvpair->second.u.m_m);\n\t\t\t\tSTRINGP\tpfx = getstring(*kvpair->second.u.m_m,\n\t\t\t\t\t\t\tKYSLAVE_PREFIX);\n\t\t\t\tif ((bi)&&(pfx)) {\n\t\t\t\t\tfprintf(fp, \"\\t// Null bus slave\\n\\t// {{{\\n\");\n\t\t\t\t\tbi->writeout_no_slave_v(fp, pfx);\n\t\t\t\t\tfprintf(fp, \"\\t// }}}\\n\");\n\t\t\t\t}\n\t\t\t\t// }}}\n\t\t\t}\n\t\t\tkvint    = kvpair->second.u.m_m->find(KY_INT);\n\t\t\tif ((kvint != kvpair->second.u.m_m->end())\n\t\t\t\t\t&&(kvint->second.m_typ == MAPT_MAP)) {\n\t\t\t\tMAPDHASH\t*imap = kvint->second.u.m_m,\n\t\t\t\t\t\t*smap;\n\t\t\t\tfprintf(fp, \"\\t// Null interrupt definitions\\n\"\n\t\t\t\t\t\"\\t// {{{\\n\");\n\t\t\t\tfor(kvsub=imap->begin(); kvsub != imap->end();\n\t\t\t\t\t\tkvsub++) {\n\t\t\t\t\t// p.INT.SUB\n\t\t\t\t\tif (kvsub->second.m_typ != MAPT_MAP)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tsmap = kvsub->second.u.m_m;\n\t\t\t\t\tkvwire = smap->find(KY_WIRE);\n\t\t\t\t\tif (kvwire == smap->end())\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tif (kvwire->second.m_typ != MAPT_STRING)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tif ((NULL == kvwire->second.u.m_s)\n\t\t\t\t\t\t||(kvwire->second.u.m_s->size()==0))\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tfprintf(fp, \"\\tassign\\t%s = 1\\'b0;\\t// %s.%s.%s.%s\\n\",\n\t\t\t\t\t\tkvwire->second.u.m_s->c_str(),\n\t\t\t\t\t\tkvpair->first.c_str(),\n\t\t\t\t\t\tkvint->first.c_str(),\n\t\t\t\t\t\tkvsub->first.c_str(),\n\t\t\t\t\t\tkvwire->first.c_str());\n\t\t\t\t}\n\t\t\t\tfprintf(fp, \"\\t// }}}\\n\");\n\t\t\t}\n\t\t\tfprintf(fp, \"\\t// }}}\\n\");\n\t\t\tfprintf(fp, \"`endif\\t// %s\\n\\n\", accesstok);\n\t\t}\n\n\t\tif (accessdup)\n\t\t\tfree(accessdup);\n\t}\n\n\n\tfprintf(fp, \"\\t// }}}\\nendmodule // main.v\\n\");\n\n}\n// }}}\n\nSTRINGP\tremove_comments(STRINGP s) {\n\tSTRINGP\tr;\n\tint\tsi, di;\t// Source and destination indices\n\n\tr = new STRING(*s);\n\tfor(si=0, di=0; (*s)[si]; si++) {\n\t\tif (((*s)[si] == '/')&&((*s)[si+1])&&((*s)[si+1] == '/')) {\n\t\t\t// Comment to the end of the line\n\t\t\tsi += 2;\n\t\t\twhile(((*s)[si])&&((*s)[si] != '\\r')&&((*s)[si] != '\\n'))\n\t\t\t\tsi++;\n\t\t} else if (((*s)[si] == '/')&&((*s)[si+1])&&((*s)[si+1] == '*')) {\n\t\t\tsi += 2;\n\t\t\t// Go until the end of a block comment\n\t\t\twhile(((*s)[si])&&((*s)[si] != '*')&&((!(*s)[si+1])||((*s)[si+1]!='/')))\n\t\t\t\tsi++;\n\t\t\tsi += 1;\n\t\t} else\n\t\t\t(*r)[di++] = (*s)[si];\n\t} (*r)[di] = '\\0';\n\n\treturn r;\n}\n\nvoid\tbuild_outfile_aux(MAPDHASH &info, STRINGP fname, STRINGP data) {\n\tSTRING\tstr;\n\tSTRINGP\tsubd = getstring(info, KYSUBD);\n\n\tif (NULL != strchr(fname->c_str(), '/')) {\n\t\tgbl_msg.warning(\"Output files can only be placed in output directory\\n\"\n\t\t\t\"Output file: %s ignored\\n\", fname->c_str());\n\t\treturn;\n\t}\n\n\tFILE\t*fp;\n\tstr = subd->c_str(); str += \"/\"+(*fname);\n\tfp = fopen(str.c_str(), \"w\");\n\tif (NULL == fp)\n\t\tgbl_msg.fatal(\"Cannot write %s\\n\", str.c_str());\n\n\tunsigned nw = fwrite(data->c_str(), 1, data->size(), fp);\n\tif (nw != data->size())\n\t\tgbl_msg.fatal(\"%s data not fully written\\n\", str.c_str());\n}\n\n\nvoid\tbuild_other_files(MAPDHASH &info) {\n\tMAPDHASH::iterator\tkvpair;\n\tSTRINGP\t\t\tfname, data;\n\n\tfor(kvpair = info.begin(); kvpair != info.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tfname = getstring(kvpair->second, KYOUT_FILE);\n\t\tif (NULL == fname)\n\t\t\tcontinue;\n\t\tdata  = getstring(kvpair->second, KYOUT_DATA);\n\t\tif (NULL == data)\n\t\t\tcontinue;\n\n\t\tbuild_outfile_aux(info, fname, data);\n\t}\n}\n\nFILE\t*open_in(MAPDHASH &info, const STRING &fname) {\n\tstatic\tconst\tchar\tdelimiters[] = \" \\t\\n:,\";\n\tSTRINGP\tpath = getstring(info, KYPATH);\n\tSTRING\tpathcpy;\n\tchar\t*tok;\n\tFILE\t*fp;\n\n\tif (!path)\n\t\tpath = getstring(gbl_hash, KYPATH);\n\tif (path && fname[0] != '.' && fname[0] != '/') {\n\t\tpathcpy = *path;\n\t\ttok =strtok((char *)pathcpy.c_str(), delimiters);\n\t\twhile(NULL != tok) {\n\t\t\tchar\t*prepath = realpath(tok, NULL);\n\t\t\tSTRING\tfpath = STRING(prepath) + \"/\" + fname;\n\t\t\tfree(prepath);\n\t\t\tif (NULL != (fp = fopen(fpath.c_str(), \"r\"))) {\n\t\t\t\treturn fp;\n\t\t\t}\n\t\t\ttok = strtok(NULL, delimiters);\n\t\t}\n\t}\n\treturn fopen(fname.c_str(), \"r\");\n}\n\n\ntypedef\tstd::vector<STRINGP>\tPORTLIST;\nvoid\tget_portlist(MAPDHASH &master, PORTLIST &ports) {\n\tMAPDHASH::iterator\tkvpair;\n\tSTRINGP\t\t\tstr, stripped;\n\tchar\t\t\t*pptr;\n\n\tfor(kvpair = master.begin(); kvpair != master.end(); kvpair++) {\n\t\tconst\tchar\t*DELIMITERS = \", \\t\\n\";\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tstr = getstring(kvpair->second, KYTOP_PORTLIST);\n\t\tif (str == NULL)\n\t\t\tstr = getstring(kvpair->second, KYMAIN_PORTLIST);\n\t\tif (str == NULL)\n\t\t\tcontinue;\n\t\tstripped = remove_comments(str);\n\n\t\tpptr = strtok((char *)stripped->c_str(), DELIMITERS);\n\t\twhile(pptr) {\n\t\t\tports.push_back(new STRING(pptr));\n\t\t\tgbl_msg.info(\"\\t%s\\n\", pptr);\n\t\t\tpptr = strtok(NULL, DELIMITERS);\n\t\t} delete stripped;\n\t}\n\n\t// Check any CLOCK.TOP keys\n\tfor(kvpair = master.begin(); kvpair != master.end(); kvpair++) {\n\t\tconst\tchar\t*DELIMITERS = \", \\t\\n\";\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tstr = getstring(kvpair->second, KYCLOCK_TOP);\n\t\tif (str == NULL)\n\t\t\tcontinue;\n\t\tstripped = remove_comments(str);\n\n\t\tpptr = strtok((char *)stripped->c_str(), DELIMITERS);\n\t\twhile(pptr) {\n\t\t\tports.push_back(new STRING(pptr));\n\t\t\tgbl_msg.info(\"\\t%s\\n\", pptr);\n\t\t\tpptr = strtok(NULL, DELIMITERS);\n\t\t} delete stripped;\n\t}\n}\n\nvoid\tbuild_xdc(MAPDHASH &master, FILE *fp, STRING &fname) {\n\tMAPDHASH::iterator\tkvpair;\n\tSTRINGP\t\t\tstr;\n\tPORTLIST\t\tports;\n\tFILE\t\t\t*fpsrc;\n\tchar\tline[512];\n\n\tgbl_msg.info(\"\\n\\nBUILD-XDC\\nLooking for ports:\\n\");\n\tgbl_msg.flush();\n\n\tget_portlist(master, ports);\n\n\tstr = getstring(master, KYXDC_FILE);\n\tfpsrc = open_in(master, *str);\n\n\tif (!fpsrc) {\n\t\tgbl_msg.fatal(\"Could not find or open %s\\n\", str->c_str());\n\t}\n\n\t// Uncomment any lines referencing top-level ports\n\t// {{{\n\twhile(fgets(line, sizeof(line), fpsrc)) {\n\t\tconst char\t*GET_PORTS_KEY = \"get_ports\",\n\t\t\t\t*SET_PROPERTY_KEY = \"set_property\";\n\t\tconst\tchar\t*cptr;\n\n\t\tSTRINGP\ttmp = trim(STRING(line));\n\t\tstrcpy(line, tmp->c_str());\n\t\tdelete\ttmp;\n\n\n\t\t// Ignore any lines that don't begin with #,\n\t\t// Ignore any lines that start with two ##'s,\n\t\t// Ignore any lines that don't have set_property within them\n\t\tif ((line[0] != '#')||(line[1] == '#')\n\t\t\t||(NULL == (cptr= strstr(line, SET_PROPERTY_KEY)))) {\n\t\t\tfprintf(fp, \"%s\\n\", line);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (NULL != (cptr = strstr(cptr, GET_PORTS_KEY))) {\n\t\t\tbool\tfound = false;\n\n\t\t\tcptr += strlen(GET_PORTS_KEY);\n\t\t\twhile((*cptr)&&(*cptr != '{')&&(isspace(*cptr)))\n\t\t\t\tcptr++;\n\t\t\tif (*cptr == '{')\n\t\t\t\tcptr++;\n\t\t\tif (!(*cptr)) {\n\t\t\t\tfprintf(fp, \"%s\\n\", line);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\twhile((*cptr)&&(isspace(*cptr)))\n\t\t\t\tcptr++;\n\n\t\t\tchar\t\t*ptr, *name;\n\t\t\tname = strdup(cptr);\n\t\t\tptr = name;\n\t\t\twhile((*ptr)\n\t\t\t\t&&(*ptr != '[')\n\t\t\t\t&&(*ptr != '}')\n\t\t\t\t&&(*ptr != ']')\n\t\t\t\t&&(!isspace(*ptr)))\n\t\t\t\tptr++;\n\t\t\t*ptr = '\\0';\n\n\t\t\tgbl_msg.info(\"Found XDC port: %s\\n\", name);\n\n\t\t\t// Now, let's check to see if this is in our set\n\t\t\tfor(unsigned k=0; k<ports.size(); k++) {\n\t\t\t\tif (strcmp(ports[k]->c_str(), name)==0) {\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} free(name);\n\n\t\t\tif (found) {\n\t\t\t\tint start = 0;\n\t\t\t\twhile((line[start])&&(\n\t\t\t\t\t\t(line[start]=='#')\n\t\t\t\t\t\t||(isspace(line[start]))))\n\t\t\t\t\tstart++;\n\t\t\t\tfprintf(fp, \"%s\\n\", &line[start]);\n\t\t\t} else\n\t\t\t\tfprintf(fp, \"%s\\n\", line);\n\t\t} else\n\t\t\tfprintf(fp, \"%s\\n\", line);\n\t}\n\t// }}}\n\n\tfclose(fpsrc);\n\n\tfprintf(fp, \"\\n## Adding in any XDC_INSERT tags\\n\\n\");\n\t// {{{\n\tfor(kvpair = master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tstr = getstring(kvpair->second, KYXDC_INSERT);\n\t\tif (NULL == str) {\n\t\t\tfprintf(fp, \"## No XDC.INSERT tag in %s\\n\",\n\t\t\t\tkvpair->first.c_str());\n\t\t\tcontinue;\n\t\t}\n\n\t\tfprintf(fp, \"## From %s\\n%s\", kvpair->first.c_str(),\n\t\t\tstr->c_str());\n\t}\n\tstr = getstring(master, KYXDC_INSERT);\n\tif (NULL != str) {\n\t\tfprintf(fp, \"## From the global level\\n%s\",\n\t\t\tstr->c_str());\n\t}\n\t// }}}\n}\n\nvoid\tbuild_pcf(MAPDHASH &master, FILE *fp, STRING &fname) {\n\tMAPDHASH::iterator\tkvpair;\n\tSTRINGP\t\t\tstr;\n\tPORTLIST\t\tports;\n\tFILE\t\t\t*fpsrc;\n\tchar\tline[512];\n\n\tgbl_msg.info(\"\\n\\nBUILD-PCF\\nLooking for ports:\\n\");\n\tgbl_msg.flush();\n\n\tget_portlist(master, ports);\n\n\tstr = getstring(master, KYPCF_FILE);\n\tfpsrc = open_in(master, *str);\n\n\tif (!fpsrc) {\n\t\tgbl_msg.fatal(\"Could not find or open %s\\n\", str->c_str());\n\t}\n\n\t// Uncomment any lines referencing top-level ports\n\t// {{{\n\twhile(fgets(line, sizeof(line), fpsrc)) {\n\t\tconst char\t*SET_IO_KEY = \"set_io\";\n\t\tconst\tchar\t*cptr;\n\n\t\tSTRINGP\ttmp = trim(STRING(line));\n\t\tstrcpy(line, tmp->c_str());\n\t\tdelete\ttmp;\n\n\n\t\t// Ignore any lines that don't begin with #,\n\t\t// Ignore any lines that start with two ##'s,\n\t\t// Ignore any lines that don't have the SET_IO_KEY within them\n\t\tif ((line[0] != '#')||(line[1] == '#')\n\t\t\t||(NULL == (cptr= strstr(line, SET_IO_KEY)))) {\n\t\t\tfprintf(fp, \"%s\\n\", line);\n\t\t\tcontinue;\n\t\t}\n\n\t\tbool\tfound = false;\n\t\tchar\t*cpy = strdup(cptr + strlen(SET_IO_KEY));\n\t\tchar\t\t*ptr, *name;\n\n\t\tname = strtok(cpy, \" \\t\");\n\n\t\tptr = name;\n\t\twhile((*ptr)\n\t\t\t&&(*ptr != '[')\n\t\t\t&&(*ptr != '}')\n\t\t\t&&(*ptr != ']')\n\t\t\t&&(!isspace(*ptr)))\n\t\t\tptr++;\n\t\t*ptr = '\\0';\n\n\t\tgbl_msg.info(\"Found PCF port: %s\\n\", name);\n\n\t\t// Now, let's check to see if this is in our set\n\t\tfor(unsigned k=0; k<ports.size(); k++) {\n\t\t\tif (strcmp(ports[k]->c_str(), name)==0) {\n\t\t\t\tfound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} free(cpy);\n\n\t\tif (found) {\n\t\t\tint start = 0;\n\t\t\twhile((line[start])&&(\n\t\t\t\t\t(line[start]=='#')\n\t\t\t\t\t||(isspace(line[start]))))\n\t\t\t\tstart++;\n\t\t\tfprintf(fp, \"%s\\n\", &line[start]);\n\t\t} else\n\t\t\tfprintf(fp, \"%s\\n\", line);\n\t} fclose(fpsrc);\n\t// }}}\n\n\tfprintf(fp, \"\\n## Adding in any PCF_INSERT tags\\n\\n\");\n\t// {{{\n\tfor(kvpair = master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tstr = getstring(kvpair->second, KYPCF_INSERT);\n\t\tif (NULL == str) {\n\t\t\tfprintf(fp, \"## No PCF.INSERT tag in %s\\n\",\n\t\t\t\tkvpair->first.c_str());\n\t\t\tcontinue;\n\t\t}\n\n\t\tfprintf(fp, \"## From %s\\n%s\", kvpair->first.c_str(),\n\t\t\tstr->c_str());\n\t}\n\tstr = getstring(master, KYPCF_INSERT);\n\tif (NULL != str) {\n\t\tfprintf(fp, \"## From the global level\\n%s\",\n\t\t\tstr->c_str());\n\t}\n\t// }}}\n}\n\nvoid\tbuild_lpf(MAPDHASH &master, FILE *fp, STRING &fname) {\n\tMAPDHASH::iterator\tkvpair;\n\tSTRINGP\t\t\tstr;\n\tPORTLIST\t\tports;\n\tFILE\t\t\t*fpsrc;\n\tchar\tline[512];\n\n\tgbl_msg.info(\"\\n\\nBUILD-LPF\\nLooking for ports:\\n\");\n\tgbl_msg.flush();\n\n\tget_portlist(master, ports);\n\n\t// Uncomment any lines referencing top-level ports\n\t// {{{\n\tstr = getstring(master, KYLPF_FILE);\n\tfpsrc = open_in(master, *str);\n\n\tif (!fpsrc) {\n\t\tgbl_msg.fatal(\"Could not find or open %s\\n\", str->c_str());\n\t}\n\n\twhile(fgets(line, sizeof(line), fpsrc)) {\n\t\tconst char\t*LOC_KEY = \"LOCATE COMP\",\n\t\t\t\t*BUF_KEY = \"IOBUF PORT\";\n\t\tconst\tchar\t*locp, *bufp, *keyp;\n\n\t\tSTRINGP\ttmp = trim(STRING(line));\n\t\tstrcpy(line, tmp->c_str());\n\t\tdelete\ttmp;\n\n\n\t\t// Ignore any lines that don't begin with #,\n\t\t// Ignore any lines that start with two ##'s,\n\t\t// Ignore any lines that don't have either key within them\n\t\tif ((line[0] != '#')||(line[1] == '#')\n\t\t\t||((NULL == (locp= strcasestr(line, LOC_KEY)))\n\t\t\t&&(NULL == (bufp= strcasestr(line, BUF_KEY))))) {\n\t\t\tfprintf(fp, \"%s\\n\", line);\n\t\t\tcontinue;\n\t\t}\n\n\t\tbool\tfound = false;\n\t\tkeyp = LOC_KEY;\n\t\tif (!locp) {\n\t\t\tlocp = bufp;\n\t\t\tkeyp = BUF_KEY;\n\t\t}\n\n\t\tif (strncmp(locp+strlen(keyp), \" \\\"\", 2)==0)\n\t\t\tlocp += 2;\n\t\tchar\t*cpy = strdup(locp + strlen(keyp));\n\t\tchar\t\t*ptr, *name;\n\n\t\tname = strtok(cpy, \" \\t\");\n\n\t\tptr = name;\n\t\twhile((*ptr)\n\t\t\t&&(*ptr != '[')\n\t\t\t&&(*ptr != '}')\n\t\t\t&&(*ptr != ']')\n\t\t\t&&(*ptr != '\\\"')\n\t\t\t&&(!isspace(*ptr)))\n\t\t\tptr++;\n\t\t*ptr = '\\0';\n\n\t\tgbl_msg.info(\"Found LOC port: %s\\n\", name);\n\n\t\t// Now, let's check to see if this is in our set\n\t\tfor(unsigned k=0; k<ports.size(); k++) {\n\t\t\tif (strcmp(ports[k]->c_str(), name)==0) {\n\t\t\t\tfound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} free(cpy);\n\n\t\tif (found) {\n\t\t\tint start = 0;\n\t\t\twhile((line[start])&&(\n\t\t\t\t\t(line[start]=='#')\n\t\t\t\t\t||(isspace(line[start]))))\n\t\t\t\tstart++;\n\t\t\tfprintf(fp, \"%s\\n\", &line[start]);\n\t\t} else\n\t\t\tfprintf(fp, \"%s\\n\", line);\n\t} fclose(fpsrc);\n\t// }}}\n\n\tfprintf(fp, \"\\n## Adding in any LPF_INSERT tags\\n\\n\");\n\t// {{{\n\tfor(kvpair = master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tstr = getstring(kvpair->second, KYLPF_INSERT);\n\t\tif (NULL == str)\n\t\t\tcontinue;\n\n\t\tfprintf(fp, \"## From %s\\n%s\", kvpair->first.c_str(),\n\t\t\tstr->c_str());\n\t}\n\tstr = getstring(master, KYLPF_INSERT);\n\tif (NULL != str) {\n\t\tfprintf(fp, \"## From the global level\\n%s\",\n\t\t\tstr->c_str());\n\t}\n\t// }}}\n}\n\nvoid\tbuild_ucf(MAPDHASH &master, FILE *fp, STRING &fname) {\n\tMAPDHASH::iterator\tkvpair;\n\tSTRINGP\t\t\tstr;\n\tFILE\t\t\t*fpsrc;\n\tPORTLIST\t\tports;\n\tchar\tline[512];\n\n\tgbl_msg.info(\"\\n\\nBUILD-UCF\\nLooking for ports:\\n\");\n\tgbl_msg.flush();\n\n\tget_portlist(master, ports);\n\n\t// Uncomment any lines referencing top-level ports\n\t// {{{\n\tstr = getstring(master, KYUCF_FILE);\n\tfpsrc = open_in(master, *str);\n\n\tif (!fpsrc) {\n\t\tgbl_msg.fatal(\"Could not find or open %s\\n\", str->c_str());\n\t}\n\n\twhile(fgets(line, sizeof(line), fpsrc)) {\n\t\tconst char\t*NET_KEY = \"NET\";\n\t\tconst char\t*cptr;\n\n\t\tif ((line[0] == '#')&&(cptr = strstr(line, NET_KEY))) {\n\t\t\tbool\tfound = false;\n\n\n\t\t\tcptr += strlen(NET_KEY);\n\t\t\tif (!isspace(*cptr)) {\n\t\t\t\tfprintf(fp, \"%s\", line);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Skip white space\n\t\t\twhile((*cptr)&&(isspace(*cptr)))\n\t\t\t\tcptr++;\n\n\t\t\t// On a broken file, just continue\n\t\t\tif (!(*cptr)) {\n\t\t\t\tfprintf(fp, \"%s\", line);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\n\t\t\tchar\t*ptr, *name;\n\t\t\tname = strdup(cptr+1);\n\n\t\t\tptr = name;\n\t\t\twhile((*ptr)&&(!isspace(*ptr))&&(*ptr != ';'))\n\t\t\t\tptr++;\n\t\t\t*ptr = '\\0';\n\n\t\t\tgbl_msg.info(\"Found UCF port: %s\", name);\n\t\t\tgbl_msg.flush();\n\n\t\t\t// Now, let's check to see if this is in our set\n\t\t\tfor(unsigned k=0; k<ports.size(); k++) {\n\t\t\t\tif (strcmp(ports[k]->c_str(), name)==0) {\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} free(name);\n\n\t\t\tif (found) {\n\t\t\t\tunsigned start = 0;\n\t\t\t\twhile((line[start])&&(\n\t\t\t\t\t\t(line[start]=='#')\n\t\t\t\t\t\t||(isspace(line[start]))))\n\t\t\t\t\tstart++;\n\t\t\t\tfprintf(fp, \"%s\", &line[start]);\n\t\t\t} else\n\t\t\t\tfprintf(fp, \"%s\", line);\n\t\t} else\n\t\t\tfprintf(fp, \"%s\", line);\n\t} fclose(fpsrc);\n\t// }}}\n\n\tfprintf(fp, \"\\n## Adding in any UCF_INSERT tags\\n\\n\");\n\t// {{{\n\tfor(kvpair = master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tstr = getstring(kvpair->second, KYUCF_INSERT);\n\t\tif (str == NULL)\n\t\t\tcontinue;\n\n\t\tfprintf(fp, \"## From %s\\n%s\", kvpair->first.c_str(),\n\t\t\tstr->c_str());\n\t} str = getstring(master, KYUCF_INSERT);\n\tif (NULL != str) {\n\t\tfprintf(fp, \"## From the global level\\n%s\",\n\t\t\tstr->c_str());\n\t}\n\t// }}}\n}\n\nint\tmain(int argc, char **argv) {\n\tint\t\targn, nhash = 0;\n\tMAPDHASH\tmaster;\n\tFILE\t\t*fp;\n\tSTRING\t\tstr, cmdline, searchstr = \".\";\n\tconst char\t*subdir = NULL;\n\n\n\t// gbl_msg.open(\"autofpga.dbg\", \"w\");\n\n\tif (argc > 0) {\n\t\tcmdline = STRING(argv[0]);\n\t\tfor(argn=1; argn<argc; argn++) {\n\t\t\tcmdline = cmdline + \" \" + STRING(argv[argn]);\n\t\t}\n\n\t\tsetstring(master, KYCMDLINE, new STRING(cmdline));\n\t}\n\n\tfor(argn=1; argn<argc; argn++) {\n\t\tif (argv[argn][0] == '-') {\n\t\t\tfor(int j=1; ((j<2000)&&(argv[argn][j])); j++) {\n\t\t\t\tswitch(argv[argn][j]) {\n\t\t\t\tcase 'd':\n\t\t\t\t\tif (argv[argn][j+1]) {\n\t\t\t\t\t\tgbl_msg.open(\"autofpga.dbg\");\n\t\t\t\t\t\tgbl_msg.userinfo(\"Opened %s\\n\", \"autofpga.dbg\");\n\t\t\t\t\t} else if (argv[argn+1][0] == '-') {\n\t\t\t\t\t\tgbl_msg.open(\"autofpga.dbg\");\n\t\t\t\t\t\tgbl_msg.userinfo(\"Opened %s\\n\", \"autofpga.dbg\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tgbl_msg.open(argv[++argn]);\n\t\t\t\t\t\tgbl_msg.userinfo(\"Opened %s\\n\", argv[argn]);\n\t\t\t\t\t}\n\t\t\t\t\tj+=5000;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'o': subdir = argv[++argn];\n\t\t\t\t\tj+=5000;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'I':\n\t\t\t\t\tsearchstr = searchstr + \":\" + argv[++argn];\n\t\t\t\t\tsetstring(master, KYPATH, new STRING(searchstr));\n\t\t\t\t\tj+=5000;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'V':\n#ifdef\tBUILDDATE\n\t\t\t\t\tprintf(\"autofpga\\nbuilt on %08x\\n\", BUILDDATE);\n#else\n\t\t\t\t\tprintf(\"autofpga [data-file-list]*\\n\");\n#endif\n\t\t\t\t\texit(EXIT_SUCCESS);\n\t\t\t\tdefault:\n\t\t\t\t\tfprintf(stderr, \"Unknown argument, -%c\\n\", argv[argn][j]);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tMAPDHASH\t*fhash;\n\t\t\tSTRINGP\t\tpath;\n\n\t\t\tpath = getstring(master, KYPATH);\n\t\t\tif (NULL == path) {\n\t\t\t\tpath = new STRING(\".\");\n\t\t\t\tsetstring(master, KYPATH, path);\n\t\t\t} fhash = parsefile(argv[argn], *path);\n\t\t\tif (fhash) {\n\t\t\t\tmergemaps(master, *fhash);\n\t\t\t\tdelete fhash;\n\n\t\t\t\tnhash++;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (nhash == 0)\n\t\tgbl_msg.fatal(\"No files given, no files written\\n\");\n\n\tgbl_hash = &master;\n\n\tSTRINGP\tsubd = NULL;\n\tif (subdir) {\n\t\tsubd = new STRING(subdir);\n\t\tsetstring(master, KYSUBD, subd);\n\t} else {\n\t\tsubd = getstring(master, KYSUBD);\n\t} if (subd == NULL) {\n\t\t// subd = new STRING(\"autofpga-out\");\n\t\tsubd = new STRING(\"demo-out\");\n\t\tsetstring(master, KYSUBD, subd);\n\t}\n\tif ((*subd) == STRING(\"/\")) {\n\t\tgbl_msg.fatal(\"OUTPUT SUBDIRECTORY = %s\\n\"\n\t\t\t\"Cowardly refusing to place output products into the \"\n\t\t\t\"root directory, '/'\\n\", subd->c_str());\n\t} if ((*subd)[subd->size()-1] == '/')\n\t\t(*subd).erase(subd->size()-1);\n\n\t{\t// Build ourselves a subdirectory for our outputs\n\t\t// First, check if the directory exists.\n\t\t// If it does not, then create it.\n\t\tstruct\tstat\tsbuf;\n\t\tif (0 == stat(subd->c_str(), &sbuf)) {\n\t\t\tif (!S_ISDIR(sbuf.st_mode)) {\n\t\t\t\tgbl_msg.fatal(\"%s exists, and is not a directory\\n\"\n\t\t\t\t\"Cowardly refusing to erase %s and build a directory in its place\\n\", subd->c_str(), subd->c_str());\n\t\t\t}\n\t\t} else if (mkdir(subd->c_str(), 0777) != 0) {\n\t\t\tgbl_msg.fatal(\"Could not create %s/ directory\\n\",\n\t\t\t\tsubd->c_str());\n\t\t}\n\t}\n\n\tSTRINGP\tlegal = getstring(master, KYLEGAL);\n\tif (legal == NULL) {\n\t\tlegal = getstring(master, KYCOPYRIGHT);\n\t\tif (legal == NULL)\n\t\t\tlegal = new STRING(\"legalgen.txt\");\n\t\tsetstring(master, KYLEGAL, legal);\n\t}\n\n\tflatten(master);\n\n\t// trimbykeylist(master, KYKEYS_TRIMLIST);\n\tcvtintbykeylist(master, KYKEYS_INTLIST);\n\n\treeval(master);\n\tassign_interrupts(master);\n\treeval(master);\n\tfind_clocks(master);\n\t// assign_scopes(    master);\n\tbuild_bus_list(master);\n\t// assign_addresses( master);\n\t// get_address_width(master);\n\n\treeval(master);\n\n\tstr = subd->c_str(); str += \"/regdefs.h\";\n\tfp = fopen(str.c_str(), \"w\");\n\tif (fp) { build_regdefs_h(  master, fp, str); fclose(fp); }\n\n\tstr = subd->c_str(); str += \"/regdefs.cpp\";\n\tfp = fopen(str.c_str(), \"w\");\n\tif (fp) { build_regdefs_cpp(  master, fp, str); fclose(fp); }\n\n\tstr = subd->c_str(); str += \"/board.h\";\n\tfp = fopen(str.c_str(), \"w\");\n\tif (fp) { build_board_h(  master, fp, str); fclose(fp); }\n\n\tbuild_ld_files(master, subd);\n\n\tbuild_latex_tbls( master);\n\n\tstr = subd->c_str(); str += \"/toplevel.v\";\n\tfp = fopen(str.c_str(), \"w\");\n\tif (fp) { build_toplevel_v(  master, fp, str); fclose(fp); }\n\n\tstr = subd->c_str(); str += \"/main.v\";\n\tfp = fopen(str.c_str(), \"w\");\n\tif (fp) { build_main_v(  master, fp, str);\n\t\t// fprintf(fp, \"//\\n//\\n//\\n//\\n//\\n//\\n\");\n\t\t// writeout_bus_defns_v(fp);\n\t\t// writeout_bus_logic_v(fp);\n\t\tfclose(fp); }\n\tbuild_cachable_v(master, subd);\n\n\tstr = subd->c_str(); str += \"/rtl.make.inc\";\n\tfp = fopen(str.c_str(), \"w\");\n\tif (fp) { build_rtl_make_inc(  master, fp, str); fclose(fp); }\n\n\tstr = subd->c_str(); str += \"/testb.h\";\n\tfp = fopen(str.c_str(), \"w\");\n\tif (fp) { build_testb_h(  master, fp, str); fclose(fp); }\n\n\tif (NULL != getstring(master, KYXDC_FILE)) {\n\t\tstr = subd->c_str(); str += \"/build.xdc\";\n\t\tfp = fopen(str.c_str(), \"w\");\n\t\tif (fp) { build_xdc(  master, fp, str); fclose(fp); }\n\t\telse\n\t\t\tgbl_msg.error(\"Cannot open %s !\\n\", str.c_str());\n\t}\n\n\tif (NULL != getstring(master, KYPCF_FILE)) {\n\t\tstr = subd->c_str(); str += \"/build.pcf\";\n\t\tfp = fopen(str.c_str(), \"w\");\n\t\tif (fp) { build_pcf(  master, fp, str); fclose(fp); }\n\t\telse\n\t\t\tgbl_msg.error(\"Cannot open %s !\\n\", str.c_str());\n\t}\n\n\tif (NULL != getstring(master, KYLPF_FILE)) {\n\t\tstr = subd->c_str(); str += \"/build.lpf\";\n\t\tfp = fopen(str.c_str(), \"w\");\n\t\tif (fp) { build_lpf(  master, fp, str); fclose(fp); }\n\t\telse\n\t\t\tgbl_msg.error(\"Cannot open %s !\\n\", str.c_str());\n\t}\n\n\tif (NULL != getstring(master, KYUCF_FILE)) {\n\t\tstr = subd->c_str(); str += \"/build.ucf\";\n\t\tfp = fopen(str.c_str(), \"w\");\n\t\tif (fp) { build_ucf(  master, fp, str); fclose(fp); }\n\t}\n\n\tstr = subd->c_str(); str += \"/main_tb.cpp\";\n\tfp = fopen(str.c_str(), \"w\");\n\tif (fp) { build_main_tb_cpp(  master, fp, str); fclose(fp); }\n\n\tbuild_other_files(master);\n\n\tif (0 != gbl_msg.status())\n\t\tgbl_msg.error(\"ERR: Errors present\\n\");\n\n\tgbl_msg.dump(master);\n\treturn gbl_msg.status();\n}\n"
  },
  {
    "path": "sw/automdata.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/automdata.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\t\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2015-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tAUTOMDATA_H\n#define\tAUTOMDATA_H\n\ntypedef\tstruct\tBUSMASTER_S {\n\tconst\tchar\t*prefix;\t// to build %s_cyc\n\tconst\tchar\t*access;\t// for `ifdef\n} BUSMASTER;\n\n#endif\n"
  },
  {
    "path": "sw/autopdata.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/autopdata.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\t\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tAUTOPDATA_H\n#define\tAUTOPDATA_H\n\ntypedef\tstruct\tREGINFO_S {\n\tint\t\toffset;\n\tconst char\t*defname;\n\tconst char\t*namelist;\n} REGINFO;\n\ntypedef\tstruct\tAUTOPDATA_S {\n\tconst char\t*prefix;\n\tint\tnaddr;\n\tconst char\t*access;\n\tconst char\t*ext_ports, *ext_decls;\n\tconst char\t*main_defns;\n\tconst char\t*dbg_defns;\n\tconst char\t*main_insert;\n\tconst char\t*alt_insert;\n\tconst char\t*dbg_insert;\n\tREGINFO\t\t*pregs;\n\tconst char\t*cstruct, *ioname;\n} AUTOPDATA;\n\n#endif\n"
  },
  {
    "path": "sw/bitlib.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bitlib.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tBasic bit-level processing functions.\n//\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n\n\n\n//\n// nextlg\n// {{{\n// This is basically ceil(log_2(vl))\n//\nunsigned\tnextlg(const unsigned long vl) {\n\tunsigned r;\n\n\tfor(r=0; (1ul<<r)<(unsigned long)vl; r+=1)\n\t\t;\n\treturn r;\n}\n// }}}\n\n//\n// popc\n// {{{\n// Return the number of non-zero bits in a given value\nunsigned\tpopc(const unsigned vl) {\n\tunsigned\tr;\n\tr = ((vl & 0xaaaaaa)>>1)+(vl & 0x55555555);\n\tr = (r & 0x33333333)+((r>> 2)&0x33333333);\n\tr = (r +(r>> 4))&0x0f0f0f0f;\n\tr = (r +(r>> 8))&0x001f001f;\n\tr = (r +(r>>16))&0x03f;\n\treturn r;\n}\n// }}}\n"
  },
  {
    "path": "sw/bitlib.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bitlib.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\t\n//\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tBITLIB_H\n#define\tBITLIB_H\n\n\n//\n// nextlg\n//\n// This is basically ceil(log_2(vl))\n//\nunsigned\tnextlg(const unsigned long vl);\n\n//\n// popc\n//\n// Return the number of non-zero bits in a given value\nunsigned\tpopc(const unsigned vl);\n\n#endif\t// BITLIB_H\n"
  },
  {
    "path": "sw/bldboardld.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bldboardld.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tBuilds the board.h file, used by the CPU within the design\n//\t\t(if present) to know where particular components are located\n//\ton the bus.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <string.h>\n#include <unistd.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <limits.h>\n#include <ctype.h>\n\n#include \"parser.h\"\n#include \"keys.h\"\n#include \"kveval.h\"\n#include \"legalnotice.h\"\n#include \"bldtestb.h\"\n#include \"bitlib.h\"\n#include \"plist.h\"\n#include \"bldregdefs.h\"\n#include \"ifdefs.h\"\n#include \"bldsim.h\"\n#include \"predicates.h\"\n#include \"businfo.h\"\n#include \"globals.h\"\n#include \"gather.h\"\n#include \"msgs.h\"\n\nstatic void\tbuild_script_ld(MAPDHASH &master, MAPDHASH &busmaster, FILE *fp, STRING &fname) {\n\tMAPDHASH::iterator\tkvpair;\n\tSTRINGP\t\tstrp;\n\tint\t\treset_address;\n\tPERIPHP\t\tfastmem = NULL, bigmem = NULL, bootmem = NULL;\n\tAPLIST\t\t*alist;\n\tBUSINFO\t\t*bi;\n\tMAPDHASH\t*bimap;\n\tint\t\tfound = 0;\n\n\tlegal_notice(master, fp, fname, \"/*******************************************************************************\", \"*\");\n\tfprintf(fp, \"*/\\n\");\n\n\tif (NULL == (strp = getstring(busmaster, KYLD_ENTRY)))\n\t\tfprintf(fp, \"ENTRY(_start)\\n\\n\");\n\telse\n\t\tfprintf(fp, \"ENTRY(%s)\\n\\n\", strp->c_str());\n\n\tbimap = getmap(busmaster, KYMASTER_BUS);\n\tif (bimap == NULL) {\n\t\tgbl_msg.error(\"Linker script not found within a bus master component\\n\");\n\t\treturn;\n\t}\n\n\tbi = find_bus(bimap);\n\talist = gather_peripherals(bi);\n\tsort(alist->begin(), alist->end(), compare_regaddr);\n\n\tfprintf(fp, \"MEMORY\\n{\\n\"\n\"\\t/* To be listed here, a slave must be of type MEMORY.  If the slave\\n\"\n\"\\t* has a defined name in its @%s tag, it will be listed here\\n\"\n\"\\t* under that name, otherwise it will be listed under it\\'s\\n\"\n\"\\t* @$(PREFIX) tag with an underscore prepended to it.  The permissions\\n\"\n\"\\t* are given by the @%s tag.  Allowable permissions include\\n\"\n\"\\t* \\'r\\' (read only), \\'rx\\' (read and execute, but no writes),\\n\"\n\"\\t* \\'wx\\' (read, write, and execute).  If no permission tag exists, a\\n\"\n\"\\t* permission of \\'r\\' will be assumed.\\n\"\n\"\\t*/\\n\", KYLD_NAME.c_str(), KYLD_PERM.c_str());\n\n\tfor(unsigned i=0; i<alist->size(); i++) {\n\t\tPERIPHP\tp = (*alist)[i];\n\t\tSTRINGP\tname = getstring(*p->p_phash, KYLD_NAME),\n\t\t\tperm = getstring(*p->p_phash, KYLD_PERM);\n\n\t\tif (!ismemory(*p->p_phash)) {\n\t\t\t// fprintf(fp,\"\\t\\t/* %s is not a memory */\\n\",\n\t\t\t//\t(name) ? name->c_str():p->p_name->c_str());\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (NULL == name)\n\t\t\tname = p->p_name;\n\t\tfound++;\n\t\tfprintf(fp,\"\\t%8s(%2s) : ORIGIN = 0x%08lx, LENGTH = 0x%08x\\n\",\n\t\t\tname->c_str(), (perm)?(perm->c_str()):\"r\",\n\t\t\tp->p_regbase,\n\t\t\t(p->naddr()*(p->p_slave_bus->data_width()/8)));\n\n\t\tif (perm != NULL && (perm->compare(\"wx\") != 0)\n\t\t\t\t&& (perm->compare(\"rx\") != 0))\n\t\t\tgbl_msg.warning(\"%s.LD.PERM=%s is not supported.\\nUse either wx or rx as defined by ld\\n\",\n\t\t\t\tname->c_str(), perm->c_str());\n\t\tif ((perm == NULL) || (tolower(perm->c_str()[0]) != 'w')) {\n\t\t\t// Read only memory must be flash\n\t\t\tif (!bootmem)\n\t\t\t\tbootmem = p;\n\t\t\telse if ((bootmem)&&(KYFLASH.compare(*name)==0))\n\t\t\t\t// Unless flash is explicitly named\n\t\t\t\tbootmem = p;\n\t\t} else {\n\t\t\t// Find our bigest (and fastest?) memories\n\t\t\tif (!bigmem)\n\t\t\t\tbigmem = p;\n\t\t\telse if ((bigmem)&&(p->naddr() > bigmem->naddr())) {\n\t\t\t\tbigmem = p;\n\t\t\t}\n\t\t}\n\t}\n\tif (found == 0)\n\t\tfprintf(fp, \"\\t/* No memories found */\\n\");\n\tfprintf(fp, \"}\\n\\n\");\n\n\tfprintf(fp,\n\"/* For each defined memory peripheral, we also define a pointer to that\\n\"\n\"* memory.  The name of this pointer is given by the @%s tag within\\n\"\n\"* the memory peripheral\\'s configuration\\n\"\n\"*/\\n\", KYLD_NAME.c_str());\n\t// Define pointers to these memories\n\tfor(unsigned i=0; i<alist->size(); i++) {\n\t\tPERIPHP\tp = (*alist)[i];\n\t\tSTRINGP\tname = getstring(*p->p_phash, KYLD_NAME);\n\n\t\tif (!ismemory(*p->p_phash))\n\t\t\tcontinue;\n\n\t\tif (NULL == name)\n\t\t\tname = p->p_name;\n\n\t\tfprintf(fp, \"_%-8s = ORIGIN(%s);\\n\",\n\t\t\tname->c_str(), name->c_str());\n\t}\n\n\tSTRINGP\tdefns, ldfile;\n\tdefns = getstring(master, KYLD_DEFNS);\n\tif (NULL != defns) {\n\t\tldfile = getstring(master, KYLD_FILE);\n\t\tif ((NULL == ldfile)||(ldfile->compare(fname)==0))\n\t\t\tfprintf(fp, \"%s\\n\", defns->c_str());\n\t}\n\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tdefns = getstring(kvpair->second, KYLD_DEFNS);\n\t\tif (NULL == defns)\n\t\t\tcontinue;\n\t\tldfile = getstring(kvpair->second, KYLD_FILE);\n\t\tif ((NULL == ldfile)||(ldfile->compare(fname)==0))\n\t\t\tfprintf(fp, \"%s\\n\", defns->c_str());\n\t}\n\n\t//\n\t// Check to see if the configuration for this master has already given\n\t// us a linker script to work with.  If so, use it.\n\t//\n\tif (NULL != (strp = getstring(busmaster,KYLD_SCRIPT))) {\n\t\tfprintf(fp, \"%s\\n\", strp->c_str());\n\n\t\t// clear_regbase(alist);\n\t\t// delete\talist;\n\t\treturn;\n\t}\n\n\t//\n\t// There is no given configuration script.  We'll have to try to build\n\t// one using a default that may or may not apply in all cases.  This is\n\t// making the best of a bad situation.\n\t//\n\tif (!getvalue(master, KYRESET_ADDRESS, reset_address)) {\n\t\tbool\tfound = false;\n\t\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\t\tcontinue;\n\t\t\tif (getvalue(*kvpair->second.u.m_m, KYRESET_ADDRESS, reset_address)) {\n\t\t\t\tfound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} if (!found) {\n\t\t\tif (bootmem) {\n\t\t\t\treset_address = bootmem->p_regbase;\n\t\t\t} else {\n\t\t\t\tfor(unsigned i=0; i<alist->size(); i++) {\n\t\t\t\t\tPERIPHP\tp = (*alist)[i];\n\t\t\t\t\tif (!ismemory(*p->p_phash))\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tSTRINGP\tname = getstring(*p->p_phash, KYLD_NAME);\n\t\t\t\t\tif (NULL == name) {\n\t\t\t\t\t\tbootmem = p;\n\t\t\t\t\t\tname = p->p_name;\n\t\t\t\t\t} if (KYFLASH.compare(*name) == 0) {\n\t\t\t\t\t\treset_address = p->p_regbase;\n\t\t\t\t\t\tbootmem = p;\n\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} if (!found) {\n\t\t\treset_address = 0;\n\t\t\tgbl_msg.warning(\"RESET_ADDRESS NOT FOUND, assuming address zero\\n\");\n\t\t}\n\t}\n\n\tif ((reset_address != 0)&&(!bootmem)) {\n\t\t// We have a boot memory, but just don't know what it is.\n\t\t// Let's go find it\n\t\tfor(unsigned i=0; i<alist->size(); i++) {\n\t\t\tPERIPHP\tp = (*alist)[i];\n\n\t\t\t// If its not a memory, then we can't boot from it\n\t\t\tif (!ismemory(*p->p_phash))\n\t\t\t\tcontinue;\n\n\t\t\t// If the reset address comes before this address,\n\t\t\t// then its not the right peripheral\n\t\t\tif ((unsigned)reset_address < p->p_regbase)\n\t\t\t\tcontinue;\n\t\t\t// Likewise if the reset address comes after this\n\t\t\t// peripheral, this peripheral isn't it either\n\t\t\telse if ((unsigned)reset_address\n\t\t\t\t>= p->p_regbase + (p->naddr()\n\t\t\t\t\t*(p->p_slave_bus->data_width()/8)))\n\t\t\t\tcontinue;\n\n\t\t\t// Otherwise we just found it.\n\t\t\tbootmem = p;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (!bootmem) {\n\t\tgbl_msg.warning(\"WARNING: No boot device, abandoning board.ld\\n\");\n\t} else {\n\n\t\tfprintf(fp, \"SECTIONS\\n{\\n\");\n\t\tfprintf(fp, \"\\t.rocode 0x%08x : ALIGN(4) {\\n\"\n\t\t\t\"\\t\\t_boot_address = .;\\n\"\n\t\t\t\"\\t\\t*(.start) *(.boot)\\n\", reset_address);\n\t\tfprintf(fp, \"\\t} > %s\\n\\t_kernel_image_start = . ;\\n\",\n\t\t\tbootmem->p_name->c_str());\n\t\tif ((fastmem)&&(fastmem != bigmem)) {\n\t\t\tSTRINGP\tname = getstring(*fastmem->p_phash, KYLD_NAME);\n\t\t\tif (!name)\n\t\t\tname = fastmem->p_name;\n\t\t\tfprintf(fp, \"\\t.fastcode : ALIGN_WITH_INPUT {\\n\"\n\t\t\t\t\t\"\\t\\t*(.kernel)\\n\"\n\t\t\t\t\t\"\\t\\t_kernel_image_end = . ;\\n\"\n\t\t\t\t\t\"\\t\\t*(.start) *(.boot)\\n\");\n\t\t\tfprintf(fp, \"\\t} > %s\", name->c_str());\n\t\t\tif (bootmem != fastmem)\n\t\t\t\tfprintf(fp, \" AT>%s\", bootmem->p_name->c_str());\n\t\t\tfprintf(fp, \"\\n\");\n\t\t} else {\n\t\t\tfprintf(fp, \"\\t_kernel_image_end = . ;\\n\");\n\t\t}\n\n\t\tif (bigmem) {\n\t\t\tSTRINGP\tname = getstring(*bigmem->p_phash, KYLD_NAME);\n\t\t\tif (!name)\n\t\t\t\tname = bigmem->p_name;\n\t\t\tfprintf(fp, \"\\t_ram_image_start = . ;\\n\");\n\t\t\tfprintf(fp, \"\\t.ramcode : ALIGN_WITH_INPUT {\\n\");\n\t\t\tif ((!fastmem)||(fastmem == bigmem))\n\t\t\t\tfprintf(fp, \"\\t\\t*(.kernel)\\n\");\n\t\t\tfprintf(fp, \"\"\n\t\t\t\t\"\\t\\t*(.text.startup)\\n\"\n\t\t\t\t\"\\t\\t*(.text*)\\n\"\n\t\t\t\t\"\\t\\t*(.rodata*) *(.strings)\\n\"\n\t\t\t\t\"\\t\\t*(.data) *(COMMON)\\n\"\n\t\t\t\"\\t\\t}> %s\", bigmem->p_name->c_str());\n\t\t\tif (bootmem != bigmem)\n\t\t\t\tfprintf(fp, \" AT> %s\", bootmem->p_name->c_str());\n\t\t\tfprintf(fp, \"\\n\\t_ram_image_end = . ;\\n\"\n\t\t\t\t\"\\t.bss : ALIGN_WITH_INPUT {\\n\"\n\t\t\t\t\t\"\\t\\t*(.bss)\\n\"\n\t\t\t\t\t\"\\t\\t_bss_image_end = . ;\\n\"\n\t\t\t\t\t\"\\t\\t} > %s\\n\",\n\t\t\t\tbigmem->p_name->c_str());\n\t\t}\n\n\t\tfprintf(fp, \"\\t_top_of_heap = .;\\n\");\n\t\tfprintf(fp, \"}\\n\");\n\t}\n}\n\nvoid\tbuild_ld_files(MAPDHASH &master, STRINGP subd) {\n\tFILE\t\t *fp;\n\tMAPDHASH::iterator\tkvpair;\n\tSTRINGP\t\tfnamep;\n\tMAPDHASH\t*bimap;\n\n\tfor(kvpair = master.begin(); kvpair != master.end(); kvpair++) {\n\t\tSTRINGP\tmtyp;\n\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\n\t\tfnamep = getstring(kvpair->second.u.m_m, KYLD_FILE);\n\t\tif (fnamep == NULL)\n\t\t\t// No linker script filename, ignore this component\n\t\t\tcontinue;\n\n\t\tbimap = getmap(kvpair->second.u.m_m, KYMASTER_BUS);\n\t\tif (bimap == NULL) {\n\t\t\tgbl_msg.error(\"Linker scripts can only be made within bus master.  %s is not a bus master\\n\", kvpair->first.c_str());\n\t\t\tcontinue;\n\t\t}\n\n\t\tmtyp = getstring(kvpair->second.u.m_m, KYMASTER_TYPE);\n\t\tif ((mtyp == NULL)||(KYSCRIPT.compare(*mtyp)!=0)) {\n\t\t\tgbl_msg.error(\"Linker script for %s \"\n\t\t\t\t\"must have type SCRIPT, not %s\\n\",\n\t\t\t\tkvpair->first.c_str(),\n\t\t\t\t(mtyp) ? mtyp->c_str() : \"(NULL)\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (fnamep->size() < 3) {\n\t\t\tgbl_msg.error(\"Linker script filename, %s, \"\n\t\t\t\t\"for %s is too short\\n\",\n\t\t\t\tfnamep->c_str(), kvpair->first.c_str());\n\t\t\tcontinue;\n\t\t} else if ((*fnamep)[0] == '/') {\n\t\t\tgbl_msg.error(\"Cowardly refusing to write a linker \"\n\t\t\t\t\"script to an absolute pathname, %s\\n\",\n\t\t\t\tfnamep->c_str());\n\t\t\tcontinue;\n\t\t}\n\n\t\tSTRING\tfname = (*subd) + \"/\" + (*fnamep);\n\t\tif (strcmp(&fname.c_str()[fname.size()-3],\".ld\")!=0)\n\t\t\tfname += \".ld\";\n\t\tfp = fopen(fname.c_str(), \"w\");\n\t\tif (fp == NULL)\n\t\t\tgbl_msg.error(\"Could not write linker script, %s\\n\",\n\t\t\t\tfname.c_str());\n\t\telse {\n\t\t\tbuild_script_ld(master, *kvpair->second.u.m_m,\n\t\t\t\tfp, *fnamep);\n\t\t\tfclose(fp);\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "sw/bldboardld.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bldboardld.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\t\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tBLDBOARDLD_H\n#define\tBLDBOARDLD_H\n\n#include <stdio.h>\n#include <string>\n#include \"parser.h\"\n\nextern\tvoid\tbuild_ld_files(MAPDHASH &master, STRINGP subd);\n\n#endif\t// BLDBOARDLD_H\n"
  },
  {
    "path": "sw/bldcachable.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bldcachable.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tCreates a verilog file, upon request, containing combinatorial\n//\t\tlogic returning true if a particular address beneath this\n//\tlocation in the address/bus hierarchy is a memory.  This can be used\n//\tto determine if an address is a cachable address or not--something the\n//\tZipCPU data cache needs to know.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <string.h>\n\n#include \"bldcachable.h\"\n#include \"keys.h\"\n#include \"legalnotice.h\"\n#include \"businfo.h\"\n#include \"bitlib.h\"\n#include \"predicates.h\"\n#include \"msgs.h\"\n\n\nstatic void\tprint_cachable(FILE *fp, BUSINFO *bi,\n\t\tunsigned dw,\n\t\tunsigned mask_8,\n\t\tunsigned addr_8) {\n\tunsigned\tpbits;\n\tunsigned\tsubmask = 0, subaddr = 0;\n\tunsigned\tlgdw = nextlg(bi->data_width()), bbits=lgdw-3;\n\tPLIST\t\t*pl;\n\n\n\tpl = bi->m_plist;\n\tfprintf(fp, \"\\t\\t// Bus master: %s\\n\", bi->name()->c_str());\n\tsubmask = mask_8; // Octets\n\tfor(unsigned i=0; i<pl->size(); i++)\n\t\tsubmask |= (*pl)[i]->p_mask << bbits;\t// bytes\n\n\tfor(unsigned i=0; i<pl->size(); i++) {\n\t\tif (!(*pl)[i]->p_name) {\n\t\t\tcontinue;\n\t\t} if (((0)&&(*pl)[i]->p_mask == 0)) {\n\t\t\tcontinue;//\n\t\t}\n\n\n\t\t// Octets\n\t\tif (bi->word_addressing())\n\t\t\tsubmask = ((*pl)[i]->p_mask<<bbits) | mask_8;\n\t\telse\n\t\t\tsubmask = ((*pl)[i]->p_mask) | mask_8;\n\t\tsubaddr = ((*pl)[i]->p_base | addr_8) & submask;\n\t\tpbits = nextlg(submask);\n\t\tif ((1ul<<pbits) <= submask)\n\t\t\tpbits++;\t// log_2 Octets\n\n\t\tif ((*pl)[i]->p_master_bus) {\n\t\t\tprint_cachable(fp, (*pl)[i]->p_master_bus,\n\t\t\t\tdw, submask, subaddr);\n\t\t\tcontinue;\n\t\t} else if ((!(*pl)[i]->ismemory())\n\t\t\t&&(!issubbus(*(*pl)[i]->p_phash))) {\n\t\t\t// fprintf(fp, \"\\t\\t// %s: Not a memory\\n\", (*pl)[i]->p_name->c_str());\n\t\t\tcontinue;\n\t\t}\n\n\t\t// pbits -= dw;\n\t\tfprintf(fp, \"\\t\\t// %s\\n\"\n\t\t\"\\t\\tif ((i_addr[%d:0] & %d'h%0*x) == %d'h%0*x)\\n\"\n\t\t\t\t\"\\t\\t\\to_cachable = 1'b1;\\n\",\n\t\t\t(*pl)[i]->p_name->c_str(), pbits - 1,\n\t\t\tpbits, (pbits+3)/4, submask,\n\t\t\tpbits, (pbits+3)/4, subaddr);\n\t}\n}\n\nvoid build_cachable_core_v(MAPDHASH &master, MAPDHASH &busmaster,\n\t\tFILE *fp, STRING &fname) {\n\t// We come in here after a CACHEABLE.FILE = (*fname) key\n\tchar\t*modulename;\n\tconst char *ptr;\n\tBUSINFO\t*bi;\n\tint\tdw;\n\tMAPDHASH\t*bimap;\n\n\tbimap = getmap(busmaster, KYMASTER_BUS);\n\tif (bimap == NULL) {\n\t\tgbl_msg.error(\"Could not find MASTER.BUS key for LD script file %s\\n\", fname.c_str());\n\t\treturn;\n\t}\n\n\tbi = find_bus(bimap);\n\n\tif (NULL == (ptr = strrchr(fname.c_str(),'/')))\n\t\tmodulename = strdup(fname.c_str());\n\telse\n\t\tmodulename = strdup(ptr+1);\n\n\tassert((strlen(modulename)>2)\n\t\t&& strcmp(&modulename[strlen(modulename)-2],\".v\")==0);\n\n\tmodulename[strlen(modulename)-2] = '\\0';\n\n\tlegal_notice(master, fp, fname);\n\tfprintf(fp,\n\"`default_nettype none\\n\"\n\"//\\n\"\n\"module %s(\\n\"\n\t\"\\t\\t// {{{\\n\"\n\t\"\\t\\tinput\\twire\\t[%d-1:0]\\ti_addr,\\n\"\n\t\"\\t\\toutput\\treg\\t\\t\\to_cachable\\n\"\n\t\"\\t\\t// }}}\\n\"\n\t\"\\t);\\n\"\n\t\"\\n\", modulename, bi->byte_address_width());\n\tfree(modulename);\n\n\tfprintf(fp,\n\t\"\\talways @(*)\\n\"\n\t\"\\tbegin\\n\"\n\t\"\\t\\to_cachable = 1'b0;\\n\");\n\n\tdw = bi->data_width();\n\tdw = nextlg(dw)-3;\n\tprint_cachable(fp, bi, dw, 0, 0);\n\n\tfprintf(fp,\n\t\"\\tend\\n\"\n\"\\n\"\n\"endmodule\\n\");\n}\n\nvoid build_cachable_v(MAPDHASH &master, STRINGP subd) {\n\tFILE\t*fp;\n\tMAPDHASH::iterator\tkvpair;\n\tSTRINGP\tfnamep;\n\n\tfor(kvpair = master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tfnamep = getstring(kvpair->second.u.m_m, KYCACHABLE_FILE);\n\t\tif (fnamep == NULL)\n\t\t\t// No cachable file tag, ignore this component\n\t\t\tcontinue;\n\n\t\t// A cachable file tag can only be found within a bus master\n\t\t// component\n\t\tif (fnamep->size() < 3) {\n\t\t\tgbl_msg.error(\"Cachable filename is too short\\n\",\n\t\t\t\tkvpair->first.c_str());\n\t\t\tcontinue;\n\t\t} else if ((*fnamep)[0] == '/') {\n\t\t\tgbl_msg.error(\"Cowardly refusing to write cachable with an absolute pathname, %s\\n\",\n\t\t\t\tfnamep->c_str());\n\t\t\tcontinue;\n\t\t}\n\n\t\tSTRING\tfname = (*subd) + \"/\" + (*fnamep);\n\t\tif (strcmp(&fname.c_str()[fname.size()-2],\".v\") != 0)\n\t\t\tfname += \".v\";\n\t\tfp = fopen(fname.c_str(), \"w\");\n\t\tif (fp == NULL)\n\t\t\tgbl_msg.error(\"Could not write cachable file: %s\\n\", fname.c_str());\n\t\telse {\n\t\t\tbuild_cachable_core_v(master, *kvpair->second.u.m_m,\n\t\t\t\tfp, fname);\n\t\t\tfclose(fp);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "sw/bldcachable.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bldcachable.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\t\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tBLDCACHABLE_H\n#define\tBLDCACHABLE_H\n\n#include <stdio.h>\n#include <string>\n#include \"parser.h\"\n\nextern\tvoid\tbuild_cachable_v(MAPDHASH &master, STRINGP subd);\n\n#endif\t// BLDCACHABLE_H\n"
  },
  {
    "path": "sw/bldregdefs.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bldregdefs.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tTo build the regdefs.h and regdefs.cpp files.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <string.h>\n#include <unistd.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <limits.h>\n#include <ctype.h>\n\n#include \"parser.h\"\n#include \"keys.h\"\n#include \"kveval.h\"\n#include \"legalnotice.h\"\n#include \"plist.h\"\n#include \"bldregdefs.h\"\n#include \"businfo.h\"\n#include \"subbus.h\"\n#include \"globals.h\"\n#include \"gather.h\"\n#include \"msgs.h\"\n\nextern\tbool\tisperipheral(MAPT &pmap);\nextern\tbool\tisperipheral(MAPDHASH &phash);\n\nint\tget_longest_defname(APLIST *alist) {\n\t// {{{\n\tconst char DELIMITERS[] = \", \\t\\n\";\n\tunsigned\tlongest_defname = 0;\n\tSTRING\t\tstr;\n\n\tfor(unsigned i=0; i<alist->size(); i++) {\n\t\tMAPDHASH::iterator\tkvp;\n\t\tint\tnregs = 0;\n\t\tMAPDHASH\t*ph;\n\n\t\tph = (*alist)[i]->p_phash;\n\t\t/*\n\t\tif ((*alist)[i]->isbus()) {\n\t\t\tSUBBUS\t*sbp;\n\t\t\tsbp = (SUBBUS *)(*alist[i]);\n\t\t\tassert(sbp->p_slave_bus);\n\t\t\tassert(sbp->p_master_bus);\n\t\t\tif (!sbp->p_slave_bus->need_translator(sbp->p_master_bus)) {\n\t\t\t\tunsigned k = get_longest_defname(*sbp->p_master_bus->m_plist);\n\t\t\t\tif (k > longest_defname)\n\t\t\t\t\tlongest_defname = k;\n\t\t\t}\n\t\t}*/\n\n\n\t\tif (!getvalue(*ph, KYREGS_N, nregs))\n\t\t\tcontinue;\n\n\t\tfor(int j=0; j<nregs; j++) {\n\t\t\tchar\tnstr[32];\n\n\t\t\tsprintf(nstr, \"%d\", j);\n\t\t\tkvp = findkey(*ph,str=STRING(\"REGS.\")+nstr);\n\t\t\tif (kvp == ph->end()) {\n\t\t\t\tfprintf(stderr, \"%s not found\\n\", str.c_str());\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (kvp->second.m_typ != MAPT_STRING) {\n\t\t\t\tgbl_msg.info(\"%s is not a string\\n\", str.c_str());\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tSTRING\tscpy = *kvp->second.u.m_s;\n\n\t\t\tchar\t*nxtp, *rname;\n\n\t\t\t// 1. Read the number (Not used)\n\t\t\tstrtoul(scpy.c_str(), &nxtp, 0);\n\t\t\tif ((nxtp==NULL)||(nxtp == scpy.c_str())) {\n\t\t\t\tfprintf(stderr, \"No register name within string: %s\\n\", scpy.c_str());\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// 2. Get the C name\n\t\t\trname = strtok(nxtp, DELIMITERS);\n\t\t\tif (strlen(rname) > longest_defname)\n\t\t\t\tlongest_defname = strlen(rname);\n\t\t}\n\t}\n\n\treturn longest_defname;\n}\n// }}}\n\n//\n// write_regdefs\n// {{{\n// This writes out the definitions of all the registers found within the plist\n// to the C++ header file given by fp.  It takes as a parameter the longest\n// name definition, which we use to try to line things up in a prettier fashion\n// than we could without it.\n//\nvoid write_regdefs(FILE *fp, APLIST *alist, unsigned longest_defname) {\n\tconst char DELIMITERS[] = \", \\t\\n\";\n\tSTRING\tstr;\n\n\tgbl_msg.info(\"WRITE-REGDEFS\\n\");\n\t// Walk through this peripheral list one peripheral at a time\n\tfor(unsigned i=0; i<alist->size(); i++) {\n\t\tMAPDHASH::iterator\tkvp;\n\t\tint\tnregs = 0;\n\t\tMAPDHASH\t*ph;\n\t\tSTRINGP\t\tpname;\n\n\t\tph = (*alist)[i]->p_phash;\n\t\tpname = (*alist)[i]->p_name;\n\t\tgbl_msg.info(\"WRITE-REGDEFS(%d, %s)\\n\", i, (NULL != pname)?pname->c_str() : \"(No-name)\");\n\n\t\t// If there is a note key for this peripheral, place it into\n\t\t// the output without modifications.\n\t\tkvp = findkey(*ph,KYREGS_NOTE);\n\t\tif ((kvp != ph->end())&&(kvp->second.m_typ == MAPT_STRING))\n\t\t\tfprintf(fp, \"%s\\n\", kvp->second.u.m_s->c_str());\n\n\n\t\t// Walk through each of the defined registers.  There will be\n\t\t// @REGS.N registers defined.\n\t\tif (!getvalue(ph, KYREGS_N, nregs)) {\n\t\t\tgbl_msg.info(\"REGS.N not found in %s\\n\", pname->c_str());\n\t\t\tcontinue;\n\t\t}\n\n\t\tgbl_msg.info(\"Looking for REGS in %s\\n\", pname->c_str());\n\t\t// Now, walk through all of the register definitions\n\t\tfor(int j=0; j<nregs; j++) {\n\t\t\tchar\tnstr[32];\n\t\t\tSTRINGP\tstrp;\n\n\t\t\t// Look for a @REGS.%d tag, defining each of the named\n\t\t\t// registers within this set.\n\t\t\tsprintf(nstr, \"%d\", j);\n\t\t\tstrp = getstring(ph, str=STRING(\"REGS.\")+nstr);\n\t\t\tif (!strp) {\n\t\t\t\tfprintf(stderr, \"%s not found\\n\", str.c_str());\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tSTRING\tscpy = *strp;\n\n\t\t\tchar\t*nxtp, *rname, *rv;\n\n\t\t\t// 1. Read the number\n\t\t\tint roff = strtoul(scpy.c_str(), &nxtp, 0);\n\t\t\tif ((nxtp==NULL)||(nxtp == scpy.c_str())) {\n\t\t\t\tgbl_msg.info(\"No register name within string: %s\\n\", scpy.c_str());\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// 2. Get the C name\n\t\t\trname = strtok(nxtp, DELIMITERS);\n\t\t\tfprintf(fp, \"#define\\t%-*s\\t0x%08lx\", longest_defname,\n\t\t\t\trname, (roff<<2)+(*alist)[i]->p_regbase);\n\n\t\t\tfprintf(fp, \"\\t// %08lx, wbregs names: \", (*alist)[i]->p_regbase);\n\t\t\tint\tfirst = 1;\n\t\t\t// 3. Get the various user names\n\t\t\twhile(NULL != (rv = strtok(NULL, DELIMITERS))) {\n\t\t\t\tif (!first)\n\t\t\t\t\tfprintf(fp, \", \");\n\t\t\t\tfirst = 0;\n\t\t\t\tfprintf(fp, \"%s\", rv);\n\t\t\t} fprintf(fp, \"\\n\");\n\t\t}\n\t}\n\tfprintf(fp, \"\\n\\n\");\n}\n// }}}\n\n//\n// build_regdefs_h\n// {{{\n// This builds a regdefs.h file, a file that can be used on a host in order\n// to access our design.\n//\nvoid\tbuild_regdefs_h(  MAPDHASH &master, FILE *fp, STRING &fname) {\n\tMAPDHASH::iterator\tkvpair, kvaccess;\n\tSTRING\tstr;\n\tSTRINGP\tstrp;\n\tAPLIST\t*alist;\n\n\tlegal_notice(master, fp, fname);\n\n\tfprintf(fp, \"#ifndef\\tREGDEFS_H\\n\");\n\tfprintf(fp, \"#define\\tREGDEFS_H\\n\");\n\tfprintf(fp, \"\\n\\n\");\n\n\tfprintf(fp, \"//\\n\");\n\tfprintf(fp, \"// The @REGDEFS.H.INCLUDE tag\\n\");\n\tfprintf(fp, \"//\\n\");\n\tfprintf(fp, \"// @REGDEFS.H.INCLUDE for masters\\n\");\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tif (isperipheral(kvpair->second))\n\t\t\tcontinue;\n\t\tstrp = getstring(kvpair->second, KYREGDEFS_H_INCLUDE);\n\t\tif (strp)\n\t\t\tfputs(strp->c_str(), fp);\n\t}\n\n\tfprintf(fp, \"// @REGDEFS.H.INCLUDE for peripherals\\n\");\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tif (!isperipheral(kvpair->second))\n\t\t\tcontinue;\n\t\tstrp = getstring(kvpair->second, KYREGDEFS_H_INCLUDE);\n\t\tif (strp)\n\t\t\tfputs(strp->c_str(), fp);\n\t}\n\n\tfprintf(fp, \"// And finally any master REGDEFS.H.INCLUDE tags\\n\");\n\tstrp = getstring(master, KYREGDEFS_H_INCLUDE);\n\tif (strp)\n\t\tfputs(strp->c_str(), fp);\n\tfprintf(fp, \"// End of definitions from REGDEFS.H.INCLUDE\\n\\n\\n\");\n\n\n\tfprintf(fp, \"//\\n// Register address definitions, from @REGS.#d\\n//\\n\");\n\n\tunsigned\tlongest_defname = 0;\n\n\t// Get the list of all peripherals\n\talist = full_gather();\n\n\tlongest_defname = get_longest_defname(alist);\n\n\twrite_regdefs(fp, alist, longest_defname);\n\n\n\tfprintf(fp, \"//\\n\");\n\tfprintf(fp, \"// The @REGDEFS.H.DEFNS tag\\n\");\n\tfprintf(fp, \"//\\n\");\n\tfprintf(fp, \"// @REGDEFS.H.DEFNS for masters\\n\");\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tif (isperipheral(kvpair->second))\n\t\t\tcontinue;\n\t\tstrp = getstring(kvpair->second, KYREGDEFS_H_DEFNS);\n\t\tif (strp)\n\t\t\tfputs(strp->c_str(), fp);\n\t}\n\n\tfprintf(fp, \"// @REGDEFS.H.DEFNS for peripherals\\n\");\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tif (!isperipheral(kvpair->second))\n\t\t\tcontinue;\n\t\tstrp = getstring(kvpair->second, KYREGDEFS_H_DEFNS);\n\t\tif (strp)\n\t\t\tfputs(strp->c_str(), fp);\n\t}\n\n\tfprintf(fp, \"// @REGDEFS.H.DEFNS at the top level\\n\");\n\tstrp = getstring(master, KYREGDEFS_H_DEFNS);\n\tif (strp)\n\t\tfputs(strp->c_str(), fp);\n\tfprintf(fp, \"// End of definitions from REGDEFS.H.DEFNS\\n\");\n\n\n\n\tfprintf(fp, \"//\\n\");\n\tfprintf(fp, \"// The @REGDEFS.H.INSERT tag\\n\");\n\tfprintf(fp, \"//\\n\");\n\tfprintf(fp, \"// @REGDEFS.H.INSERT for masters\\n\");\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tif (isperipheral(kvpair->second))\n\t\t\tcontinue;\n\t\tstrp = getstring(kvpair->second, KYREGDEFS_H_INSERT);\n\t\tif (strp)\n\t\t\tfputs(strp->c_str(), fp);\n\t}\n\n\tfprintf(fp, \"// @REGDEFS.H.INSERT for peripherals\\n\");\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tif (!isperipheral(kvpair->second))\n\t\t\tcontinue;\n\t\tstrp = getstring(kvpair->second, KYREGDEFS_H_INSERT);\n\t\tif (strp)\n\t\t\tfputs(strp->c_str(), fp);\n\t}\n\n\tfprintf(fp, \"// @REGDEFS.H.INSERT from the top level\\n\");\n\tstrp = getstring(master, KYREGDEFS_H_INSERT);\n\tif (strp)\n\t\tfputs(strp->c_str(), fp);\n\tfprintf(fp, \"// End of definitions from REGDEFS.H.INSERT\\n\");\n\n\tfprintf(fp, \"\\n\\n\");\n\n\tfprintf(fp, \"#endif\\t// REGDEFS_H\\n\");\n}\n// }}}\n\n//\n// get_longest_uname\n// {{{\n// This is very similar to the get longest defname (get length of the longest\n// variable definition name) above, save that this is applied to the user\n// names within regdefs.cpp\n//\nunsigned\tget_longest_uname(APLIST *alist) {\n\tconst char DELIMITERS[] = \", \\t\\n\";\n\tunsigned\tlongest_uname = 0;\n\tSTRING\tstr;\n\tSTRINGP\tstrp;\n\n\tfor(unsigned i=0; i<alist->size(); i++) {\n\t\tMAPDHASH::iterator\tkvp;\n\t\tMAPDHASH\t*ph;\n\n\t\tph = (*alist)[i]->p_phash;\n\n\t\tint nregs = 0;\n\t\tif (!getvalue(*ph, KYREGS_N, nregs))\n\t\t\tcontinue;\n\n\t\tfor(int j=0; j<nregs; j++) {\n\t\t\tchar\tnstr[32];\n\t\t\tsprintf(nstr, \"%d\", j);\n\t\t\tstrp = getstring(*ph, str=STRING(\"REGS.\")+nstr);\n\n\t\t\tif (!strp)\n\t\t\t\tcontinue;\n\t\t\tSTRING\tscpy = *strp;\n\n\t\t\tchar\t*nxtp, *rv;\n\n\t\t\t// 1. Read the number\n\t\t\tstrtoul(scpy.c_str(), &nxtp, 0);\n\t\t\tif ((nxtp==NULL)||(nxtp == scpy.c_str())) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// 2. Get (and ignore) the C definition name\n\t\t\tstrtok(nxtp, DELIMITERS); // (Ignore first result)\n\n\t\t\t// 3. Every token that follows will be a user (string)\n\t\t\t// name.  Find the one of these with the longest length.\n\t\t\twhile(NULL != (rv = strtok(NULL, DELIMITERS))) {\n\t\t\t\tif (strlen(rv) > longest_uname)\n\t\t\t\t\tlongest_uname = strlen(rv);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn longest_uname;\n}\n// }}}\n\n//\n// write_regnames\n// {{{\n//\nvoid write_regnames(FILE *fp, APLIST *alist,\n\t\tunsigned longest_defname, unsigned longest_uname) {\n\tconst char DELIMITERS[] = \", \\t\\n\";\n\tSTRING\tstr;\n\tSTRINGP\tstrp;\n\tint\tfirst = 1;\n\n\tfor(unsigned i=0; i<alist->size(); i++) {\n\t\tint nregs = 0;\n\t\tMAPDHASH\t*ph;\n\n\t\tph = (*alist)[i]->p_phash;\n\n\t\tif (!getvalue(*ph, KYREGS_N, nregs))\n\t\t\tcontinue;\n\n\t\tfor(int j=0; j<nregs; j++) {\n\t\t\tchar\tnstr[32];\n\t\t\tsprintf(nstr, \"%d\", j);\n\t\t\tstrp = getstring(*ph,str=STRING(\"REGS.\")+nstr);\n\t\t\tif (!strp)\n\t\t\t\tcontinue;\n\t\t\tSTRING\tscpy = *strp;\n\t\t\tchar\t*nxtp, *rname, *rv;\n\n\t\t\t// 1. Read the number\n\t\t\tstrtoul(scpy.c_str(), &nxtp, 0);\n\t\t\tif ((nxtp==NULL)||(nxtp == scpy.c_str())) {\n\t\t\t\tgbl_msg.info(\"No register name within string: %s\\n\", scpy.c_str());\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// 2. Get the C name\n\t\t\trname = strtok(nxtp, DELIMITERS);\n\t\t\t// 3. Get the various user names and ... define them\n\t\t\twhile(NULL != (rv = strtok(NULL, DELIMITERS))) {\n\t\t\t\tif (!first)\n\t\t\t\t\tfprintf(fp, \",\\n\");\n\t\t\t\tfirst = 0;\n\t\t\t\tfprintf(fp, \"\\t{ %-*s,\\t\\\"%s\\\"%*s\\t}\",\n\t\t\t\t\tlongest_defname, rname, rv,\n\t\t\t\t\t(int)(longest_uname-strlen(rv)), \"\");\n\t\t\t}\n\t\t}\n\t}\n}\n// }}}\n\n//\n// build_regdefs_cpp\n// {{{\nvoid\tbuild_regdefs_cpp(MAPDHASH &master, FILE *fp, STRING &fname) {\n\tSTRINGP\tstrp;\n\tSTRING\tstr;\n\tAPLIST\t*alist;\n\n\tlegal_notice(master, fp, fname);\n\n\tif (NULL != (strp = getstring(master, KYREGDEFS_CPP_INCLUDE))) {\n\t\tfputs(strp->c_str(), fp);\n\t} else {\n\t\tfprintf(fp, \"// No default include list found\\n\");\n\t\tfprintf(fp, \"#include <stdio.h>\\n\");\n\t\tfprintf(fp, \"#include <stdlib.h>\\n\");\n\t\tfprintf(fp, \"#include <strings.h>\\n\");\n\t\tfprintf(fp, \"#include <ctype.h>\\n\");\n\t}\n\n\tfprintf(fp, \"#include \\\"regdefs.h\\\"\\n\\n\");\n\tfprintf(fp, \"const\\tREGNAME\\traw_bregs[] = {\\n\");\n\n\t// Get the list of peripherals\n\talist = full_gather();\n\n\t// First, find out how long our longest definition name is.\n\t// This will help to allow us to line things up later.\n\tunsigned\tlongest_defname = 0;\n\tunsigned\tlongest_uname = 0;\n\n\t// Find the length of the longest register name\n\tlongest_defname = get_longest_defname(alist);\n\n\t// Find the length of the longest user name string\n\tlongest_uname = get_longest_uname(alist);\n\n\twrite_regnames(fp, alist, longest_defname, longest_uname);\n\n\tfprintf(fp, \"\\n};\\n\\n\");\n\n\tfprintf(fp, \"// REGSDEFS.CPP.INSERT for any bus masters\\n\");\n\tfor(MAPDHASH::iterator kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tif (isperipheral(kvpair->second))\n\t\t\tcontinue;\n\t\tstrp = getstring(kvpair->second, KYREGDEFS_CPP_INSERT);\n\t\tif (strp)\n\t\t\tfputs(strp->c_str(), fp);\n\t}\n\n\tfprintf(fp, \"// And then from the peripherals\\n\");\n\tfor(MAPDHASH::iterator kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tif (!isperipheral(kvpair->second))\n\t\t\tcontinue;\n\t\tstrp = getstring(kvpair->second, KYREGDEFS_CPP_INSERT);\n\t\tif (strp)\n\t\t\tfputs(strp->c_str(), fp);\n\t}\n\n\tfprintf(fp, \"// And finally any master REGS.CPP.INSERT tags\\n\");\n\tif (NULL != (strp = getstring(master, KYREGDEFS_CPP_INSERT))) {\n\t\tfputs(strp->c_str(), fp);\n\t}\n}\n// }}}\n\n"
  },
  {
    "path": "sw/bldregdefs.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bldregdefs.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tTo build the regdefs.h and regdefs.cpp files.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tBLDREGDEFS_H\n#define\tBLDREGDEFS_H\n\n#include <stdio.h>\n\n#include \"mapdhash.h\"\n#include \"plist.h\"\n\nextern\tint\tget_longest_defname(PLIST &plist);\n\n//\n// write_regdefs\n//\n// This writes out the definitions of all the registers found within the plist\n// to the C++ header file given by fp.  It takes as a parameter the longest\n// name definition, which we use to try to line things up in a prettier fashion\n// than we could without it.\n//\nextern\tvoid write_regdefs(FILE *fp, PLIST &plist, unsigned longest_defname);\n\n//\n// build_regdefs_h\n//\n//\n// This builds a regdefs.h file, a file that can be used on a host in order\n// to access our design.\n//\nextern\tvoid\tbuild_regdefs_h(  MAPDHASH &master, FILE *fp, STRING &fname);\n\n//\n// get_longest_uname\n//\n// This is very similar to the get longest defname (get length of the longest\n// variable definition name) above, save that this is applied to the user\n// names within regdefs.cpp\n//\nextern\tunsigned\tget_longest_uname(PLIST &plist);\n\n//\n// write_regnames\n//\n//\nextern\tvoid write_regnames(FILE *fp, PLIST &plist,\n\t\tunsigned longest_defname, unsigned longest_uname);\n\n\n//\n// build_regdefs_cpp\n//\nextern\tvoid\tbuild_regdefs_cpp(MAPDHASH &master, FILE *fp, STRING &fname);\n\n#endif\t// BLDREGDEFS_H\n"
  },
  {
    "path": "sw/bldrtlmake.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bldrtlmake.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tTo draw the information from the master hash database out in\n//\t\tto create a Makefile for an rtl/ directory.\n//\n// Builds: rtl.make.inc, for include'ing in your rtl Makefile\n//\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <string.h>\n#include <unistd.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <limits.h>\n#include <ctype.h>\n\n#include \"parser.h\"\n#include \"keys.h\"\n#include \"kveval.h\"\n#include \"legalnotice.h\"\n#include \"bldtestb.h\"\n#include \"bldboardld.h\"\n#include \"bitlib.h\"\n#include \"plist.h\"\n#include \"bldregdefs.h\"\n#include \"ifdefs.h\"\n#include \"bldsim.h\"\n#include \"predicates.h\"\n#include \"businfo.h\"\n#include \"globals.h\"\n\nvoid\tbuild_rtl_make_inc(MAPDHASH &master, FILE *fp, STRING &fname) {\n\tMAPDHASH::iterator\tkvpair;\n\tSTRINGP\tmksubd, mkgroup, mkfiles;\n\tSTRING\tallgroups, vdirs;\n\tconst char *DELIMITERS=\", \\t\\r\\n\";\n\tstd::vector<STRINGP>\tsubdirs;\n\n\tlegal_notice(master, fp, fname,\n\t\t\"########################################\"\n\t\t\"########################################\", \"##\");\n\n\tfor(kvpair=master.begin(); kvpair!=master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tmksubd  = getstring(kvpair->second, KYRTL_MAKE_SUBD);\n\t\tmkgroup = getstring(kvpair->second, KYRTL_MAKE_GROUP);\n\t\tmkfiles = getstring(kvpair->second, KYRTL_MAKE_FILES);\n\n\t\tif (mksubd && mksubd->size() > 0) {\n\t\t\tbool\tprior_dir = false;\n\t\t\tfor(auto k : subdirs) {\n\t\t\t\tif (mksubd->compare(*k)==0) {\n\t\t\t\t\tprior_dir = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} if (!prior_dir)\n\t\t\t\tsubdirs.push_back(mksubd);\n\t\t}\n\n\t\tif (!mkfiles)\n\t\t\tcontinue;\n\n\t\tchar\t*tokstr = strdup(mkfiles->c_str()), *tok;\n\t\tSTRING\tfilstr = \"\";\n\n\t\ttok = strtok(tokstr, DELIMITERS);\n\t\twhile(NULL != tok) {\n\t\t\tfilstr += STRING(tok) + \" \";\n\t\t\ttok = strtok(NULL, DELIMITERS);\n\t\t} if (filstr[filstr.size()-1] == ' ')\n\t\t\tfilstr[filstr.size()-1] = '\\0';\n\t\tif (!mkgroup) {\n\t\t\tchar\ttemp[] = \"MKGRPXXXXXX\";\n\t\t\tmkstemp(temp);\n\t\t\tunlink(temp);\n\t\t\tmkgroup = new STRING(temp);\n\t\t\tsetstring(kvpair->second, KYRTL_MAKE_GROUP, mkgroup);\n\n\t\t\tSTRINGP pfx = getstring(kvpair->second.u.m_m, KYPREFIX);\n\t\t\tif (NULL == pfx)\n\t\t\t\tpfx = new STRING(\"(Unnamed)\");\n\n\t\t\tfprintf(stderr, \"WARNING: Creating a temporary group name for %s\\n\", pfx->c_str());\n\t\t}\n\t\tif (mksubd && mksubd->size() > 0) {\n\t\t\tfprintf(fp, \"%sD := %s\\n\", mkgroup->c_str(),\n\t\t\t\tmksubd->c_str());\n\t\t\tfprintf(fp, \"%s  := $(addprefix $(%sD)/,%s)\\n\",\n\t\t\t\tmkgroup->c_str(), mkgroup->c_str(),\n\t\t\t\tfilstr.c_str());\n\t\t} else {\n\t\t\tfprintf(fp, \"%s := %s\\n\\n\", mkgroup->c_str(), filstr.c_str());\n\t\t}\n\n\t\tSTRING\tmkgroupref = STRING(\"$(\")\n\t\t\t\t\t+ (*mkgroup)\n\t\t\t\t\t+ STRING(\")\");\n\t\tif (std::string::npos == allgroups.find(mkgroupref))\n\t\t\tallgroups = allgroups + STRING(\" \") + mkgroupref;\n\t\tfree(tokstr);\n\t}\n\n\tmksubd  = getstring(master, KYRTL_MAKE_SUBD);\n\tmkgroup  = getstring(master, KYRTL_MAKE_GROUP);\n\tif (NULL == mkgroup)\n\t\tmkgroup = new STRING(KYVFLIST);\n\tmkfiles = getstring(master, KYRTL_MAKE_FILES);\n\tmksubd  = getstring(master, KYRTL_MAKE_SUBD);\n\tif (NULL != mkfiles) {\n\t\tif (mksubd && mksubd->size() > 0) {\n\t\t\tfprintf(fp, \"%sD := %s\\n\", mkgroup->c_str(),\n\t\t\t\t\tmksubd->c_str());\n\t\t\tfprintf(fp, \"%s  := $(addprefix $(%sD)/,%s) \\\\\\t%s\\n\",\n\t\t\t\tmkgroup->c_str(), mkgroup->c_str(),\n\t\t\t\tmkfiles->c_str(), allgroups.c_str());\n\t\t} else {\n\t\t\tfprintf(fp, \"%s := %s //\\t\\t%s\\n\",\n\t\t\t\tmkgroup->c_str(), mkfiles->c_str(),\n\t\t\t\tallgroups.c_str());\n\t\t}\n\t} else if (allgroups.size() > 0) {\n\t\tfprintf(fp, \"%s := main.v %s\\n\", mkgroup->c_str(), allgroups.c_str());\n\t}\n\n\tif (mksubd && mksubd->size() > 0) {\n\t\tbool\tprior_dir = false;\n\t\tfor(auto k : subdirs) {\n\t\t\tif (mksubd->compare(*k)==0) {\n\t\t\t\tprior_dir = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!prior_dir)\n\t\t\tsubdirs.push_back(mksubd);\n\t}\n\n\tfor(auto k : subdirs)\n\t\tvdirs = vdirs + STRING(\" -y \") + (*k);\n\n\tmksubd = getstring(master, KYRTL_MAKE_VDIRS);\n\tif (NULL == mksubd)\n\t\tmksubd = new STRING(KYAUTOVDIRS);\n\tfprintf(fp, \"%s := %s\\n\", mksubd->c_str(), vdirs.c_str());\n}\n"
  },
  {
    "path": "sw/bldrtlmake.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bldrtlmake.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tTo draw the information from the master hash database out in\n//\t\tto create a Makefile for an rtl/ directory.\n//\n// Builds: rtl.make.inc, for include'ing in your rtl Makefile\n//\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tBLDRTLMAKE_H\n#define\tBLDRTLMAKE_H\n//\n#include <stdio.h>\n#include \"mapdhash.h\"\n\nvoid\tbuild_rtl_make_inc(MAPDHASH &master, FILE *fp, STRING &fname);\n\n#endif\n\n"
  },
  {
    "path": "sw/bldsim.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bldsim.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tBuilds a main_tb.cpp simulation file, which can then be called\n//\t\tfrom a master Verilator based simulation script.  The primary\n//\tfunction of the simulation class defined herein is tick(), which\n//\tadvances one of the clocks forward by one step while also simulating all\n//\tof the peripherals associated with that clock.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <string.h>\n#include <unistd.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <limits.h>\n#include <ctype.h>\n\n#include \"parser.h\"\n#include \"keys.h\"\n#include \"legalnotice.h\"\n#include \"bldtestb.h\"\n#include \"msgs.h\"\n\nextern\tvoid\twriteout(FILE *fp, MAPDHASH &master, const STRING &ky);\n\nbool\ttb_same_clock(MAPDHASH &info, STRINGP ckname) {\n\tMAPDHASH::iterator\tkvpair;\n\tSTRINGP\tsimclk;\n\n\tkvpair = findkey(info, KYSIM_CLOCK);\n\tif (info.end() != kvpair) {\n\t\tif (kvpair->second.m_typ == MAPT_MAP)\n\t\t\tkvpair = findkey(*kvpair->second.u.m_m, KY_NAME);\n\t\tif (info.end()== kvpair || kvpair->second.m_typ != MAPT_STRING)\n\t\t\treturn false;\n\t\tsimclk = kvpair->second.u.m_s;\n\t\treturn (NULL != simclk) && (ckname->compare(*simclk)==0);\n\t}\n\n\tkvpair = findkey(info, KYCLOCK_NAME);\n\tif (info.end() == kvpair || kvpair->second.m_typ != MAPT_STRING)\n\t\treturn false;\n\tsimclk = kvpair->second.u.m_s;\n\tif (NULL != simclk) {\n\t\tconst\tchar\tDELIMITERS[] = \" \\t\\n,\";\n\t\tchar\t*dstr, *tok;\n\t\tbool\tresult;\n\n\n\t\tdstr = strdup(simclk->c_str());\n\t\ttok = strtok(dstr, DELIMITERS);\n\t\tresult = (ckname->compare(tok)==0);\n\t\ttok = strtok(NULL, DELIMITERS);\n\t\tif (tok)\n\t\t\tresult = false;\n\t\tfree(dstr);\n\n\t\treturn result;\n\t}\n\n\treturn false;\n}\n\nbool\ttb_tick(MAPDHASH &info, STRINGP ckname, FILE *fp) {\n\tMAPDHASH::iterator\tkvpair;\n\tbool\tresult = false;\n\tconst STRING *ky = &KYSIM_TICK;\n\n\tif ((ckname)&&(fp))\n\t\tfprintf(fp, \"\\t\\t//\\n\\t\\t// SIM.TICK tags go here for SIM.CLOCK=%s\\n\\t\\t//\\n\", ckname->c_str());\n\telse if (fp)\n\t\tfprintf(fp, \"\\t\\t//\\n\\t\\t// SIM.TICK tags go here for the default clock\\n\\t\\t//\\n\");\n\n\tif (tb_same_clock(info, ckname)) {\n\t\tSTRINGP\ttick = getstring(info, *ky);\n\t\tif (tick) {\n\t\t\tif (fp) {\n\t\t\t\tfprintf(fp, \"\\t\\t// %s from master\\n\", ky->c_str());\n\t\t\t\tfprintf(fp, \"%s\", tick->c_str());\n\t\t\t}\n\t\t\tresult = true;\n\t\t}\n\t}\n\n\tfor(kvpair=info.begin(); kvpair!=info.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tMAPDHASH\t*p = kvpair->second.u.m_m;\n\t\tMAPDHASH::iterator\tckp;\n\t\tSTRINGP\ttick = getstring(*p, *ky);\n\n\t\tif (!tick)\n\t\t\tcontinue;\n\n\t\tckp = findkey(*p, KYSIM_CLOCK);\n\t\tif (p->end() == ckp)\n\t\t\tgbl_msg.warning(\"%s defines SIM.TICK, but not SIM.CLOCK\\n\",\n\t\t\t\tkvpair->first.c_str());\n\t\tif (!tb_same_clock(*p, ckname))\n\t\t\tcontinue;\n\t\tif (fp) {\n\t\t\tfprintf(fp, \"\\t\\t// %s from %s\\n\", ky->c_str(),\n\t\t\t\tkvpair->first.c_str());\n\t\t\tfprintf(fp, \"%s\", tick->c_str());\n\t\t}\n\t\tresult = true;\n\t}\n\n\tif ((fp)&&(!result))\n\t\tfprintf(fp, \"\\t\\t// No %s tags defined\\n\", ky->c_str());\n\treturn result;\n}\n\nbool\ttb_dbg_condition(MAPDHASH &info, STRINGP ckname, FILE *fp) {\n\tMAPDHASH::iterator\tkvpair;\n\tbool\tresult = true;\n\tconst STRING *ky = &KYSIM_DBGCONDITION;\n\n\tif (fp) fprintf(fp, \"\\t\\t//\\n\\t\\t// SIM.DBGCONDITION\\n\"\n\t\t\"\\t\\t// Set writeout to true here for debug by printf access\\n\"\n\t\t\"\\t\\t// to this routine\\n\"\n\t\t\"\\t\\t//\\n\");\n\n\tif (tb_same_clock(info, ckname)) {\n\t\tSTRINGP\ttick = getstring(info, *ky);\n\t\tif (tick) {\n\t\t\tif (fp) {\n\t\t\t\tfprintf(fp, \"\\t\\t// %s from master\\n\", ky->c_str());\n\t\t\t\tfprintf(fp, \"%s\", tick->c_str());\n\t\t\t}\n\t\t\tresult= true;\n\t\t}\n\t}\n\n\tfor(kvpair=info.begin(); kvpair!=info.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tMAPDHASH\t*p = kvpair->second.u.m_m;\n\t\tSTRINGP\ttick = getstring(*p, *ky);\n\t\tif (!tick)\n\t\t\tcontinue;\n\t\tif (NULL == getstring(*p, KYSIM_CLOCK))\n\t\t\tgbl_msg.warning(\"%s defines SIM.DBGCONDITION, but not SIM.CLOCK\\n\",\n\t\t\t\tkvpair->first.c_str());\n\t\tif (!tb_same_clock(*p, ckname))\n\t\t\tcontinue;\n\t\tif (fp) {\n\t\t\tfprintf(fp, \"%s\", tick->c_str());\n\t\t} result = true;\n\t}\n\n\tif ((fp)&&(!result))\n\t\tfprintf(fp, \"\\t\\t// No %s tags defined\\n\", ky->c_str());\n\n\treturn result;\n}\n\nbool\ttb_debug(MAPDHASH &info, STRINGP ckname, FILE *fp) {\n\tMAPDHASH::iterator\tkvpair;\n\tbool\tresult = false;\n\tconst STRING *ky = &KYSIM_DEBUG;\n\n\tif (fp)\n\t\tfprintf(fp, \"\\t\\t\\t//\\n\\t\\t\\t// SIM.DEBUG tags can print here, supporting\\n\"\n\t\t\t\"\\t\\t\\t// any attempts to debug by printf.  Following any\\n\"\n\t\t\t\"\\t\\t\\t// code you place here, a newline will close the\\n\"\n\t\t\t\"\\t\\t\\t// debug section.\\n\"\n\t\t\t\"\\t\\t\\t//\\n\");\n\tif (tb_same_clock(info, ckname)) {\n\t\tSTRINGP\ttick = getstring(info, *ky);\n\t\tif (tick) {\n\t\t\tif (fp) {\n\t\t\t\tfprintf(fp, \"\\t\\t\\t// %s from master\\n\", ky->c_str());\n\t\t\t\tfprintf(fp, \"%s\", tick->c_str());\n\t\t\t}\n\t\t\tresult = true;\n\t\t}\n\t}\n\n\tfor(kvpair=info.begin(); kvpair!=info.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tMAPDHASH\t*p = kvpair->second.u.m_m;\n\t\tSTRINGP\ttick = getstring(*p, KYSIM_DEBUG);\n\n\t\tif (!tick)\n\t\t\tcontinue;\n\t\tif (NULL == getstring(*p, KYSIM_CLOCK))\n\t\t\tgbl_msg.warning(\"%s defines SIM.DEBUG, but not SIM.CLOCK\\n\",\n\t\t\t\tkvpair->first.c_str());\n\t\tif (!tb_same_clock(*p, ckname))\n\t\t\tcontinue;\n\t\tif (fp) {\n\t\t\tfprintf(fp, \"\\t\\t\\t//    %s from %s\\n\",\n\t\t\t\tky->c_str(),\n\t\t\t\tkvpair->first.c_str());\n\t\t\tfprintf(fp, \"%s\", tick->c_str());\n\t\t}\n\t\tresult = true;\n\t}\n\n\tif ((fp)&&(!result))\n\t\tfprintf(fp, \"\\t\\t\\t// No %s tags defined\\n\", ky->c_str());\n\treturn result;\n}\n\nvoid\tbuild_main_tb_cpp(MAPDHASH &master, FILE *fp, STRING &fname) {\n\tMAPDHASH::iterator\tkvpair;\n\tSTRINGP\t\t\tstr;\n\n\tlegal_notice(master, fp, fname);\n\n\tfprintf(fp, \"//\\n// SIM.INCLUDE\\n//\\n\");\n\tfprintf(fp, \"// Any SIM.INCLUDE tags you define will be pasted here.\\n\");\n\tfprintf(fp, \"// This is useful for guaranteeing any include functions\\n\");\n\tfprintf(fp, \"// your simulation needs are called.\\n//\\n\");\n\twriteout(fp, master, KYSIM_INCLUDE);\n\tfprintf(fp, \"//\\n// SIM.DEFINES\\n//\\n\");\n\tfprintf(fp, \"// This tag is useful fr pasting in any #define values that\\n\");\n\tfprintf(fp, \"// might then control the simulation following.\\n//\\n\");\n\twriteout(fp, master, KYSIM_DEFINES);\n\n\t// Class definitions\n\tfprintf(fp, \"class\\tMAINTB : public TESTB<Vmain> {\\npublic:\\n\");\n\tfprintf(fp, \"\\t\\t// SIM.DEFNS\\n\\t\\t//\\n\");\n\tfprintf(fp, \"\\t\\t// If you have any simulation components, create a\\n\");\n\tfprintf(fp, \"\\t\\t// SIM.DEFNS tag to have those components defined here\\n\");\n\tfprintf(fp, \"\\t\\t// as part of the main_tb.cpp function.\\n\");\n\twriteout(fp, master, KYSIM_DEFNS);\n\n\n\tfprintf(fp, \"\\tMAINTB(void) {\\n\");\n/*\n\t// Pre-Initial stuffs ....\n\t{\n\t\tbool\thave_initial = false;\n\n\t\tstr = getstring(master, KYSIM_PREINITIAL);\n\t\tif (NULL != str) {\n\t\t\tfprintf(fp, \":\\n%s\", str->c_str());\n\t\t\thave_initial = true;\n\t\t}\n\n\t\tfor(kvpair = master.begin(); kvpair != master.end(); kvpair++) {\n\t\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\t\tcontinue;\n\t\t\tstr = getstring(kvpair->second, KYSIM_PREINITIAL);\n\t\t\tif (str == NULL)\n\t\t\t\tcontinue;\n\n\t\t\tif (!have_initial)\n\t\t\t\tfprintf(fp, \":\\n\");\n\t\t\telse\tfprintf(fp, \",\\n\");\n\t\t\thave_initial = true;\n\t\t\tfprintf(fp, \"\\t// From %s\\n%s\", kvpair->first.c_str(),\n\t\t\t\tstr->c_str());\n\t\t}\n\t} fprintf(fp, \"\\t{\\n\");\n*/\n\n\tfprintf(fp, \"\\t\\t// SIM.INIT\\n\\t\\t//\\n\");\n\tfprintf(fp, \"\\t\\t// If your simulation components need to be initialized,\\n\");\n\tfprintf(fp, \"\\t\\t// create a SIM.INIT tag.  That tag\\'s value will be pasted\\n\");\n\tfprintf(fp, \"\\t\\t// here.\\n\\t\\t//\\n\");\n\tstr = getstring(master, KYSIM_INIT);\n\tif (NULL != str) {\n\t\tfprintf(fp, \"\\t%s\", str->c_str());\n\t}\n\n\tfor(kvpair = master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\t\tcontinue;\n\t\tstr = getstring(kvpair->second, KYSIM_INIT);\n\t\tif (str == NULL)\n\t\t\tcontinue;\n\n\t\tfprintf(fp, \"\\t\\t// From %s\\n%s\", kvpair->first.c_str(),\n\t\t\tstr->c_str());\n\t}\n\n\tfprintf(fp, \"\\t}\\n\\n\");\n\n\tfprintf(fp, \"\\tvoid\\treset(void) {\\n\"\n\t\t\"\\t\\t// SIM.SETRESET\\n\"\n\t\t\"\\t\\t// If your simulation component needs logic before the\\n\"\n\t\t\"\\t\\t// tick with reset set, that logic can be placed into\\n\"\n\t\t\"\\t\\t// the SIM.SETRESET tag and thus pasted here.\\n\"\n\t\t\"\\t\\t//\\n\");\n\n\twriteout(fp, master, KYSIM_SETRESET);\n\n\tfprintf(fp, \"\\t\\tTESTB<Vmain>::reset();\\n\");\n\n\tfprintf(fp,\n\t\t\"\\t\\t// SIM.CLRRESET\\n\"\n\t\t\"\\t\\t// If your simulation component needs logic following the\\n\"\n\t\t\"\\t\\t// reset tick, that logic can be placed into the\\n\"\n\t\t\"\\t\\t// SIM.CLRRESET tag and thus pasted here.\\n\"\n\t\t\"\\t\\t//\\n\");\n\twriteout(fp, master, KYSIM_CLRRESET);\n\n\tfprintf(fp, \"\\t}\\n\");\n\n\tfprintf(fp, \"\\n\"\n\"\\tvoid\ttrace(const char *vcd_trace_file_name) {\\n\"\n\"\\t\\tfprintf(stderr, \\\"Opening TRACE(%%s)\\\\n\\\",\\n\"\n\"\\t\\t\t\tvcd_trace_file_name);\\n\"\n\"\\t\\topentrace(vcd_trace_file_name);\\n\"\n\"\\t\\tm_time_ps = 0;\\n\"\n\"\\t}\\n\\n\");\n\n\tfprintf(fp,\n\"\tvoid\tclose(void) {\\n\"\n\"\t\tm_done = true;\\n\"\n\"\t}\\n\\n\");\n\n\tfprintf(fp,\n\"\tvoid\ttick(void) {\\n\");\n\tfprintf(fp, \"\\t\\tTESTB<Vmain>::tick(); // Clock.size = %ld\\n\\t}\\n\\n\", cklist.size());\n\n\tfor(unsigned i=0; i<cklist.size(); i++) {\n\t\tbool\thave_sim_tick = false, have_debug = false,\n\t\t\thave_condition = false;\n\n\t\tfprintf(fp, \"\\n\\t// Evaluating clock %s\\n\",\n\t\t\t\tcklist[i].m_name->c_str());\n\t\thave_debug = tb_debug(master, cklist[i].m_name, NULL);\n\t\thave_condition = tb_dbg_condition(master,\n\t\t\t\t\t\tcklist[i].m_name, NULL);\n\t\thave_sim_tick = tb_tick(master, cklist[i].m_name, NULL);\n\n\t\tif ((!have_sim_tick)&&(!have_condition)&&(!have_debug))\n\t\t\tcontinue;\n\n\n\t\tfprintf(fp, \"\\n\\t// sim_%s_tick() will be called from\"\n\t\t\t\t\" TESTB<Vmain>::tick()\\n\"\n\t\t\t\t\"\\t//   following any falling edge of clock \"\n\t\t\t\t\"%s\\n\",\n\t\t\t\tcklist[i].m_name->c_str(),\n\t\t\t\tcklist[i].m_name->c_str());\n\t\tfprintf(fp, \"\\tvirtual\\tvoid\\tsim_%s_tick(void) {\\n\",\n\t\t\tcklist[i].m_name->c_str());\n\t\tif (0 == i)\n\t\t\tfprintf(fp, \"\\t\\t// Default clock tick\\n\");\n\n\t\tif ((have_debug)&&(have_condition))\n\t\t\tfprintf(fp, \"\\t\\tbool\\twriteout;\\n\\n\");\n\t\ttb_tick(master, cklist[i].m_name, fp);\n\t\tif (!have_sim_tick)\n\t\t\tfprintf(fp, \"\\t\\tm_changed = false;\\n\");\n\n\t\tif ((have_debug)&&(have_condition)) {\n\t\t\tfprintf(fp, \"\\t\\twriteout = false;\\n\");\n\n\t\t\ttb_dbg_condition(master, cklist[i].m_name, fp);\n\n\t\t\tfprintf(fp, \"\\t\\tif (writeout) {\\n\");\n\t\t\ttb_debug(master, cklist[i].m_name, fp);\n\t\t\tfprintf(fp, \"\\t\\t}\\n\");\n\t\t}\n\t\tfprintf(fp, \"\\t}\\n\");\n\t}\n\n\tif (cklist.size()>1) {\n\t\tfor(unsigned i=0; i<cklist.size(); i++) {\n\t\t\tfprintf(fp, \"\\t//\\n\\t// Step until clock %s ticks\\n\\t//\\n\",\n\t\t\t\tcklist[i].m_name->c_str());\n\n\t\t\tfprintf(fp, \"\\tvirtual\\tvoid\\ttick_%s(void) {\\n\",\n\t\t\t\tcklist[i].m_name->c_str());\n\t\t\tif (0 == i)\n\t\t\t\tfprintf(fp, \"\\t\\t// Advance until the default clock ticks\\n\");\n\n\t\t\tfprintf(fp, \"\\t\\tdo {\\n\"\n\t\t\t\t\"\\t\\t\\ttick();\\n\"\n\t\t\t\t\"\\t\\t} while(!m_%s.rising_edge());\\n\",\n\t\t\t\tcklist[i].m_name->c_str());\n\n\t\t\tfprintf(fp, \"\\t}\\n\\n\");\n\t\t}\n\t} else {\n\t\tfprintf(fp,\n\t\t\t\"\\tinline\\tvoid\\ttick_%s(void) {\\ttick();\\t}\\n\\n\",\n\t\t\tcklist[0].m_name->c_str());\n\t}\n\n\tfprintf(fp, \"\\t//\\n\\t// The load function\\n\"\n\t\t\"\\t//\\n\"\n\t\t\"\\t// This function is required by designs that need the flash or memory\\n\"\n\t\t\"\\t// set prior to run time.  The test harness should be able to call\\n\"\n\t\t\"\\t// this function to load values into any (memory-type) location\\n\"\n\t\t\"\\t// on the bus.\\n\"\n\t\t\"\\t//\\n\"\n\t\t\"\\tbool\\tload(uint32_t addr, const char *buf, uint32_t len) {\\n\");\n\tSTRING\tprestr = STRING(\"\\t\\tuint32_t\\tstart, offset, wlen, base, adrln;\\n\\n\");\n\n\tfor(kvpair = master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\t\tcontinue;\n\t\tMAPDHASH *dev = kvpair->second.u.m_m, *bus;\n\t\tint\tbase, naddr, dw;\n\t\tSTRINGP\taccessp;\n\t\tconst\tchar *accessptr;\n\n\t\tstr = getstring(kvpair->second, KYSIM_LOAD);\n\t\tif (str == NULL)\n\t\t\tcontinue;\n\t\tif (!getvalue(*dev, KYREGBASE, base))\n\t\t\tcontinue;\n\t\tif (!getvalue(*dev, KYNADDR, naddr))\n\t\t\tcontinue;\n\t\tif (NULL == (bus = getmap(*dev, KYSLAVE_BUS))) {\n\t\t\tgbl_msg.error(\"No map found for %s\\n\", kvpair->first.c_str());\n\t\t\tcontinue;\n\t\t} if (!getvalue(*bus, KY_WIDTH, dw)) {\n\t\t\tgbl_msg.error(\"No bus width found for %s\\n\", kvpair->first.c_str());\n\t\t\tcontinue;\n\t\t} accessp = getstring(*dev, KYACCESS);\n\n\t\tif (prestr[0]) {\n\t\t\tfprintf(fp, \"%s\", prestr.c_str());\n\t\t\tprestr[0] = '\\0';\n\t\t}\n\n\t\tfprintf(fp, \"\\t\\t//\\n\\t\\t// Loading the %s component\\n\\t\\t//\\n\",\n\t\t\tkvpair->first.c_str());\n\t\tfprintf(fp, \"\\t\\tbase  = 0x%08x; // in octets\\n\"\n\t\t\t\t\"\\t\\tadrln = 0x%08x;\\n\\n\",\n\t\t\tbase, naddr * (dw/8));\n\t\tfprintf(fp, \"\\t\\tif ((addr >= base)&&(addr < base + adrln)) {\\n\");\n\t\tfprintf(fp, \"\\t\\t\\t// If the start access is in %s\\n\", kvpair->first.c_str());\n\t\tfprintf(fp, \"\\t\\t\\tstart = (addr > base) ? (addr-base) : 0;\\n\");\n\t\tfprintf(fp, \"\\t\\t\\toffset = (start + base) - addr;\\n\");\n\t\tfprintf(fp, \"\\t\\t\\twlen = (len-offset > adrln - start)\\n\\t\\t\\t\\t? (adrln - start) : len - offset;\\n\");\n\n\n\t\tif (accessp) {\n\t\t\taccessptr = accessp->c_str();\n\t\t\tif (accessptr[0] == '!')\n\t\t\t\taccessptr++;\n\t\t\tfprintf(fp, \"#ifdef\\t%s\\n\", accessptr);\n\t\t} else accessptr = NULL;\n\t\tfprintf(fp, \"\\t\\t\\t// FROM %s.%s\\n\", kvpair->first.c_str(), KYSIM_LOAD.c_str());\n\t\tfprintf(fp, \"%s\", str->c_str());\n\t\tfprintf(fp, \"\\t\\t\\t// AUTOFPGA::Now clean up anything else\\n\");\n\t\tfprintf(fp, \"\\t\\t\\t// Was there more to write than we wrote?\\n\");\n\t\tfprintf(fp, \"\\t\\t\\tif (addr + len > base + adrln)\\n\");\n\t\tfprintf(fp, \"\\t\\t\\t\\treturn load(base + adrln, &buf[offset+wlen], len-wlen);\\n\");\n\t\tfprintf(fp, \"\\t\\t\\treturn true;\\n\");\n\t\tif (accessp) {\n\t\t\tfprintf(fp, \"#else\\t// %s\\n\", accessptr);\n\t\t\tfprintf(fp, \"\\t\\t\\treturn false;\\n\");\n\t\t\tfprintf(fp, \"#endif\\t// %s\\n\", accessptr);\n\t\t}\n\n\t\tfprintf(fp, \"\\t\\t//\\n\"\n\t\t\t\"\\t\\t// End of components with a SIM.LOAD tag, and a\\n\"\n\t\t\t\"\\t\\t// non-zero number of addresses (NADDR)\\n\"\n\t\t\t\"\\t\\t//\\n\");\n\t\tfprintf(fp, \"\\t\\t}\\n\\n\");\n\t}\n\tfprintf(fp, \"\\t\\treturn false;\\n\");\n\tfprintf(fp, \"\\t}\\n\\n\");\n\n\tfprintf(fp, \"\\t//\\n\\t// KYSIM.METHODS\\n\\t//\\n\"\n\t\t\"\\t// If your simulation code will need to call any of its own function\\n\"\n\t\t\"\\t// define this tag by those functions (or other sim code), and\\n\"\n\t\t\"\\t// it will be pasated here.\\n\"\n\t\t\"\\t//\\n\");\n\twriteout(fp, master, KYSIM_METHODS);\n\n\tfprintf(fp, \"\\n};\\n\");\n}\n\n"
  },
  {
    "path": "sw/bldsim.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bldsim.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tTo build the main_tb.cpp file.\n//\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tBLDSIM_H\n#define\tBLDSIM_H\n\n#include <stdio.h>\n#include <string>\n\n#include \"parser.h\"\n\nextern\tvoid\twriteout(FILE *fp, MAPDHASH &master, const STRING &ky);\nextern\tbool\ttb_same_clock(MAPDHASH &info, STRINGP ckname);\nextern\tbool\ttb_tick(MAPDHASH &info, STRINGP ckname, FILE *fp);\nextern\tvoid\ttb_dbg_condition(MAPDHASH &info, STRINGP ckname, FILE *fp);\nextern\tvoid\ttb_debug(MAPDHASH &info, STRINGP ckname, FILE *fp);\nextern\tvoid\tbuild_main_tb_cpp(MAPDHASH &master, FILE *fp, STRING &fname) ;\n\n#endif\n"
  },
  {
    "path": "sw/bldtestb.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bldtestb.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tTo build a test framework that can be used with Verilator for\n//\t\thandling multiple clocks.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdio.h>\n#include <stdlib.h>\n#include <vector>\n#include \"parser.h\"\n#include \"mapdhash.h\"\n#include \"keys.h\"\n#include \"bldtestb.h\"\n#include \"legalnotice.h\"\n#include \"clockinfo.h\"\n\nvoid\tbuild_testb_h(MAPDHASH &master, FILE *fp, STRING &fname) {\n\tbool\tmulticlock = false;\n\t// Find all the clocks in the design, and categorize them\n\tfind_clocks(master);\n\n\tlegal_notice(master, fp, fname);\n\n\tfprintf(fp, \"\"\n\"#ifndef\tTESTB_H\\n\"\n\"#define\tTESTB_H\\n\"\n\"\\n\"\n\"// #define TRACE_FST\\n\"\n\"\\n\"\n\"#include <stdio.h>\\n\"\n\"#include <stdint.h>\\n\"\n\"#ifdef\tTRACE_FST\\n\"\n\"#define\\tTRACECLASS\\tVerilatedFstC\\n\"\n\"#include <verilated_fst_c.h>\\n\"\n\"#else // TRACE_FST\\n\"\n\"#define\\tTRACECLASS\\tVerilatedVcdC\\n\"\n\"#include <verilated_vcd_c.h>\\n\"\n\"#endif\\n\");\n\n\tif (cklist.size() == 0) {\n\t\tfprintf(stderr, \"ERR: No clocks defined!\\n\");\n\t\texit(EXIT_FAILURE);\n\t}\n\n\tif (cklist.size() > 1)\n\t\tmulticlock = true;\n\telse if (cklist[0].m_simclass != NULL)\n\t\tmulticlock = true;\n\telse\n\t\tmulticlock = false;\n\tif (multiclock)\n\t\tfprintf(fp, \"#include <tbclock.h>\\n\");\n\n\tfprintf(fp, \"\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// The TESTB class is a useful wrapper for interacting with a Verilator\\n\"\n\t\"\\t// based design.  Key to its capabilities are the tick() method for\\n\"\n\t\"\\t// advancing the simulation timestep, and the opentrace() and\\n\"\n\t\"\\t// closetrace() methods for handling VCD tracefile generation.  To\\n\"\n\t\"\\t// use a non-VCD trace, redefine TRACECLASS before calling this\\n\"\n\t\"\\t// function to the trace class you wish to use.\\n//\\n\"\n\"template <class VA>\tclass TESTB {\\n\"\n\"public:\\n\"\n\"\tVA\t*m_core;\\n\"\n\"\tbool\t\tm_changed;\\n\"\n\"\tTRACECLASS*\tm_trace;\\n\"\n\"\tbool\t\tm_done, m_paused_trace;\\n\"\n\"\tuint64_t\tm_time_ps;\\n\");\n\n\tif (multiclock) {\n\t\tfprintf(fp, \"\\t// TBCLOCK is a clock support class, enabling\"\n\t\t\t\t\" multiclock simulation\\n\\t// operation.\\n\");\n\t\tfor(unsigned i=0; i<cklist.size(); i++)\n\t\t\tfprintf(fp, \"\\t%s\\tm_%s;\\n\",\n\t\t\t\t(cklist[i].m_simclass)\n\t\t\t\t\t? cklist[i].m_simclass->c_str()\n\t\t\t\t\t: \"TBCLOCK\",\n\t\t\t\tcklist[i].m_name->c_str());\n\t} else {\n\t\tfprintf(fp, \"\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// Since design has only one clock within it, we won't need to use the\\n\"\n\t\"\\t// multiclock techniques, and so those aren't included here at this time.\\n\"\n\t\"\\t//\\n\");\n\t}\n\n\tfprintf(fp, \"\\n\"\n\"\tTESTB(void) {\\n\"\n\"\t\t// {{{\\n\"\n\"\t\tm_core = new VA;\\n\"\n\"\t\tm_time_ps  = 0ul;\\n\"\n\"\t\tm_trace    = NULL;\\n\"\n\"\t\tm_done     = false;\\n\"\n\"\t\tm_paused_trace = false;\\n\"\n\"\t\tVerilated::traceEverOn(true);\\n\");\n\n\tif (multiclock) {\n\t\tfprintf(fp, \"// Set the initial clock periods\\n\");\n\t\tfor(unsigned i=0; i<cklist.size(); i++) {\n\t\t\tdouble\tfreq;\n\t\t\tfprintf(fp, \"\\t\\tm_%s.init(%ld);\",\n\t\t\t\tcklist[i].m_name->c_str(),\n\t\t\t\tcklist[i].interval_ps());\n\t\t\tfreq = 1e6 / cklist[i].interval_ps();\n\t\t\tfprintf(fp, \"\\t//%8.2f MHz\\n\", freq);\n\t\t}\n\t}\n\n\tfprintf(fp,\n\"\t}\\n\"\n\"\t// }}}\\n\"\n\"\\n\"\n\"\tvirtual ~TESTB(void) {\\n\"\n\"\t\t// {{{\\n\"\n\"\t\tif (m_trace) m_trace->close();\\n\"\n\"\t\tdelete m_core;\\n\"\n\"\t\tm_core = NULL;\\n\"\n\"\t}\\n\"\n\"\t// }}}\\n\"\n\"\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// opentrace()\\n\"\n\t\"\\t// {{{\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// Useful for beginning a (VCD) trace.  To open such a trace, just call\\n\"\n\t\"\\t// opentrace() with the name of the VCD file you'd like to trace\\n\"\n\t\"\\t// everything into\\n\"\n\"\tvirtual\tvoid\topentrace(const char *vcdname, int depth=99) {\\n\"\n\"\t\tif (!m_trace) {\\n\"\n\"\t\t\tm_trace = new TRACECLASS;\\n\"\n\"\t\t\tm_core->trace(m_trace, 99);\\n\"\n\"\t\t\tm_trace->spTrace()->set_time_resolution(\\\"ps\\\");\\n\"\n\"\t\t\tm_trace->spTrace()->set_time_unit(\\\"ps\\\");\\n\"\n\"\t\t\tm_trace->open(vcdname);\\n\"\n\"\t\t\tm_paused_trace = false;\\n\"\n\"\t\t}\\n\"\n\"\t}\\n\"\n\t\"\\t// }}}\\n\"\n\"\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// trace()\\n\"\n\t\"\\t// {{{\\n\"\n\t\"\\t// A synonym for opentrace() above.\\n\"\n\t\"\\t//\\n\"\n\"\tvoid\ttrace(const char *vcdname) {\\n\"\n\"\t\topentrace(vcdname);\\n\"\n\"\t}\\n\"\n\t\"\\t// }}}\\n\"\n\"\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// pausetrace(pause)\\n\"\n\t\"\\t// {{{\\n\"\n\t\"\\t// Set/clear a flag telling us whether or not to write to the VCD trace\\n\"\n\t\"\\t// file.  The default is to write to the file, but this can be changed\\n\"\n\t\"\\t// by calling pausetrace.  pausetrace(false) will resume tracing,\\n\"\n\t\"\\t// whereas pausetrace(true) will stop all calls to Verilator's trace()\\n\"\n\t\"\\t// function\\n\"\n\t\"\\t//\\n\"\n\"\tvirtual\tbool\tpausetrace(bool pausetrace) {\\n\"\n\"\t\tm_paused_trace = pausetrace;\\n\"\n\"\t\treturn m_paused_trace;\\n\"\n\"\t}\\n\"\n\t\"\\t// }}}\\n\"\n\"\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// pausetrace()\\n\"\n\t\"\\t// {{{\\n\"\n\t\"\\t// Like pausetrace(bool) above, except that pausetrace() will return\\n\"\n\t\"\\t// the current status of the pausetrace flag above.  Specifically, it\\n\"\n\t\"\\t// will return true if the trace has been paused or false otherwise.\\n\"\n\"\tvirtual\tbool\tpausetrace(void) {\\n\"\n\"\t\treturn m_paused_trace;\\n\"\n\"\t}\\n\"\n\t\"\\t// }}}\\n\"\n\"\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// closetrace()\\n\"\n\t\"\\t// {{{\\n\"\n\t\"\\t// Closes the open trace file.  No more information will be written\\n\"\n\t\"\\t// to it\\n\"\n\"\tvirtual\tvoid\tclosetrace(void) {\\n\"\n\"\t\tif (m_trace) {\\n\"\n\"\t\t\tm_trace->close();\\n\"\n\"\t\t\tdelete m_trace;\\n\"\n\"\t\t\tm_trace = NULL;\\n\"\n\"\t\t}\\n\"\n\"\t}\\n\"\n\t\"\\t// }}}\\n\"\n\"\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// eval()\\n\"\n\t\"\\t// {{{\\n\"\n\t\"\\t// This is a synonym for Verilator's eval() function.  It evaluates all\\n\"\n\t\"\\t// of the logic within the design.  AutoFPGA based designs shouldn't\\n\"\n\t\"\\t// need to be calling this, they should call tick() instead.  However,\\n\"\n\t\"\\t// in the off chance that your design inputs depend upon combinatorial\\n\"\n\t\"\\t// expressions that would be output based upon other input expressions,\\n\"\n\t\"\\t// you might need to call this function.\\n\"\n\"\tvirtual\tvoid\teval(void) {\\n\"\n\"\t\tm_core->eval();\\n\"\n\"\t}\\n\"\n\t\"\\t// }}}\\n\"\n\"\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// tick()\\n\"\n\t\"\\t// {{{\\n\"\n\t\"\\t// tick() is the main entry point into this helper core.  In general,\\n\"\n\t\"\\t// tick() will advance the clock by one clock tick.  In a multiple clock\\n\"\n\t\"\\t// design, this will advance the clocks up until the nearest clock\\n\"\n\t\"\\t// transition.\\n\"\n\"\tvirtual\tvoid\ttick(void) {\\n\");\n\n\tif (multiclock) {\n\t\tfprintf(fp, \"\"\n\t\t\t\"\\t\\tunsigned\tmintime = m_%s.time_to_edge();\\n\\n\",\n\t\t\t\tcklist[0].m_name->c_str());\n\n\t\tfor(unsigned i=1; i<cklist.size(); i++)\n\t\t\tfprintf(fp, \"\"\n\t\t\t\t\"\\t\\tif (m_%s.time_to_edge() < mintime)\\n\"\n\t\t\t\t\"\\t\\t\\tmintime = m_%s.time_to_edge();\\n\\n\",\n\t\t\t\tcklist[i].m_name->c_str(),\n\t\t\t\tcklist[i].m_name->c_str());\n\n\t\tfprintf(fp, \"\\t\\tassert(mintime > 1);\\n\\n\");\n\n\t\tfprintf(fp, \"\\t\\t// Pre-evaluate, to give verilator a chance\"\n\t\t\t\" to settle any\\n\\t\\t// combinatorial logic that\"\n\t\t\t\"that may have changed since the\\n\\t\\t// last clock\"\n\t\t\t\"evaluation, and then record that in the trace.\\n\");\n\t\tfprintf(fp, \"\\t\\teval();\\n\"\n\t\t\t\"\\t\\tif (m_trace && !m_paused_trace) m_trace->dump(m_time_ps+1);\\n\\n\");\n\n\t\tfprintf(fp, \"\\t\\t// Advance each clock\\n\");\n\t\tfor(unsigned i=0; i<cklist.size(); i++)\n\t\t\tfprintf(fp, \"\\t\\tm_core->%s = m_%s.advance(mintime);\\n\",\n\t\t\t\tcklist[i].m_wire->c_str(),\n\t\t\t\tcklist[i].m_name->c_str());\n\n\t\tfprintf(fp, \"\\n\\t\\tm_time_ps += mintime;\\n\");\n\n\t} else {\n\t\tunsigned long\tclock_duration_ps, quarter_tick, half_tick;\n\n\t\tclock_duration_ps = cklist[0].interval_ps();\n\t\thalf_tick    = clock_duration_ps / 2;\n\t\tquarter_tick = half_tick / 2;\n\n\t\tfprintf(fp, \"\\t\\t// Pre-evaluate, to give verilator a chance\\n\"\n\t\t\t\"\\t\\t// to settle any combinatorial logic that\\n\"\n\t\t\t\"\\t\\t// that may have changed since the last clock\\n\"\n\t\t\t\"\\t\\t// evaluation, and then record that in the\\n\"\n\t\t\t\"\\t\\t// trace.\\n\");\n\t\tfprintf(fp, \"\\t\\teval();\\n\"\n\t\t\t\"\\t\\tif (m_trace && !m_paused_trace) m_trace->dump(m_time_ps+%ld);\\n\\n\",\n\t\t\tquarter_tick);\n\n\t\tfprintf(fp, \"\\t\\t// Advance the one simulation clock, %s\\n\",\n\t\t\t\tcklist[0].m_name->c_str());\n\n\t\tfprintf(fp, \"\\t\\tm_time_ps+= %ld;\\n\", half_tick);\n\t\tfprintf(fp, \"\\t\\tm_core->%s = 1;\\n\", cklist[0].m_wire->c_str());\n\t}\n\n\tfprintf(fp, \"\\t\\teval();\\n\"\n\t\t\"\\t\\t// If we are keeping a trace, dump the current state to \"\n\t\t\"that\\n\\t\\t// trace now\\n\"\n\t\t\"\\t\\tif (m_trace && !m_paused_trace) {\\n\"\n\t\t\t\"\\t\\t\\tm_trace->dump(m_time_ps);\\n\"\n\t\t\t\"\\t\\t\\tm_trace->flush();\\n\"\n\t\t\"\\t\\t}\\n\\n\");\n\n\n\tif (multiclock) {\n\t\tfor(unsigned i=0; i<cklist.size(); i++)\n\t\t\tfprintf(fp, \"\\t\\tif (m_%s.falling_edge()) {\\n\"\n\t\t\t\t\"\\t\\t\\tm_changed = true;\\n\"\n\t\t\t\t\"\\t\\t\\tsim_%s_tick();\\n\"\n\t\t\t\t\"\\t\\t}\\n\",\n\t\t\t\tcklist[i].m_name->c_str(),\n\t\t\t\tcklist[i].m_name->c_str());\n\t} else {\n\t\tunsigned long\tclock_duration_ps, previous;\n\n\t\tclock_duration_ps = cklist[0].interval_ps();\n\t\tprevious = clock_duration_ps/2;\n\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t// <SINGLE CLOCK ONLY>:\\n\"\n\t\t\t\"\\t\\t// Advance the clock again, so that it has \"\n\t\t\t\"its negative edge\\n\");\n\t\tfprintf(fp, \"\\t\\tm_core->%s = 0;\\n\"\n\t\t\t\"\\t\\tm_time_ps+= %ld;\\n\"\n\t\t\t\"\\t\\teval();\\n\"\n\t\t\t\"\\t\\tif (m_trace && !m_paused_trace) m_trace->dump(m_time_ps);\\n\\n\",\n\t\t\t\tcklist[0].m_wire->c_str(),\n\t\t\t\tclock_duration_ps-previous);\n\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t// Call to see if any simulation components need\\n\"\n\t\t\t\"\\t\\t// to advance their inputs based upon this clock\\n\");\n\t\tfprintf(fp, \"\\t\\tsim_%s_tick();\\n\",\n\t\t\t\tcklist[0].m_name->c_str());\n\t}\n\tfprintf(fp,\n\t\"\\t}\\n\"\n\t\"\\t// }}}\\n\"\n\t\"\\n\");\n\n\n\tfor(unsigned i=0; i<cklist.size(); i++) {\n\t\tfprintf(fp, \"\\tvirtual\tvoid\tsim_%s_tick(void) {\\n\"\n\t\t\"\\t\\t// {{{\\n\"\n\t\t\"\\t\\t// AutoFPGA will override this method within \"\n\t\t\"main_tb.cpp if any\\n\\t\\t// @SIM.TICK key is present \"\n\t\t\"within a design component also\\n\\t\\t// containing a \"\n\t\t\"@SIM.CLOCK key identifying this clock.  That\\n\\t\\t// \"\n\t\t\"component must also set m_changed to true.\\n\"\n\t\t\"\\t\\tm_changed = false;\\n\"\n\t\t\"\\t}\\n\"\n\t\t\"\\t// }}}\\n\",\n\t\t\tcklist[i].m_name->c_str());\n\t}\n\n\tfprintf(fp, \"\"\n\t\"\\tvirtual bool\tdone(void) {\\n\"\n\t\t\"\\t\\t// {{{\\n\"\n\t\t\"\\t\\tif (m_done)\\n\"\n\t\t\t\"\\t\\t\\treturn true;\\n\"\n\"\\n\"\n\t\t\"\\t\\tif (Verilated::gotFinish())\\n\"\n\t\t\t\"\\t\\t\\tm_done = true;\\n\"\n\"\\n\"\n\t\t\"\\t\\treturn m_done;\\n\"\n\t\"\\t}\\n\"\n\t\"\\t// }}}\\n\"\n\"\\n\");\n\n\tfprintf(fp, \"\"\n\t\"\\t//\\n\"\n\t\"\\t// reset()\\n\"\n\t\"\\t// {{{\\n\"\n\t\"\\t// Sets the i_reset input for one clock tick.  It's really just a\\n\"\n\t\"\\t// function for the capabilies shown below.  You'll want to reset any\\n\"\n\t\"\\t// external input values before calling this though.\\n\"\n\t\"\\tvirtual\tvoid\treset(void) {\\n\"\n\t\"\\t\tm_core->i_reset = 1;\\n\"\n\t\"\\t\ttick();\\n\");\n\tif (cklist.size() > 1) {\n\t\tfprintf(fp, \"\"\n\t\"\\t\twhile(!m_core->i_clk)\\n\"\n\t\"\\t\t\ttick();\\n\");\n\t}\n\tfprintf(fp, \"\"\n\t\"\\t\tm_core->i_reset = 0;\\n\"\n\t\"\\t\t// printf(\\\"RESET\\\\n\\\");\\n\"\n\t\"\\t}\\n\"\n\t\"\\t// }}}\\n\"\n\"};\\n\"\n\"\\n\"\n\"#endif\\t// TESTB\\n\"\n\"\\n\");\n}\n\n"
  },
  {
    "path": "sw/bldtestb.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bldtestb.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tTo build a test framework that can be used with Verilator for\n//\t\thandling multiple clocks.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tBLDTESTB_H\n#define\tBLDTESTB_H\n\n#include \"parser.h\"\n#include \"mapdhash.h\"\n#include \"clockinfo.h\"\n\n// Build the test bench sim driver helper, that handles clocks and clock ticks.\nextern\tvoid\tbuild_testb_h(MAPDHASH &master, FILE *fp, STRING &fname);\n\n#endif\t// BLDTESTB_H\n\n"
  },
  {
    "path": "sw/bus/axi.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bus/axi.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\n// Tags used:\n//\n//\tBUS.WIDTH\n//\tBUS.AWID\n//\n//\tSLAVE.TYPE:\n//\t- SINGLE\n//\t- DOUBLE\n//\t- OTHER/MEMORY/BUS\n//\tSLAVE.OPTIONS=\n//\t// string of case-insensitive options\n//\t\tROM\t(slave has no write ports)\n//\t\tWOM\t(slave has no read ports)\n//\t\tFULL\t(default:slave has no all ports, not just the ports used)\n//\tSLAVE.SHARE=\n//\t// slave shares parts of the interface with the other listed slaves\n//\n//\tMASTER.TYPE=\n//\t(currently ignored)\n//\n//\tINTERCONNECT.TYPE\n//\t- SINGLE\n//\t- CROSSBAR\n//\n//\tINTERCONNECT.MASTERS\n//\t= list of the PREFIXs of all of the masters of this bus\n//\n//\tINTERCONNECT.OPTIONS\n//\t= string of case-insensitive options\n//\tOPT_STARVATION_TIMEOUT\n//\tOPT_LOWPOWER\n//\tOPT_DBLBUFFER\n//\n//\n//\tINTERCONNECT.OPTVAL=\n//\t= Options that require values\n//\t- OPT_TIMEOUT\n//\t- LGMAXBURST\n//\n// Creates tags:\n//\n//\tBLIST:\tA list of bus interconnect parameters, somewhat like:\n//\t\t\t@$(SLAVE.BUS)_cyc,\n//\t\t\t@$(SLAVE.BUS)_stb,\n//\t(if !ROM&!WOM)\t@$(SLAVE.BUS)_we,\n//\t(if AWID>0)\t@$(SLAVE.BUS)_addr[@$(SLAVE.AWID)-1:0],\n//\t(if !ROM)\t@$(SLAVE.BUS)_data,\n//\t(if !ROM)\t@$(SLAVE.BUS)_sel,\n//\t\t\t@$(PREFIX)_stall,\n//\t\t\t@$(PREFIX)_ack,\n//\t(if !WOM)\t@$(PREFIX)_data,\n//\t(and possibly)\t@$(PREFIX)_err\n//\n//\tASCBLIST.PREFIX: [%io] prefix\n//\tASCBLIST.SUFFIX:\n//\tASCBLIST.CAPS:\n//\tASCBLIST.DATA:\n//\t\t.@$(ASCBLIST.PREFIX)cyc@$(ASCBLIST.SUFFIX)(@$SLAVE.BUS)_cyc),\n//\t\t.@$(ASCBLIST.PREFIX)stb@$(ASCBLIST.SUFFIX)(@$SLAVE.BUS)_stb),\n//\t\t.@$(ASCBLIST.PREFIX)we@$(ASCBLIST.SUFFIX)(@$SLAVE.BUS)_we),\n//\t\t\t.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <string.h>\n#include <unistd.h>\n#include <ctype.h>\n\n#include \"../parser.h\"\n#include \"../mapdhash.h\"\n#include \"../keys.h\"\n#include \"../kveval.h\"\n#include \"../legalnotice.h\"\n#include \"../bldtestb.h\"\n#include \"../bitlib.h\"\n#include \"../plist.h\"\n#include \"../bldregdefs.h\"\n#include \"../ifdefs.h\"\n#include \"../bldsim.h\"\n#include \"../predicates.h\"\n#include \"../businfo.h\"\n#include \"../globals.h\"\n#include \"../subbus.h\"\n#include \"../msgs.h\"\n#include \"../genbus.h\"\n\n#include \"axil.h\"\n#include \"axi.h\"\n\n#define\tPREFIX\n\nextern\tAXIBUSCLASS\taxiclass;\nconst\tunsigned\tAXI_MIN_ADDRESS_WIDTH = 12;\n\nAXIBUS::AXIBUS(BUSINFO *bi) : AXILBUS(bi) {\n\t// {{{\n\tm_info = bi;\n\tm_slist = NULL;\n\tm_dlist = NULL;\n\n\tm_is_single = false;\n\tm_is_double = false;\n\n\tm_num_single = 0;\n\tm_num_double = 0;\n\tm_num_total = 0;\n}\n// }}}\n\nvoid\tAXIBUS::allocate_subbus(void) {\n\t// {{{\n\tPLIST\t*pl = m_info->m_plist;\n\tBUSINFO\t*sbi = NULL, *dbi = NULL;\n\n\tif (NULL == pl || pl->size() == 0) {\n\t\tgbl_msg.warning(\"Bus %s has no attached slaves\\n\",\n\t\t\t(name()) ? name()->c_str() : \"(No-name)\");\n\t}\n\n\tgbl_msg.info(\"Generating AXI4 bus logic generator for %s\\n\",\n\t\t(name()) ? name()->c_str() : \"(No-name)\");\n\tcountsio();\n\n\tif (m_num_single == m_num_total) {\n\t\tm_num_single = 0;\n\t\tm_is_single = true;\n\t} else if ((m_num_single <= 2)&&(m_num_double > 0)) {\n\t\t// Merge single and double busses, making single\n\t\t// slaves into double slaves\n\t\tm_num_double += m_num_single;\n\t\tm_num_single = 0;\n\t}\n\n\tif (!m_is_single && m_num_single + m_num_double == m_num_total) {\n\t\tm_num_single = 0;\n\t\tm_num_double = 0;\n\t\tm_is_double  = true;\n\t}\n\n\tassert(!m_is_single || !m_is_double);\n\tassert(m_num_single < 50);\n\tassert(m_num_double < 50);\n\tassert(m_num_total >= m_num_single + m_num_double);\n\n\t//\n\t// Master of multiple classes\n\t//\n\tif (!m_is_single && m_num_single > 0) {\n\t\tsbi = create_sio();\n\t\tm_num_total++;\n\t}\n\n\tif (!m_is_double && m_num_double > 0) {\n\t\tm_num_total++;\n\t\tdbi = create_dio();\n\t}\n\n\tif (!m_is_single && !m_is_double && pl) {\n\t\t//\n\t\t// There exist peripherals that are neither singles nor doubles\n\t\t//\n\t\tfor(unsigned pi = 0; pi< pl->size(); pi++) {\n\t\t\tPERIPHP\tp = (*pl)[pi];\n\t\t\tSTRINGP\tptyp;\n\n\t\t\tptyp = getstring(p->p_phash, KYSLAVE_TYPE);\n\t\t\tif (m_slist && ptyp != NULL\n\t\t\t\t&& ptyp->compare(KYSINGLE) == 0) {\n\t\t\t\tm_info->m_plist->erase(pl->begin()+pi);\n\t\t\t\tpi--;\n\t\t\t\tm_slist->add(p);\n\t\t\t} else if (m_dlist && ptyp != NULL\n\t\t\t\t\t\t&& ptyp->compare(KYDOUBLE) == 0) {\n\t\t\t\tm_info->m_plist->erase(pl->begin()+pi);\n\t\t\t\tpi--;\n\t\t\t\tm_dlist->add(p);\n\t\t\t} else {\n\t\t\t// Leave this peripheral in m_info->m_plist\n\t\t\t}\n\t\t}\n\t}\n\n\tif (sbi)\n\t\tsetstring(sbi->m_hash, KY_TYPE, axiclass.name());\n\tif (dbi)\n\t\tsetstring(dbi->m_hash, KY_TYPE, axiclass.name());\n\tREHASH;\n}\n// }}}\n\nint\tAXIBUS::address_width(void) {\n\t// {{{\n\tassert(m_info);\n\treturn m_info->m_address_width;\n}\n// }}}\n\nbool\tAXIBUS::get_base_address(MAPDHASH *phash, unsigned &base) {\n\t// {{{\n\tif (!m_info || !m_info->m_plist) {\n\t\tgbl_msg.error(\"BUS[%s] has no peripherals!\\n\",\n\t\t\t(name()) ? name()->c_str() : \"(No name)\");\n\t\treturn false;\n\t} else\n\t\treturn m_info->m_plist->get_base_address(phash, base);\n}\n// }}}\n\nbool\tcompare_idwidths(BMASTERP a, BMASTERP b) {\n\tint\taidw, bidw;\n\n\tassert(a);\n\tassert(b);\n\n\tif (!getvalue(a->m_hash, KYMASTER_IDWIDTH, aidw)) {\n\t\taidw = 0;\n\t\tgbl_msg.error(\"Bus master %s has no required ID width specified, assuming 0 bits\\n\", a->name()->c_str());\n\t}\n\tif (!getvalue(a->m_hash, KYMASTER_IDWIDTH, bidw)) {\n\t\tbidw = 0;\n\t\tgbl_msg.error(\"Bus master %s has no required ID width specified, assuming 0 bits\\n\", b->name()->c_str());\n\t}\n\n\treturn (aidw < bidw);\n}\n\n/*\nvoid\tAXIBUS::assign_ids(void) {\n\tint\tid_width;\n\n\tif (!m_info)\n\t\treturn;\n\tif (m_info->m_ids_assigned)\n\t\treturn;\n\tgbl_msg.info(\"AXI4: Assigning IDs for bus %s\\n\",\n\t\t(name()) ? name()->c_str() : \"(No name bus)\");\n\tif (m_info->m_list->size() == 0) {\n\t\tm_id_width = 0;\n\t\treturn;\n\t} else if (m_info->m_list->size() == 0) {\n\t\tBMASTERP\tm = (*m_info->m_list)[0];\n\t\tif (!getvalue(m->m_hash, KYMASTER_IDWIDTH, m_id_width)) {\n\t\t\tgbl_msg.warning(\"Bus master %s has no required ID width specified, assuming 0 bits\\n\", m->name()->c_str());\n\t\t\tgbl_msg.info(\"This is a warning since bus %s has only one master\", name()->c_str());\n\t\t\tm_id_width = 0;\n\t\t}\n\t\treturn;\n\t}\n\n\tsort(m_info->m_list->begin(), m_info->m_list->end(), \n\t\tcompare_idwidths);\n\tbase = 0;\n\tfor(auto p=m_info->m_list->begin(); p!=m_info->m_list->end(); p++) {\n\t\tif (!getvalue((*m_info->m_list)[0]->m_hash, KYMASTER_IDWIDTH, iw)\n\t\t\tiw = 1;\n\t\tid = base + ((1<<iw)-1) & (-1l<<iw);\n\t\tbase = id + (1<<iw);\n\n\t\tsetvalue((*m_info->m_list)[0]->m_hash, KYMASTER_BUSID, id);\n\t}\n\n\tsetvalue(m_info->m_hash, KY_IDWIDTH, nextlg(base));\n}\n*/\n\nvoid\tAXIBUS::assign_addresses(void) {\n\t// {{{\n\tint\taddress_width;\n\n\tif (m_info->m_addresses_assigned)\n\t\treturn;\n\tif ((NULL == m_slist)&&(NULL == m_dlist))\n\t\tallocate_subbus();\n\n\tif (!m_info)\n\t\treturn;\n\tgbl_msg.info(\"AXI4: Assigning addresses for bus %s\\n\",\n\t\t(name()) ? name()->c_str() : \"(No name bus)\");\n\tif (!m_info->m_plist||(m_info->m_plist->size() < 1)) {\n\t\tm_info->m_address_width = 0;\n\t} else if (!m_info->m_addresses_assigned) {\n\t\tint\tdw = m_info->data_width(),\n\t\t\tnullsz;\n\n\t\tif (m_slist)\n\t\t\tm_slist->assign_addresses(dw, 0);\n\n\t\tif (m_dlist)\n\t\t\tm_dlist->assign_addresses(dw, 0);\n\n\t\tif (!getvalue(*m_info->m_hash, KY_NULLSZ, nullsz))\n\t\t\tnullsz = 0;\n\n\t\tm_info->m_plist->assign_addresses(dw, nullsz, AXI_MIN_ADDRESS_WIDTH);\n\t\taddress_width = m_info->m_plist->get_address_width();\n\t\tm_info->m_address_width = address_width;\n\t\tif (m_info->m_hash) {\n\t\t\tsetvalue(*m_info->m_hash, KY_AWID, m_info->m_address_width);\n\t\t\tREHASH;\n\t\t}\n\t} m_info->m_addresses_assigned = true;\n}\n// }}}\n\nBUSINFO *AXIBUS::create_sio(void) {\n\t// {{{\n\tassert(m_info);\n\n\tBUSINFO\t*sbi;\n\tSUBBUS\t*subp;\n\tSTRINGP\tsioname;\n\tMAPDHASH *bushash, *shash;\n\tMAPT\telm;\n\n\tsioname = new STRING(STRING(\"\" PREFIX) + (*name()) + \"_sio\");\n\tbushash = new MAPDHASH();\n\tshash   = new MAPDHASH();\n\tsetstring(*shash, KYPREFIX, sioname);\n\tsetstring(*shash, KYSLAVE_TYPE, new STRING(KYDOUBLE));\n\tsetstring(*shash, KYSLAVE_PREFIX, sioname);\n\n\telm.m_typ = MAPT_MAP;\n\telm.u.m_m = bushash;\n\tshash->insert(KEYVALUE(KYSLAVE_BUS, elm));\n\n\telm.u.m_m = m_info->m_hash;\n\tshash->insert(KEYVALUE(KYMASTER_BUS, elm));\n\tsetstring(shash, KYMASTER_TYPE, KYARBITER);\n\n\tsbi  = new BUSINFO(sioname);\n\tsbi->prefix(new STRING(\"_sio\"));\n\tsetstring(bushash, KY_TYPE, new STRING(\"axi4\"));\n\tsbi->m_data_width = m_info->m_data_width;\n\tsbi->m_clock      = m_info->m_clock;\n\tsbi->addmaster(m_info->m_hash);\n\tsubp = new SUBBUS(shash, sioname, sbi);\n\tsubp->p_slave_bus = m_info;\n\t// subp->p_master_bus = set by the SUBBUS to be sbi\n\tm_info->m_plist->add(subp);\n\t// m_plist->integrity_check();\n\tsbi->add();\n\tm_slist = sbi->m_plist;\n\n\treturn sbi;\n}\n// }}}\n\nBUSINFO *AXIBUS::create_dio(void) {\n\t// {{{\n\tassert(m_info);\n\n\tBUSINFO\t*dbi;\n\tSUBBUS\t*subp;\n\tSTRINGP\tdioname;\n\tMAPDHASH\t*bushash, *shash;\n\tMAPT\telm;\n\n\tdioname = new STRING(STRING(\"\" PREFIX) + (*name()) + \"_dio\");\n\tbushash = new MAPDHASH();\n\tshash   = new MAPDHASH();\n\tsetstring(*bushash, KY_NAME, dioname);\n\tsetstring(*shash, KYPREFIX, dioname);\n\tsetstring(*shash, KYSLAVE_TYPE, new STRING(KYOTHER));\n\tsetstring(*shash, KYSLAVE_PREFIX, dioname);\n\n\telm.m_typ = MAPT_MAP;\n\telm.u.m_m = m_info->m_hash;\n\tshash->insert(KEYVALUE(KYSLAVE_BUS, elm));\n\n\telm.u.m_m = bushash;\n\tshash->insert(KEYVALUE(KYMASTER_BUS, elm));\n\tsetstring(shash, KYMASTER_TYPE, KYARBITER);\n\n\tdbi  = new BUSINFO(dioname);\n\tdbi->prefix(new STRING(\"_dio\"));\n\tsetstring(bushash, KY_TYPE, new STRING(\"axi4\"));\n\tsetvalue(*bushash, KY_WIDTH, m_info->data_width());\n\tdbi->m_data_width = m_info->m_data_width;\n\tdbi->m_clock      = m_info->m_clock;\n\tdbi->addmaster(m_info->m_hash);\n\tsubp = new SUBBUS(shash, dioname, dbi);\n\tsubp->p_slave_bus = m_info;\n\tm_info->m_plist->add(subp);\n\t// subp->p_master_bus = set by the slave to be dbi\n\tdbi->add();\n\tm_dlist = dbi->m_plist;\n\n\treturn dbi;\n}\n// }}}\n\nint\tAXIBUS::id_width(void) {\n\tint\tvalue;\n\n\tif (m_info && getvalue(m_info->m_hash, KY_IDWIDTH, value))\n\t\treturn m_id_width = value;\n\treturn m_id_width;\n}\n\nvoid\tAXIBUS::writeout_defn_v(FILE *fp, const char *mstype,\n\t\tconst char *pname, const char* busp, const char *btyp){\n\t// {{{\n\tSTRINGP\tn = name();\n\tint\taw = address_width();\n\tint\tiw = id_width();\n\n\tfprintf(fp, \"\\t// AXI4 %s definitions for bus %s%s,\\n\"\n\t\t\"\\t// component %s, with prefix %s\\n\"\n\t\t\"\\t// {{{\\n\",\n\t\tmstype, n->c_str(), btyp, pname, busp);\n\tfprintf(fp, \"\\t// Verilator lint_off UNUSED\\n\");\n\tfprintf(fp, \"\\twire\\t\\t%s_awvalid;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t\\t%s_awready;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t[%d:0]\\t%s_awid;\\n\",   iw-1, busp);\n\tfprintf(fp, \"\\twire\\t[%d:0]\\t%s_awaddr;\\n\", aw-1, busp);\n\tfprintf(fp, \"\\twire\\t[7:0]\\t%s_awlen;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t[2:0]\\t%s_awsize;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t[1:0]\\t%s_awburst;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t\\t%s_awlock;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t[3:0]\\t%s_awcache;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t[2:0]\\t%s_awprot;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t[3:0]\\t%s_awqos;\\n\", busp);\n\tfprintf(fp, \"\\t//\\n\");\n\t//\n\tfprintf(fp, \"\\twire\\t\\t%s_wvalid;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t\\t%s_wready;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t[%d:0]\\t%s_wdata;\\n\\n\", m_info->data_width()-1, busp);\n\tfprintf(fp, \"\\twire\\t[%d:0]\\t%s_wstrb;\\n\\n\", m_info->data_width()/8-1, busp);\n\tfprintf(fp, \"\\twire\\t\\t%s_wlast;\\n\\n\", busp);\n\t//\n\tfprintf(fp, \"\\twire\\t\\t%s_bvalid;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t\\t%s_bready;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t[%d:0]\\t%s_bid;\\n\", iw-1, busp);\n\tfprintf(fp, \"\\twire\\t[1:0]\\t%s_bresp;\\n\", busp);\n\t//\n\tfprintf(fp, \"\\twire\\t\\t%s_arvalid;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t\\t%s_arready;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t[%d:0]\\t%s_arid;\\n\",   iw-1, busp);\n\tfprintf(fp, \"\\twire\\t[%d:0]\\t%s_araddr;\\n\", aw-1, busp);\n\tfprintf(fp, \"\\twire\\t[7:0]\\t%s_arlen;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t[2:0]\\t%s_arsize;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t[1:0]\\t%s_arburst;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t\\t%s_arlock;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t[3:0]\\t%s_arcache;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t[2:0]\\t%s_arprot;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t[3:0]\\t%s_arqos;\\n\", busp);\n\tfprintf(fp, \"\\t//\\n\");\n\t//\n\tfprintf(fp, \"\\twire\\t\\t%s_rvalid;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t\\t%s_rready;\\n\", busp);\n\tfprintf(fp, \"\\twire\\t[%d:0]\\t%s_rid;\\n\", iw-1, busp);\n\tfprintf(fp, \"\\twire\\t[%d:0]\\t%s_rdata;\\n\\n\", m_info->data_width()-1, busp);\n\tfprintf(fp, \"\\twire\\t\\t%s_rlast;\\n\\n\", busp);\n\tfprintf(fp, \"\\twire\\t[1:0]\\t%s_rresp;\\n\", busp);\n\tfprintf(fp,\n\t\t\"\\t// Verilator lint_on  UNUSED\\n\"\n\t\t\"\\t// }}}\\n\");\n}\n// }}}\n\n// Inherited from AXI-lite\nvoid\tAXIBUS::writeout_bus_slave_defns_v(FILE *fp) {\n\t// {{{\n\tPLIST\t*p = m_info->m_plist;\n\tSTRINGP\tn = name();\n\n\tif (m_slist) {\n\t\tfor(PLIST::iterator pp=m_slist->begin();\n\t\t\t\tpp != m_slist->end(); pp++) {\n\t\t\twriteout_defn_v(fp, \"slave\", (*pp)->p_name->c_str(),\n\t\t\t\t(*pp)->bus_prefix()->c_str(), \"(SIO)\");\n\t\t}\n\t} else if (!m_is_single)\n\t\tfprintf(fp, \"\\n\\t// Bus %s has no SINGLE slaves\\n\\t//\\n\", n->c_str());\n\telse\n\t\tfprintf(fp, \"\\n\\t// Bus %s is all SINGLE slaves\\n\\t//\\n\", n->c_str());\n\n\tif (m_dlist) {\n\t\tfor(PLIST::iterator pp=m_dlist->begin();\n\t\t\t\tpp != m_dlist->end(); pp++) {\n\t\t\twriteout_defn_v(fp, \"slave\", (*pp)->p_name->c_str(),\n\t\t\t\t(*pp)->bus_prefix()->c_str(), \"(DIO)\");\n\t\t}\n\t} else if (!m_is_double)\n\t\tfprintf(fp, \"\\n\\t// Bus %s has no DOUBLE slaves\\n\\t//\\n\", n->c_str());\n\telse\n\t\tfprintf(fp, \"\\n\\t// Bus %s is all DOUBLE slaves\\n\\t//\\n\", n->c_str());\n\n\n\tif (p) {\n\t\tfor(PLIST::iterator pp=p->begin(); pp != p->end(); pp++) {\n\t\t\twriteout_defn_v(fp, \"slave\", (*pp)->p_name->c_str(),\n\t\t\t\t(*pp)->bus_prefix()->c_str());\n\t\t}\n\t} else {\n\t\tgbl_msg.error(\"%s has no slaves\\n\", n->c_str());\n\t}\n}\n// }}}\n\nvoid\tAXIBUS::writeout_bus_master_defns_v(FILE *fp) {\n\t// {{{\n\tMLIST\t*m = m_info->m_mlist;\n\tSTRINGP\tn = name();\n\n\tif (m) {\n\t\tfor(MLIST::iterator pp=m->begin(); pp != m->end(); pp++) {\n\t\t\twriteout_defn_v(fp, \"master\", (*pp)->name()->c_str(),\n\t\t\t(*pp)->bus_prefix()->c_str());\n\t\t}\n\t} else {\n\t\tgbl_msg.warning(\"Bus %s has no masters\\n\", n->c_str());\n\t}\n}\n// }}}\n\n// void\tAXIBUS::write_addr_range(FILE *fp, const PERIPHP p, const int dalines)\n// void\tAXIBUS::writeout_no_slave_v(FILE *fp, STRINGP prefix)\n// void\tAXIBUS::writeout_no_master_v(FILE *fp)\n// STRINGP\tAXIBUS::master_name(int k)\n\n//\n// Connect this master to the crossbar.  Specifically, we want to output\n// a list of master connections to fill the given port.\n//\n// void AXILBUS::xbarcon_master(FILE *fp, const char *tabs,\n\n//\n// Output a list of connections to slave bus wires.  Used in connecting the\n// slaves to the various crossbar inputs.\n//\n// void AXILBUS::xbarcon_slave(FILE *fp, PLIST *pl, const char *tabs,\n//\t\t\tconst char *pfx,const char *sig, bool comma)\n\nvoid\tAXIBUS::writeout_bus_logic_v(FILE *fp) {\n\tSTRINGP\t\tn = name(), rst;\n\tCLOCKINFO\t*c = m_info->m_clock;\n\tPLIST::iterator\tpp;\n\tPLISTP\t\tpl;\n\t// unsigned\tunused_lsbs;\n\tMLISTP\t\tm_mlist = m_info->m_mlist;\n\n\tif (NULL == m_info->m_plist)\n\t\treturn;\n\n\tif (NULL == m_info->m_mlist) {\n\t\tgbl_msg.warning(\"No masters assigned to bus %s\\n\",\n\t\t\t\tn->c_str());\n\t}\n\tif (NULL == (rst = m_info->reset_wire())) {\n\t\tgbl_msg.warning(\"Bus %s has no associated reset wire, using \\'i_reset\\'\\n\", n->c_str());\n\t\trst = new STRING(\"i_reset\");\n\t\tsetstring(m_info->m_hash, KY_RESET, rst);\n\t\tREHASH;\n\t}\n\n\tif (NULL == c || NULL == c->m_wire) {\n\t\tgbl_msg.fatal(\"Bus %s has no associated clock\\n\", n->c_str());\n\t}\n\n\n\t// unused_lsbs = nextlg(m_info->data_width())-3;\n\tif (m_info->m_plist->size() == 0) {\t// No slaves\n\t\t// {{{\n\t\tfprintf(fp, \"\\t//\\n\"\n\t\t\t\"\\t// Bus %s has no slaves\\n\"\n\t\t\t\"\\t//\\n\\n\", n->c_str());\n\n\t\t// Since this bus has no slaves, any attempt to access it\n\t\t// needs to cause a bus error.\n\t\t//\n\t\t// Need to loop through all possible masters ...\n\t\tfor(unsigned m=0; m_info && m < m_info->m_mlist->size(); m++) {\n\t\t\tSTRINGP\tmstr = master_name(m);\n\t\t\tconst\tchar *mp = mstr->c_str();\n\t\t\t// const char *pfx = (*m_info->m_mlist)[m]->bus_prefix()->c_str();\n\t\t\tfprintf(fp,\n\t\t\t\t\"\\t//\\n\"\n\t\t\t\t\"\\t// The %s bus has no slaves assigned to it\\n\"\n\t\t\t\t\"\\t//\\n\", mp);\n\n\t\t\tfprintf(fp,\n\t\t\t\t\"\\t// The no-slave peripheral\\n\"\n\t\t\t\t\"\\t//\\n\"\n\t\"\\taxiempty #(\\n\"\n\t\"\\t\\t// {{{\\n\"\n\t\"\\t\\t.C_AXI_ADDR_WIDTH(%d),\\n\"\n\t\"\\t\\t.C_AXI_DATA_WIDTH(%d),\\n\"\n\t\"\\t\\t.C_AXI_ID_WIDTH(%d),\\n\"\n\t\"\\t\\t// }}}\\n\",\n\t\t\t\taddress_width(),\n\t\t\t\tm_info->data_width(),\n\t\t\t\tid_width());\n\t\t\tfprintf(fp,\n\t\"\\t) %s_no_slavep (\\n\"\n\t\t\"\\t\\t// {{{\\n\"\n\t\t\"\\t\\t.S_AXI_ACLK(%s), .S_AXI_ARESETN(%s),\\n\"\n\t\t\"\\t\\t//\\n\",\n\t\t\tmp, c->m_wire->c_str(), rst->c_str());\n\t\t\tfprintf(fp,\n\t\t\"\\t\\t.S_AXI_AWVALID(%s_awvalid), .S_AXI_AWREADY(%s_awready),\\n\"\n\t\t\"\\t\\t\\t.S_AXI_AWID(%s_awid),\\n\"\n\t\t\"\\t\\t//\\n\"\n\t\t\"\\t\\t.S_AXI_WVALID(%s_wvalid),   .S_AXI_WREADY(%s_wready),\\n\"\n\t\t\"\\t\\t\\t.S_AXI_WLAST(%s_wlast),\\n\"\n\t\t\"\\t\\t//\\n\"\n\t\t\"\\t\\t.S_AXI_BVALID(%s_bvalid),   .S_AXI_BREADY(%s_bready),\\n\"\n\t\t\"\\t\\t\\t.S_AXI_BID(%s_bid),       .S_AXI_BRESP(%s_bresp),\\n\"\n\t\t\"\\t\\t//\\n\"\n\t\t\"\\t\\t.S_AXI_ARVALID(%s_arvalid), .S_AXI_ARREADY(%s_arready),\\n\"\n\t\t\"\\t\\t\\t.S_AXI_ARLEN(%s_arlen),   .S_AXI_ARID(%s_awid),\\n\"\n\t\t\"\\t\\t//\\n\"\n\t\t\"\\t\\t.S_AXI_RVALID(%s_rvalid),   .S_AXI_RREADY(%s_rready),\\n\"\n\t\t\"\\t\\t\\t.S_AXI_RID(%s_rid),       .S_AXI_RDATA(%s_rdata),\\n\"\n\t\t\"\\t\\t\\t.S_AXI_RLAST(%s_rlast),   .S_AXI_RRESP(%s_rresp)\\n\"\n\t\t\"\\t);\\n\\n\",\n\t\t\t\tmp, mp, mp,\n\t\t\t\tmp, mp, mp,\n\t\t\t\tmp, mp, mp, mp,\n\t\t\t\tmp, mp, mp, mp,\n\t\t\t\tmp, mp, mp, mp, mp, mp);\n\t\t}\n\n\t\treturn;\n\t\t// }}}\n\t} else if (NULL == m_mlist || m_mlist->size() == 0) { // No masters\n\t\t// {{{\n\t\tfor(unsigned p=0; p < m_info->m_plist->size(); p++) {\n\t\t\tSTRINGP\tpstr = (*m_info->m_plist)[p]->bus_prefix();\n\t\t\tfprintf(fp,\n\t\t\"\\t//\\n\"\n\t\t\"\\t// The %s bus has no masters assigned to it\\n\"\n\t\t\"\\t//\\n\"\n\t\t\"\\tassign\t%s_awvalid = 1\\'b0;\\n\"\n\t\t\"\\tassign\t%s_awid    = 0;\\n\"\n\t\t\"\\tassign\t%s_awaddr  = 0;\\n\"\n\t\t\"\\tassign\t%s_awlen   = 8\\'h00;\\n\"\n\t\t\"\\tassign\t%s_awsize  = 3\\'b000;\\n\"\n\t\t\"\\tassign\t%s_awburst = 2\\'b00;\\n\"\n\t\t\"\\tassign\t%s_awlock  = 1\\'b0;\\n\"\n\t\t\"\\tassign\t%s_awcache = 4\\'h0;\\n\"\n\t\t\"\\tassign\t%s_awprot  = 3\\'h0;\\n\"\n\t\t\"\\tassign\t%s_awqos   = 4\\'h0;\\n\"\n\t\t\"\\t//\\n\",\n\t\t\tpstr->c_str(), pstr->c_str(), pstr->c_str(),\n\t\t\tpstr->c_str(), pstr->c_str(), pstr->c_str(),\n\t\t\tpstr->c_str(), pstr->c_str(), pstr->c_str(),\n\t\t\tpstr->c_str(), pstr->c_str());\n\n\t\t\tfprintf(fp,\n\t\t\"\\tassign\t%s_wvalid  = 1\\'b0;\\n\"\n\t\t\"\\tassign\t%s_wdata   = 0;\\n\"\n\t\t\"\\tassign\t%s_wstrb   = 0;\\n\"\n\t\t\"\\tassign\t%s_wlast   = 1\\'b1;\\n\"\n\t\t\"\\t//\\n\",\n\t\t\tpstr->c_str(), pstr->c_str(),\n\t\t\tpstr->c_str(), pstr->c_str());\n\n\t\t\tfprintf(fp,\n\t\t\"\\tassign\t%s_bready  = 1\\'b0;\\n\",\n\t\t\tpstr->c_str());\n\n\t\t\tfprintf(fp,\n\t\t\"\\t//\\n\"\n\t\t\"\\tassign\t%s_arvalid = 1\\'b0;\\n\"\n\t\t\"\\tassign\t%s_arid    = 0;\\n\"\n\t\t\"\\tassign\t%s_araddr  = 0;\\n\"\n\t\t\"\\tassign\t%s_arlen   = 8\\'h00;\\n\"\n\t\t\"\\tassign\t%s_arsize  = 3\\'b000;\\n\"\n\t\t\"\\tassign\t%s_arburst = 2\\'b00;\\n\"\n\t\t\"\\tassign\t%s_arlock  = 1\\'b0;\\n\"\n\t\t\"\\tassign\t%s_arcache = 4\\'h0;\\n\"\n\t\t\"\\tassign\t%s_arprot  = 3\\'h0;\\n\"\n\t\t\"\\tassign\t%s_arqos   = 4\\'h0;\\n\"\n\t\t\"\\t//\\n\",\n\t\t\tpstr->c_str(), pstr->c_str(), pstr->c_str(),\n\t\t\tpstr->c_str(), pstr->c_str(), pstr->c_str(),\n\t\t\tpstr->c_str(), pstr->c_str(), pstr->c_str(),\n\t\t\tpstr->c_str());\n\n\t\t\tfprintf(fp,\n\t\t\"\\tassign\t%s_rready  = 1\\'b1;\\n\",\n\t\t\tpstr->c_str());\n\n\t\t\tfprintf(fp,\n\t\t\"\\t//\\n\"\n\t\t\"\\t//\\n\"\n\t\t\"\\twire\t%s_unused;\\n\"\n\t\t\"\\tassign\t%s_unused = &{ 1\\'b0, %s_awready, %s_wready,\\n\"\n\t\t\t\"\\t\\t%s_bvalid, %s_bid, %s_bresp,\\n\"\n\t\t\t\"\\t\\t%s_arready,\\n\"\n\t\t\t\"\\t\\t%s_rvalid, %s_rid, %s_rdata,\\n\"\n\t\t\t\t\"\\t\\t\\t%s_rlast, %s_rresp\\n\"\n\t\t\t\"\\t\\t};\\n\",\n\t\t\tpstr->c_str(), pstr->c_str(),\n\t\t\tpstr->c_str(), pstr->c_str(),\n\t\t\tpstr->c_str(), pstr->c_str(), pstr->c_str(),\n\t\t\tpstr->c_str(),\n\t\t\tpstr->c_str(), pstr->c_str(), pstr->c_str(),\n\t\t\t\tpstr->c_str(), pstr->c_str()\n\t\t\t);\n\t\t}\n\n\t\treturn;\n\t\t// }}}\n\t} else if ((m_info->m_plist->size() == 1)&&(m_mlist && m_mlist->size() == 1)) {\n\t\t// {{{\n\t\t// Only one master connected to only one slave--skip all the\n\t\t// extra connection logic.\n\t\t//\n\t\t// Can only simplify if there's only one peripheral and only\n\t\t// one master\n\t\t//\n\t\tSTRINGP\tslv  = (*m_info->m_plist)[0]->bus_prefix();\n\t\tSTRINGP\tmstr = (*m_mlist)[0]->bus_prefix();\n\t\tconst char *sp = slv->c_str(),\n\t\t\t*mp = mstr->c_str();\n\n\t\tfprintf(fp,\n\t\t\"\\t//\\n\"\n\t\t\"\\t// Bus %s has only one master (%s) and one slave (%s)\\n\"\n\t\t\"\\t// connected to it -- skipping the interconnect\\n\"\n\t\t\"\\t//\\n\",\n\t\tn->c_str(), master_name(0)->c_str(), sp);\n\n\t\t\tfprintf(fp,\n\t\t\"\\tassign\t%s_awvalid = %s_awvalid;\\n\"\n\t\t\"\\tassign\t%s_awready = %s_awready;\\n\"\n\t\t\"\\tassign\t%s_awid    = %s_awid;\\n\"\n\t\t\"\\tassign\t%s_awaddr  = %s_awaddr;\\n\"\n\t\t\"\\tassign\t%s_awlen   = %s_awlen;\\n\"\n\t\t\"\\tassign\t%s_awsize  = %s_awsize;\\n\"\n\t\t\"\\tassign\t%s_awburst = %s_awburst;\\n\"\n\t\t\"\\tassign\t%s_awlock  = %s_awlock;\\n\"\n\t\t\"\\tassign\t%s_awcache = %s_awcache;\\n\"\n\t\t\"\\tassign\t%s_awprot  = %s_awprot;\\n\"\n\t\t\"\\tassign\t%s_awqos   = %s_awqos;\\n\"\n\t\t\"\\t//\\n\",\n\t\t\tsp, mp, mp, sp,\n\t\t\tsp, mp, sp, mp, sp, mp, sp, mp,\n\t\t\tsp, mp, sp, mp, sp, mp, sp, mp,\n\t\t\tsp, mp);\n\n\t\t\tfprintf(fp,\n\t\t\"\\tassign\t%s_wvalid  = %s_wvalid;\\n\"\n\t\t\"\\tassign\t%s_wready  = %s_wready;\\n\"\n\t\t\"\\tassign\t%s_wdata   = %s_wdata;\\n\"\n\t\t\"\\tassign\t%s_wstrb   = %s_wstrb;\\n\"\n\t\t\"\\tassign\t%s_wlast   = %s_wlast;\\n\"\n\t\t\"\\t//\\n\",\n\t\t\tsp, mp, mp, sp,\n\t\t\tsp, mp, sp, mp, sp, mp);\n\n\t\t\tfprintf(fp,\n\t\t\"\\tassign\t%s_bvalid  = %s_bvalid;\\n\"\n\t\t\"\\tassign\t%s_bready  = %s_bready;\\n\"\n\t\t\"\\tassign\t%s_bid     = %s_bid;\\n\"\n\t\t\"\\tassign\t%s_bresp   = %s_bresp;\\n\",\n\t\t\tmp, sp, sp, mp,\n\t\t\tmp, sp, mp, sp);\n\n\t\t\tfprintf(fp,\n\t\t\"\\t//\\n\"\n\t\t\"\\t//\\n\"\n\t\t\"\\tassign\t%s_arvalid = %s_arvalid;\\n\"\n\t\t\"\\tassign\t%s_arready = %s_arready;\\n\"\n\t\t\"\\tassign\t%s_arid    = %s_arid;\\n\"\n\t\t\"\\tassign\t%s_araddr  = %s_araddr;\\n\"\n\t\t\"\\tassign\t%s_arlen   = %s_arlen;\\n\"\n\t\t\"\\tassign\t%s_arsize  = %s_arsize;\\n\"\n\t\t\"\\tassign\t%s_arburst = %s_arburst;\\n\"\n\t\t\"\\tassign\t%s_arlock  = %s_arlock;\\n\"\n\t\t\"\\tassign\t%s_arcache = %s_arcache;\\n\"\n\t\t\"\\tassign\t%s_arprot  = %s_arprot;\\n\"\n\t\t\"\\tassign\t%s_arqos   = %s_arqos;\\n\"\n\t\t\"\\t//\\n\",\n\t\t\tsp, mp, mp, sp,\n\t\t\tsp, mp, sp, mp,\n\t\t\tsp, mp, sp, mp, sp, mp, sp, mp,\n\t\t\tsp, mp, sp, mp, sp, mp);\n\n\t\t\tfprintf(fp,\n\t\t\"\\tassign\t%s_rvalid  = %s_rvalid;\\n\"\n\t\t\"\\tassign\t%s_rready  = %s_rready;\\n\"\n\t\t\"\\tassign\t%s_rid     = %s_rid;\\n\"\n\t\t\"\\tassign\t%s_rdata   = %s_rdata;\\n\"\n\t\t\"\\tassign\t%s_rlast   = %s_rlast;\\n\"\n\t\t\"\\tassign\t%s_rresp   = %s_rresp;\\n\\n\",\n\t\t\tmp, sp, sp, mp,\n\t\t\tmp, sp, mp, sp, mp, sp, mp, sp);\n\t\treturn;\n\t\t// }}}\n\t}\n\n\t// Start with the slist\n\tif (m_is_single || m_slist) {\n\t\t// {{{\n\t\tassert(1 == m_info->m_mlist->size());\n\n\t\tPLIST\t*slist = (m_is_single) ? m_info->m_plist : m_slist;\n\t\tconst char *np = n->c_str();\n\t\tSTRING\ts = STRING(*(*m_mlist)[0]->bus_prefix());\n\t\tint\taw = nextlg(slist->size())+nextlg(m_info->data_width())-3;\n\n\t\tgbl_msg.error(\"AXI-Single logic hasn\\'t yet been implemented\\n\");\n\t\tfprintf(fp,\n\t\t\"\\t// (AXI-Single isn\\'t yet written)\\n\"\n\t\t\"\\taxisingle #(\\n\"\n\t\t\t\"\\t\\t// {{{\\n\"\n\t\t\t\"\\t\\t// .C_AXI_ADDR_WIDTH(%d),\\n\"\n\t\t\t\"\\t\\t.C_AXI_DATA_WIDTH(%d),\\n\"\n\t\t\t\"\\t\\t.NS(%ld)\",\n\t\t\taw, m_info->data_width(),\n\t\t\tslist->size());\n\t\txbar_option(fp, KY_OPT_LOWPOWER,  \",\\n\\t\\t.OPT_LOWPOWER(%)\",\n\t\t\t\"1\\'b1\");\n\t\tfprintf(fp,\n\t\t\"\\n\\t\\t// }}}\\n\"\n\t\t\"\\t) %s_axisingle(\\n\", np);\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t// {{{\\n\"\n\t\t\t\"\\t\\t.S_AXI_ACLK(%s),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARESETN(%s),\\n\",\n\t\t\t\tc->m_wire->c_str(), rst->c_str());\n\n\t\tfprintf(fp, \"\\t\\t// Connect our SIO slave wires to axisingle\\n\"\n\t\t\t\"\\t\\t// {{{\\n\");\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t.S_AXI_AWVALID(%s_awvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWREADY(%s_awready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWID(   %s_awid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWADDR( %s_awaddr[%d:0]),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWLEN(  %s_awlen),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWSIZE( %s_awsize),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWBURST(%s_awburst),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWLOCK( %s_awlock),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWCACHE(%s_awcache),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWPROT( %s_awprot),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWQOS(  %s_awqos),\\n\"\n\t\t\t\"\\t\\t//\\n\"\n\t\t\t\"\\t\\t.S_AXI_WVALID( %s_wvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_WREADY( %s_wready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_WDATA(  %s_wdata),\\n\"\n\t\t\t\"\\t\\t.S_AXI_WSTRB(  %s_wstrb),\\n\"\n\t\t\t\"\\t\\t.S_AXI_WLAST(  %s_wlast),\\n\"\n\t\t\t\"\\t\\t//\\n\"\n\t\t\t\"\\t\\t.S_AXI_BVALID( %s_bvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_BREADY( %s_bready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_BID(    %s_bid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_BRESP(  %s_bresp),\\n\"\n\t\t\t\"\\t\\t//\\n\",\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str(), aw-1,\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str(),\n\t\t\ts.c_str(), s.c_str(), s.c_str(),\n\t\t\t//\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str(),\n\t\t\ts.c_str(),\n\t\t\t//\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str());\n\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t// Read connections\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARVALID(%s_arvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARREADY(%s_arready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARID(   %s_arid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARADDR( %s_araddr[%d:0]),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARLEN(  %s_arlen),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARSIZE( %s_arsize),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARBURST(%s_arburst),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARLOCK( %s_arlock),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARCACHE(%s_arcache),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARPROT( %s_arprot),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARQOS(  %s_arqos),\\n\"\n\t\t\t\"\\t\\t//\\n\"\n\t\t\t\"\\t\\t.S_AXI_RVALID( %s_rvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_RREADY( %s_rready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_RID(    %s_rid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_RDATA(  %s_rdata),\\n\"\n\t\t\t\"\\t\\t.S_AXI_RLAST(  %s_rlast),\\n\"\n\t\t\t\"\\t\\t.S_AXI_RRESP(  %s_rresp),\\n\"\n\t\t\t\"\\t\\t// }}}\\n\"\n\t\t\t\"\\t\\t// Connections to varous AXI (SINGLE) slaves\\n\"\n\t\t\t\"\\t\\t// {{{\\n\",\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str(), aw-1,\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str(),\n\t\t\ts.c_str(), s.c_str(), s.c_str(),\n\t\t\t//\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str(),\n\t\t\ts.c_str(), s.c_str());\n\n\t\txbarcon_slave(fp, slist, \"\\t\\t\",\".M_AXI_\",\"AWVALID\");\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t.M_AXI_AWPROT(%s_siow_awprot),\\n\"\n\t\t\t\"\\t\\t.M_AXI_WDATA( %s_siow_wdata),\\n\"\n\t\t\t\"\\t\\t.M_AXI_WSTRB( %s_siow_wstrb),\\n\",\n\t\t\tn->c_str(), n->c_str(), n->c_str());\n\t\tfprintf(fp, \"\\t\\t//\\n\"\n\t\t\t\"\\t\\t//\\n\");\n\t\txbarcon_slave(fp, slist, \"\\t\\t\",\".M_AXI_\",\"BRESP\");\n\t\tfprintf(fp, \"\\t\\t// Read connections\\n\");\n\t\txbarcon_slave(fp, slist, \"\\t\\t\",\".M_AXI_\",\"ARVALID\");\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t.M_AXI_ARPROT(%s_siow_arprot),\\n\"\n\t\t\t\"\\t\\t//\\n\", n->c_str());\n\t\txbarcon_slave(fp, slist, \"\\t\\t\",\".M_AXI_\",\"RDATA\");\n\t\txbarcon_slave(fp, slist, \"\\t\\t\",\".M_AXI_\",\"RRESP\", false);\n\t\tfprintf(fp, \"\\t\\t// }}}\\n\"\n\t\t\t\"\\t\\t// }}}\\n\"\n\t\t\t\"\\t);\\n\\n\");\n\t\tfprintf(fp,\"\\t//\\n\\t// Now connecting the extra slaves wires \"\n\t\t\t\"to the AXISINGLE controller\\n\"\n\t\t\t\"\\t// {{{\\n\");\n\n\t\tfor(int k=slist->size(); k>0; k--) {\n\t\t\tPERIPHP p = (*slist)[k-1];\n\t\t\tconst char *pn = p->p_name->c_str(),\n\t\t\t\t*ns = n->c_str();\n\n\t\t\tfprintf(fp, \"\\t// %s\\n\", pn);\n\t\t\tpn = p->bus_prefix()->c_str();\n\t\t\tfprintf(fp, \"\\tassign %s_awaddr = 0;\\n\", pn);\n\t\t\tfprintf(fp, \"\\tassign %s_awprot = %s_siow_awprot;\\n\", pn, ns);\n\t\t\tfprintf(fp, \"\\tassign %s_wvalid = %s_awvalid;\\n\", pn, pn);\n\t\t\tfprintf(fp, \"\\tassign %s_wdata = %s_siow_wdata;\\n\", pn, ns);\n\t\t\tfprintf(fp, \"\\tassign %s_wstrb = %s_siow_wstrb;\\n\", pn, ns);\n\t\t\tfprintf(fp, \"\\tassign %s_bready = 1\\'b1;\\n\", pn);\n\t\t\tfprintf(fp, \"\\tassign %s_araddr = 0;\\n\", pn);\n\t\t\tfprintf(fp, \"\\tassign %s_arprot = %s_siow_arprot;\\n\", pn, ns);\n\t\t\tfprintf(fp, \"\\tassign %s_rready = 1\\'b1;\\n\", pn);\n\t\t} fprintf(fp, \"\\t// }}}\\n\");\n\t\t// }}}\n\t\treturn;\n\t\t// }}}\n\t} else if (!m_slist)\n\t\tfprintf(fp, \"\\t//\\n\\t// No class SINGLE peripherals on the \\\"%s\\\" bus\\n\\t//\\n\\n\", n->c_str());\n\n\t// Then the dlist\n\tif (m_is_double || m_dlist) {\n\t\t// {{{\n\t\tif (m_dlist)\n\t\t\tpl = m_dlist;\n\t\telse\n\t\t\tpl = m_info->m_plist;\n\t\tSTRING\ts = STRING(*(*m_mlist)[0]->bus_prefix());\n\t\tint\taw = address_width();\n\n\t\tif (!m_is_double)\n\t\t\ts = (*n) + \"_dio\";\n\n\t\tfprintf(fp,\n\t\t\t\"\\t//\\n\"\n\t\t\t\"\\t// %s Bus logic to handle %ld DOUBLE slaves\\n\"\n\t\t\t\"\\t//\\n\"\n\t\t\t\"\\t//\\n\", n->c_str(), pl->size());\n\n\t\tfprintf(fp,\n\t\t\t\"\\t// Some extra wires to capture combined values--values\\n\"\n\t\t\t\"\\t// that will be the same across all slaves of the\\n\"\n\t\t\t\"\\t// class\\n\"\n\t\t\t\"\\twire [0:0]\\t%s_diow_awid;\\n\"\n\t\t\t\"\\twire [%d:0]\\t%s_diow_awaddr;\\n\"\n\t\t\t\"\\twire [7:0]\\t%s_diow_awlen;\\n\"\n\t\t\t\"\\twire [2:0]\\t%s_diow_awsize;\\n\"\n\t\t\t\"\\twire [1:0]\\t%s_diow_awburst;\\n\"\n\t\t\t\"\\twire\\t%s_diow_awlock;\\n\"\n\t\t\t\"\\twire [3:0]\\t%s_diow_awcache;\\n\"\n\t\t\t\"\\twire [2:0]\\t%s_diow_awprot;\\n\"\n\t\t\t\"\\twire [3:0]\\t%s_diow_awqos;\\n\"\n\t\t\t\"\\t//\\n\",\n\t\t\tn->c_str(),\n\t\t\taddress_width()-1, n->c_str(),\n\t\t\tn->c_str(), n->c_str(), n->c_str(), n->c_str(),\n\t\t\tn->c_str(), n->c_str(), n->c_str());\n\n\t\tfprintf(fp,\n\t\t\t\"\\twire [%d:0]\\t%s_diow_wdata;\\n\"\n\t\t\t\"\\twire [%d:0]\\t%s_diow_wstrb;\\n\"\n\t\t\t\"\\twire\\t%s_diow_wlast;\\n\"\n\t\t\t\"\\t//\\n\"\n\t\t\t\"\\twire\\t%s_diow_bready;\\n\"\n\t\t\t\"\\t//\\n\",\n\t\t\tm_info->data_width()-1, n->c_str(),\n\t\t\tm_info->data_width()/8-1, n->c_str(),\n\t\t\tn->c_str(), n->c_str());\n\n\t\tfprintf(fp,\n\t\t\t\"\\twire [0:0]\\t%s_diow_arid;\\n\"\n\t\t\t\"\\twire [%d:0]\\t%s_diow_araddr;\\n\"\n\t\t\t\"\\twire [7:0]\\t%s_diow_arlen;\\n\"\n\t\t\t\"\\twire [2:0]\\t%s_diow_arsize;\\n\"\n\t\t\t\"\\twire [1:0]\\t%s_diow_arburst;\\n\\n\"\n\t\t\t\"\\twire\\t%s_diow_arlock;\\n\"\n\t\t\t\"\\twire [3:0]\\t%s_diow_arcache;\\n\"\n\t\t\t\"\\twire [2:0]\\t%s_diow_arprot;\\n\"\n\t\t\t\"\\twire [3:0]\\t%s_diow_arqos;\\n\"\n\t\t\t\"\\t//\\n\"\n\t\t\t\"\\twire\\t%s_diow_rready;\\n\"\n\t\t\t\"\\t//\\n\",\n\t\t\tn->c_str(),\n\t\t\taddress_width()-1, n->c_str(),\n\t\t\tn->c_str(), n->c_str(), n->c_str(), n->c_str(),\n\t\t\tn->c_str(), n->c_str(), n->c_str(), n->c_str());\n\n\t\tfprintf(fp,\n\t\t\"\\taxidouble #(\\n\"\n\t\t\t\"\\t\\t// {{{\\n\"\n\t\t\t\"\\t\\t.C_AXI_ADDR_WIDTH(%d),\\n\"\n\t\t\t\"\\t\\t.C_AXI_DATA_WIDTH(%d),\\n\"\n\t\t\t\"\\t\\t.C_AXI_ID_WIDTH(%d),\\n\"\n\t\t\t\"\\t\\t.NS(%ld),\\n\",\n\t\t\taddress_width(), m_info->data_width(),\n\t\t\tid_width(), pl->size());\n\t\txbar_option(fp, KY_OPT_LOWPOWER,  \"\\t\\t.OPT_LOWPOWER(%),\\n\",\n\t\t\t\"1\\'b1\");\n\t\tslave_addr(fp, pl); fprintf(fp, \",\\n\");\n\t\tslave_mask(fp, pl); fprintf(fp, \"\\n\");\n\t\tfprintf(fp,\n\t\t\"\\t\\t// }}}\\n\"\n\t\t\"\\t) %s_axidouble(\\n\",\n\t\t\tn->c_str());\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t// {{{\\n\"\n\t\t\t\"\\t\\t.S_AXI_ACLK(%s),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARESETN(%s),\\n\",\n\t\t\t\tc->m_wire->c_str(), rst->c_str());\n\n\t\tfprintf(fp, \"\\t\\t//\\n\");\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t// Slave port\\n\"\n\t\t\t\"\\t\\t// {{{\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWVALID(%s_awvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWREADY(%s_awready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWID(   %s_awid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWADDR( %s_awaddr[%d:0]),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWLEN(  %s_awlen),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWSIZE( %s_awsize),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWBURST(%s_awburst),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWLOCK( %s_awlock),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWCACHE(%s_awcache),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWPROT( %s_awprot),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWQOS(  %s_awqos),\\n\"\n\t\t\t\"\\t\\t//\\n\"\n\t\t\t\"\\t\\t.S_AXI_WVALID( %s_wvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_WREADY( %s_wready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_WDATA(  %s_wdata),\\n\"\n\t\t\t\"\\t\\t.S_AXI_WSTRB(  %s_wstrb),\\n\"\n\t\t\t\"\\t\\t.S_AXI_WLAST(  %s_wlast),\\n\"\n\t\t\t\"\\t\\t//\\n\"\n\t\t\t\"\\t\\t.S_AXI_BVALID( %s_bvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_BREADY( %s_bready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_BID(    %s_bid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_BRESP(  %s_bresp),\\n\"\n\t\t\t\"\\t\\t//\\n\",\n\t\t\t// AW\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str(), aw-1,\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str(),\n\t\t\ts.c_str(), s.c_str(), s.c_str(),\n\t\t\t// W\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str(),\n\t\t\ts.c_str(),\n\t\t\t// B\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str());\n\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t// Read connections\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARVALID(%s_arvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARREADY(%s_arready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARID(   %s_arid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARADDR( %s_araddr[%d:0]),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARLEN(  %s_arlen),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARSIZE( %s_arsize),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARBURST(%s_arburst),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARLOCK( %s_arlock),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARCACHE(%s_arcache),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARPROT( %s_arprot),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARQOS(  %s_arqos),\\n\"\n\t\t\t\"\\t\\t//\\n\"\n\t\t\t\"\\t\\t.S_AXI_RVALID( %s_rvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_RREADY( %s_rready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_RID(    %s_rid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_RDATA(  %s_rdata),\\n\"\n\t\t\t\"\\t\\t.S_AXI_RLAST(  %s_rlast),\\n\"\n\t\t\t\"\\t\\t.S_AXI_RRESP(  %s_rresp),\\n\"\n\t\t\t\"\\t\\t// }}}\\n\"\n\t\t\t\"\\t\\t// Connections to slaves\\n\"\n\t\t\t\"\\t\\t// {{{\\n\",\n\t\t\t// AR\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str(), aw-1,\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str(),\n\t\t\ts.c_str(), s.c_str(), s.c_str(),\n\t\t\t// R\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str(),\n\t\t\ts.c_str(), s.c_str());\n\n\t\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWVALID\");\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t.M_AXI_AWID(   %s_diow_awid),  // == 1\\'b0\\n\"\n\t\t\t\"\\t\\t.M_AXI_AWADDR( %s_diow_awaddr),\\n\"\n\t\t\t\"\\t\\t.M_AXI_AWLEN(  %s_diow_awlen), // == 0\\n\"\n\t\t\t\"\\t\\t.M_AXI_AWSIZE( %s_diow_awsize),\\n\"\n\t\t\t\"\\t\\t.M_AXI_AWBURST(%s_diow_awburst), // ==INC==2\\'b01\\n\"\n\t\t\t\"\\t\\t.M_AXI_AWLOCK( %s_diow_awlock), // == 0\\n\"\n\t\t\t\"\\t\\t.M_AXI_AWCACHE(%s_diow_awcache),\\n\"\n\t\t\t\"\\t\\t.M_AXI_AWPROT( %s_diow_awprot),\\n\"\n\t\t\t\"\\t\\t.M_AXI_AWQOS(  %s_diow_awqos),\\n\",\n\t\t\tn->c_str(), n->c_str(), n->c_str(), n->c_str(),\n\t\t\tn->c_str(), n->c_str(), n->c_str(), n->c_str(),\n\t\t\tn->c_str());\n\n\t\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"WVALID\");\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t.M_AXI_WDATA(  %s_diow_wdata),\\n\"\n\t\t\t\"\\t\\t.M_AXI_WSTRB(  %s_diow_wstrb),\\n\"\n\t\t\t\"\\t\\t.M_AXI_WLAST(  %s_diow_wlast), // == 1\\n\",\n\t\t\tn->c_str(), n->c_str(), n->c_str());\n\t\tfprintf(fp, \"\\t\\t//\\n\");\n\t\tfprintf(fp, \"\\t\\t//\\n\");\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t.M_AXI_BREADY(  %s_diow_bready),\\n\", n->c_str());\n\t\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"BRESP\");\n\t\tfprintf(fp, \"\\t\\t// Read connections\\n\");\n\t\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARVALID\");\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t.M_AXI_ARID(   %s_diow_arid),  // == 1\\'b0\\n\"\n\t\t\t\"\\t\\t.M_AXI_ARADDR( %s_diow_araddr),\\n\"\n\t\t\t\"\\t\\t.M_AXI_ARLEN(  %s_diow_arlen), // == 0\\n\"\n\t\t\t\"\\t\\t.M_AXI_ARSIZE( %s_diow_arsize),\\n\"\n\t\t\t\"\\t\\t.M_AXI_ARBURST(%s_diow_arburst),//==INC==2\\'b01\\n\"\n\t\t\t\"\\t\\t.M_AXI_ARLOCK( %s_diow_arlock),// == 0\\n\"\n\t\t\t\"\\t\\t.M_AXI_ARCACHE(%s_diow_arcache),//== 0\\n\"\n\t\t\t\"\\t\\t.M_AXI_ARPROT( %s_diow_arprot),\\n\"\n\t\t\t\"\\t\\t.M_AXI_ARQOS(  %s_diow_arqos),  //== 0\\n\"\n\t\t\t\"\\t\\t//\\n\",\n\t\t\tn->c_str(), n->c_str(), n->c_str(),\n\t\t\tn->c_str(), n->c_str(), n->c_str(),\n\t\t\tn->c_str(), n->c_str(), n->c_str());\n\n\t\t// Read returns\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t.M_AXI_RREADY(  %s_diow_rready),\\n\", n->c_str());\n\t\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"RDATA\");\n\t\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"RRESP\", false);\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t// }}}\\n\"\n\t\t\t\"\\t\\t// }}}\\n\"\n\t\t\t\"\\t);\\n\\n\");\n\t\tfprintf(fp,\"\\t//\\n\\t// Now connecting the extra slaves wires \"\n\t\t\t\"to the AXIDOUBLE controller\\n\\t//\\n\");\n\n\t\tfor(int k=pl->size(); k>0; k--) {\n\t\t\tPERIPHP p = (*pl)[k-1];\n\t\t\tconst char *pn = p->p_name->c_str(),\n\t\t\t\t*pfx = p->bus_prefix()->c_str();\n\t\t\tint\t// aw = p->p_awid + unused_lsbs,\n\t\t\t\tiw = id_width();\n\n\t\t\tfprintf(fp, \"\\t// %s\\n\"\n\t\t\t\t\"\\t// {{{\\n\", pn);\n\t\t\tfprintf(fp, \"\\tassign %s_awid   = {(%d){1\\'b0}};\\n\", pfx, iw);\n\t\t\tfprintf(fp, \"\\tassign %s_awaddr = %s_diow_awaddr;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_awlen  = %s_diow_awlen;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_awsize = %s_diow_awsize;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_awburst= %s_diow_awburst;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_awlock = %s_diow_awlock;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_awcache= %s_diow_awcache;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_awprot = %s_diow_awprot;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_awqos  = %s_diow_awqos;\\n\", pfx, n->c_str());\n\t\t\t//\n\t\t\tfprintf(fp, \"\\tassign %s_wdata  = %s_diow_wdata;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_wstrb  = %s_diow_wstrb;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_wlast  = %s_diow_wlast;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_bready = 1\\'b1;\\n\", pfx);\n\t\t\t// arready is set by the slave ... and ignored\n\t\t\tfprintf(fp, \"\\tassign %s_arid   = {(%d){1\\'b0}};\\n\", pfx, iw);\n\t\t\tfprintf(fp, \"\\tassign %s_araddr = %s_diow_araddr;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_arlen  = %s_diow_arlen;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_arsize = %s_diow_arsize;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_arburst= %s_diow_arburst;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_arlock = %s_diow_arlock;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_arcache= %s_diow_arcache;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_arprot = %s_diow_arprot;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_arqos  = %s_diow_arqos;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_arprot = %s_diow_arprot;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_arprot = %s_diow_arprot;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_rready = 1\\'b1;\\n\"\n\t\t\t\t\"\\t// }}}\\n\", pfx);\n\t\t}\n\n\t\tif (m_is_double)\n\t\t\treturn;\n\t\t// }}}\n\t} else if (!m_dlist)\n\t\tfprintf(fp, \"\\t//\\n\\t// No class DOUBLE peripherals on the \\\"%s\\\" bus\\n\\t//\\n\\n\", n->c_str());\n\n\t//\n\t//\n\t// Now for the main set of slaves\n\t//\n\t//\n\tpl = m_info->m_plist;\n\n\tunsigned\tslave_name_width = 4;\n\t// Find the maximum width of any slaves name, for our comment tables\n\t// below\n\tfor(unsigned k=0; k<m_info->m_plist->size(); k++) {\n\t\tPERIPHP\tp = (*m_info->m_plist)[k];\n\t\tunsigned\tsz;\n\n\t\tsz = p->name()->size();\n\t\tif (slave_name_width < sz)\n\t\t\tslave_name_width = sz;\n\t}\n\n\t//\n\t// Now create the crossbar interconnect\n\t//\n\tfprintf(fp,\n\t\"\\t////////////////////////////////////////////////////////////////////////\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// Connect the %s bus components together using the axixbar()\\n\"\n\t\"\\t// {{{\\n\"\n\t\"\\t//\\n\", n->c_str());\n\n\tfprintf(fp,\n\t\"\\taxixbar #(\\n\"\n\t\"\\t\\t// {{{\\n\"\n\t\"\\t\\t.C_AXI_ADDR_WIDTH(%d),\\n\"\n\t\"\\t\\t.C_AXI_DATA_WIDTH(%d),\\n\"\n\t\"\\t\\t.C_AXI_ID_WIDTH(%d),\\n\"\n\t\"\\t\\t.NM(%ld), .NS(%ld),\\n\",\n\t\taddress_width(),\n\t\tm_info->data_width(),\n\t\tid_width(),\n\t\tm_mlist->size(),\n\t\tm_info->m_plist->size());\n\t/*\n\tfprintf(fp,\n\t\"\\t\\t.READ_ACCESS(%ld\\'b\", m_info->m_plist->size());\n\tfor(unsigned k=0; k<m_info->m_plist->size(); k++) {\n\t\tPERIPHP p = (*m_info->m_plist)[k];\n\t\tif (p->write_only()) {\n\t\t\tputc('0', fp);\n\t\t\tif (p->read_only())\n\t\t\t\tgbl_msg.error(\"Slave %s cannot be both write-only and read-only\\n\", p->name()->c_str());\n\t\t} else\n\t\t\tputc('1', fp);\n\t} fprintf(fp, \"),\\n\\t\\t.WRITE_ACCESS(%ld\\'b\", m_info->m_plist->size());\n\tfor(unsigned k=0; k<m_info->m_plist->size(); k++) {\n\t\tPERIPHP p = (*m_info->m_plist)[k];\n\t\tif (p->write_only())\n\t\t\tputc('0', fp);\n\t\telse\n\t\t\tputc('1', fp);\n\t} fprintf(fp, \"),\\n\");\n\t*/\n\n\tslave_addr(fp, m_info->m_plist); fprintf(fp, \",\\n\");\n\tslave_mask(fp, m_info->m_plist);\n\n\txbar_option(fp, KY_OPT_LOWPOWER,  \",\\n\\t\\t.OPT_LOWPOWER(%)\", \"1\\'b1\");\n\txbar_option(fp, KY_OPT_LINGER,    \",\\n\\t\\t.OPT_LINGER(%)\");\n\txbar_option(fp, KY_OPT_LGMAXBURST,\",\\n\\t\\t.LGMAXBURST(%)\");\n\t//\n\tfprintf(fp,\n\t\"\\n\\t\\t// }}}\\n\"\n\t\"\\t) %s_xbar(\\n\"\n\t\t\"\\t\\t// {{{\\n\"\n\t\t\"\\t\\t.S_AXI_ACLK(%s),\\n\",\n\t\tn->c_str(), m_info->m_clock->m_wire->c_str());\n\tfprintf(fp, \"\\t\\t.S_AXI_ARESETN(%s),\\n\", rst->c_str());\n\n\tfprintf(fp, \"\\t\\t// Connections from masters\\n\"\n\t\t\"\\t\\t// {{{\\n\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"AWVALID\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"AWREADY\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"AWID\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"AWADDR\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"AWLEN\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"AWSIZE\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"AWBURST\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"AWLOCK\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"AWCACHE\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"AWPROT\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"AWQOS\");\n\tfprintf(fp, \"\\t\\t//\\n\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"WVALID\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"WREADY\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"WDATA\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"WSTRB\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"WLAST\");\n\tfprintf(fp, \"\\t\\t//\\n\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"BVALID\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"BREADY\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"BID\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"BRESP\");\n\n\tfprintf(fp, \"\\t\\t//\\n\");\n\tfprintf(fp, \"\\t\\t// Read connections\\n\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"ARVALID\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"ARREADY\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"ARID\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"ARADDR\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"ARLEN\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"ARSIZE\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"ARBURST\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"ARLOCK\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"ARCACHE\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"ARPROT\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"ARQOS\");\n\tfprintf(fp, \"\\t\\t//\\n\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"RVALID\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"RREADY\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"RID\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"RDATA\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"RLAST\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"RRESP\");\n\tfprintf(fp, \"\\t\\t// }}}\\n\");\n\tfprintf(fp, \"\\t\\t// Connections to slaves\\n\");\n\tfprintf(fp, \"\\t\\t// {{{\\n\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWVALID\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWREADY\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWID\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWADDR\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWLEN\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWSIZE\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWBURST\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWLOCK\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWCACHE\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWPROT\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWQOS\");\n\tfprintf(fp, \"\\t\\t//\\n\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"WVALID\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"WREADY\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"WDATA\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"WSTRB\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"WLAST\");\n\tfprintf(fp, \"\\t\\t//\\n\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"BVALID\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"BREADY\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"BID\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"BRESP\");\n\tfprintf(fp, \"\\t\\t//\\n\");\n\tfprintf(fp, \"\\t\\t// Read connections\\n\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARVALID\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARREADY\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARID\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARADDR\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARLEN\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARSIZE\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARBURST\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARLOCK\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARCACHE\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARPROT\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARQOS\");\n\tfprintf(fp, \"\\t\\t//\\n\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"RVALID\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"RREADY\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"RID\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"RDATA\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"RLAST\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"RRESP\", false);\n\tfprintf(fp, \"\\t\\t// }}}\\n\"\n\t\t\"\\t\\t// }}}\\n\\t);\\n\\n\");\n\n\tfor(unsigned k=0; k < m_info->m_plist->size(); k++) {\n\t\t// Handle read only or write only slaves\n\t\t// {{{\n\t\tPERIPHP p = (*m_info->m_plist)[k];\n\t\tSTRINGP\tbusp = p->bus_prefix();\n\t\tconst char\t*bp = busp->c_str();\n\n\t\tif (p->write_only()) {\n\t\t\tfprintf(fp,\n\t\"\\taxiempty #(\\n\"\n\t\"\\t\\t// {{{\\n\"\n\t\"\\t\\t.C_AXI_ADDR_WIDTH(%d),\\n\"\n\t\"\\t\\t.C_AXI_DATA_WIDTH(%d),\\n\"\n\t\"\\t\\t.C_AXI_ID_WIDTH(%d)\\n\"\n\t\"\\t\\t// }}}\\n\",\n\t\t\t\taddress_width(),\n\t\t\t\tm_info->data_width(),\n\t\t\t\tid_width());\n\t\t\tfprintf(fp,\n\t\"\\t) %s_no_slavep (\\n\"\n\t\t\"\\t\\t// {{{\\n\"\n\t\t\"\\t\\t.S_AXI_ACLK(%s), .S_AXI_ARESETN(%s),\\n\"\n\t\t\"\\t\\t//\\n\",\n\t\t\tbp, c->m_wire->c_str(), rst->c_str());\n\n\t\t\tfprintf(fp,\n\t\t\"\\t\\t// Verilator lint_off PINCONNECTEMPTY\\n\"\n\t\t\"\\t\\t.S_AXI_AWVALID(1\\'b0), .S_AXI_AWREADY(),\\n\"\n\t\t\"\\t\\t.S_AXI_WVALID(1\\'b0),  .S_AXI_WREADY(),\\n\"\n\t\t\"\\t\\t.S_AXI_WLAST(1\\'b0),\\n\"\n\t\t\"\\t\\t//\\n\"\n\t\t\"\\t\\t.S_AXI_BVALID(),   .S_AXI_BREADY(1\\'b1),\\n\"\n\t\t\"\\t\\t.S_AXI_BID(), .S_AXI_BRESP(),\\n\"\n\t\t\"\\t\\t// Verilator lint_on PINCONNECTEMPTY\\n\"\n\t\t\"\\t\\t//\\n\"\n\t\t\"\\t\\t.S_AXI_ARVALID(%s_arvalid), .S_AXI_ARREADY(%s_arready),\\n\"\n\t\t\"\\t\\t.S_AXI_ARID(%s_arid), .S_AXI_ARLEN(%s_arlen),\\n\"\n\t\t\"\\t\\t.S_AXI_RVALID(%s_rvalid),   .S_AXI_RREADY(%s_rready),\\n\"\n\t\t\"\\t\\t.S_AXI_RDATA(%s_rdata),   .S_AXI_RLAST(%s_rlast),\\n\"\n\t\t\"\\t\\t.S_AXI_RRESP(%s_rresp)\\n\"\n\t\t\"\\t\\t// }}}\\n\"\n\t\t\"\\t);\\n\\n\",\n\t\t\t\t// AW, W, B\n\t\t\t\t//\n\t\t\t\tbp, bp, bp, bp,\n\t\t\t\tbp, bp, bp, bp, bp);\n\n\t\t}\n\t\tif (p->read_only()) {\n\n\t\t\tfprintf(fp,\n\t\"\\taxiempty #(\\n\"\n\t\"\\t\\t// {{{\\n\"\n\t\"\\t\\t.C_AXI_ADDR_WIDTH(%d),\\n\"\n\t\"\\t\\t.C_AXI_DATA_WIDTH(%d),\\n\"\n\t\"\\t\\t.C_AXI_ID_WIDTH(%d)\\n\"\n\t\"\\t\\t// }}}\\n\",\n\t\t\t\taddress_width(),\n\t\t\t\tm_info->data_width(),\n\t\t\t\tid_width());\n\t\t\tfprintf(fp,\n\t\"\\t) %s_no_slavep (\\n\"\n\t\t\"\\t\\t// {{{\\n\"\n\t\t\"\\t\\t.S_AXI_ACLK(%s), .S_AXI_ARESETN(%s),\\n\"\n\t\t\"\\t\\t//\\n\",\n\t\t\tbp, c->m_wire->c_str(), rst->c_str());\n\n\t\t\tfprintf(fp,\n\t\t\"\\t\\t.S_AXI_AWVALID(%s_awvalid), .S_AXI_AWREADY(%s_awready),\\n\"\n\t\t\"\\t\\t\\t.S_AXI_AWID(%s_awid),\\n\"\n\t\t\"\\t\\t.S_AXI_WVALID(%s_wvalid),  .S_AXI_WREADY(%s_wready),\\n\"\n\t\t\"\\t\\t.S_AXI_WLAST(%s_wlast),\\n\"\n\t\t\"\\t\\t//\\n\"\n\t\t\"\\t\\t.S_AXI_BVALID(%s_bvalid),   .S_AXI_BREADY(%s_bready),\\n\"\n\t\t\"\\t\\t.S_AXI_BID(%s_bid), .S_AXI_BRESP(%s_bresp),\\n\"\n\t\t\"\\t\\t//\\n\"\n\t\t\"\\t\\t// Verilator lint_off PINCONNECTEMPTY\\n\"\n\t\t\"\\t\\t.S_AXI_ARVALID(1\\'b0), .S_AXI_ARREADY(),\\n\"\n\t\t\"\\t\\t.S_AXI_ARID(0), .S_AXI_ARLEN(8'h00),\\n\"\n\t\t\"\\t\\t//\\n\"\n\t\t\"\\t\\t.S_AXI_RVALID(),   .S_AXI_RREADY(1\\'b1),\\n\"\n\t\t\"\\t\\t.S_AXI_RDATA(),   .S_AXI_RLAST(),\\n\"\n\t\t\"\\t\\t.S_AXI_RRESP()\\n\"\n\t\t\"\\t\\t// Verilator lint_on PINCONNECTEMPTY\\n\"\n\t\t\"\\t\\t// }}}\\n\"\n\t\t\"\\t);\\n\\n\",\n\t\t\t\t// AW, W\n\t\t\t\tbp, bp, bp, bp, bp, bp,\n\t\t\t\t// B\n\t\t\t\tbp, bp, bp, bp);\n\t\t}\n\t\t// }}}\n\t}\n\tfprintf(fp, \"\\t\\t// }}}\\n\");\n}\n\nSTRINGP\tAXIBUS::master_portlist(BMASTERP m) {\n\t// {{{\n\tSTRING\tstr;\n\n\tif (m->write_only())\n\t\tstr = str + STRING(\"// Master is write-only\\n\");\n\tif (m->read_only())\n\t\tstr = str + STRING(\"// Master is read only\\n\\t\\t\");\n\telse\n\t\tstr = str + STRING(\n\t\"@$(MASTER.PREFIX)_awvalid,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_awready,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_awid,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_awaddr[@$(MASTER.BUS.AWID)-1:0],\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_awlen,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_awsize,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_awburst,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_awlock,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_awcache,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_awprot,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_awqos,\\n\"\n\t\"\\t\\t//\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_wvalid,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_wready,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_wdata,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_wstrb,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_wlast,\\n\"\n\t\"\\t\\t//\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_bvalid,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_bready,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_bid,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_bresp\");\n\tif (!m->read_only() && !m->write_only())\n\t\tstr = str + STRING(\",\\n\\t\\t// Read connections\\n\\t\\t\");\n\tif (!m->write_only())\n\t\tstr = str + STRING(\n\t\"@$(MASTER.PREFIX)_arvalid,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_arready,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_arid,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_araddr[@$(MASTER.BUS.AWID)-1:0],\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_arlen,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_arsize,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_arburst,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_arlock,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_arcache,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_arprot,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_arqos,\\n\"\n\t\"\\t\\t//\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_rvalid,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_rready,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_rid,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_rdata,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_rlast,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_rresp\");\n\n\treturn new STRING(str);\n}\n// }}}\n\nSTRINGP\tAXIBUS::iansi(BMASTERP m) {\n\treturn new STRING(\"\");\n}\n\nSTRINGP\tAXIBUS::oansi(BMASTERP m) {\n\treturn new STRING(\"\");\n}\n\nSTRINGP\tAXIBUS::master_ansprefix(BMASTERP m) {\n\treturn new STRING(\"M_AXI_\");\n}\n\nSTRINGP\tAXIBUS::master_ansi_portlist(BMASTERP m) {\n\t// {{{\n\tSTRING\tstr;\n\n\tif (!m->read_only())\n\t\tstr = str + STRING(\n\t\".@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)AWVALID(@$(MASTER.PREFIX)_awvalid),\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)AWREADY(@$(MASTER.PREFIX)_awready),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)AWID(   @$(MASTER.PREFIX)_awid),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)AWADDR( @$(MASTER.PREFIX)_awaddr[@$(MASTER.BUS.AWID)-1:0]),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)AWLEN(  @$(MASTER.PREFIX)_awlen),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)AWSIZE( @$(MASTER.PREFIX)_awsize),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)AWBURST(@$(MASTER.PREFIX)_awburst),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)AWLOCK( @$(MASTER.PREFIX)_awlock),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)AWCACHE(@$(MASTER.PREFIX)_awcache),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)AWPROT( @$(MASTER.PREFIX)_awprot),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)AWQOS(  @$(MASTER.PREFIX)_awqos),\\n\"\n\t\"\\t\\t//\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)WVALID(@$(MASTER.PREFIX)_wvalid),\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)WREADY(@$(MASTER.PREFIX)_wready),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)WDATA( @$(MASTER.PREFIX)_wdata),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)WSTRB( @$(MASTER.PREFIX)_wstrb),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)WLAST( @$(MASTER.PREFIX)_wlast),\\n\"\n\t\"\\t\\t//\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)BVALID(@$(MASTER.PREFIX)_bvalid),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)BREADY(@$(MASTER.PREFIX)_bready),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)BID(   @$(MASTER.PREFIX)_bid),\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)BRESP( @$(MASTER.PREFIX)_bresp)\");\n\tif (!m->read_only() && !m->write_only())\n\t\tstr = str + STRING(\",\\n\\t\\t// Read connections\\n\\t\\t\");\n\tif (!m->write_only())\n\t\tstr = str + STRING(\n\t\".@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)ARVALID(@$(MASTER.PREFIX)_arvalid),\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)ARREADY(@$(MASTER.PREFIX)_arready),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)ARID(   @$(MASTER.PREFIX)_arid),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)ARADDR( @$(MASTER.PREFIX)_araddr[@$(MASTER.BUS.AWID)-1:0]),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)ARLEN(  @$(MASTER.PREFIX)_arlen),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)ARSIZE( @$(MASTER.PREFIX)_arsize),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)ARBURST(@$(MASTER.PREFIX)_arburst),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)ARLOCK( @$(MASTER.PREFIX)_arlock),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)ARCACHE(@$(MASTER.PREFIX)_arcache),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)ARPROT( @$(MASTER.PREFIX)_arprot),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)ARQOS(  @$(MASTER.PREFIX)_arqos),\\n\"\n\t\"//\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)RVALID(@$(MASTER.PREFIX)_rvalid),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)RREADY(@$(MASTER.PREFIX)_rready),\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)RID(   @$(MASTER.PREFIX)_rid),\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)RDATA( @$(MASTER.PREFIX)_rdata),\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)RLAST( @$(MASTER.PREFIX)_rlast),\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)RRESP( @$(MASTER.PREFIX)_rresp)\");\n\n\treturn new STRING(str);\n}\n// }}}\n\nSTRINGP\tAXIBUS::slave_ansprefix(PERIPHP p) {\n\treturn new STRING(\"S_AXI_\");\n}\n\nSTRINGP\tAXIBUS::slave_portlist(PERIPHP p) {\n\t// {{{\n\tSTRING\tstr;\n\n\tif (p->write_only())\n\t\tstr = str + STRING(\"// Slave is write-only\\n\\t\\t\");\n\tif (p->read_only())\n\t\tstr = str + STRING(\"// Slave is read only\\n\\t\\t\");\n\telse {\n\t\tstr = str + STRING(\n\t\"//\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_awvalid,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_awready,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_awid,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_awaddr[\")\n\t\t+ std::to_string(p->get_slave_address_width())\n\t\t+ STRING(\"-1:0],\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_awlen,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_awsize,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_awburst,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_awlock,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_awcache,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_awprot,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_awqos,\\n\"\n\t\"//\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_wvalid,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_wready,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_wdata,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_wstrb,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_wlast,\\n\"\n\t\"//\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_bvalid,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_bready,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_bid,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_bresp\");\n\t}\n\tif (!p->read_only() && !p->write_only())\n\t\tstr = str + STRING(\",\\n\\t\\t// Read connections\\n\");\n\tif (!p->write_only())\n\t\tstr = str + STRING(\n\t\"\\t\\t@$(SLAVE.PREFIX)_arvalid,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_arready,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_arid,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_araddr[\")\n\t\t+ std::to_string(p->get_slave_address_width())\n\t\t+ STRING(\"-1:0],\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_arlen,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_arsize,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_arburst,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_arlock,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_arcache,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_arprot,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_arqos,\\n\"\n\t\"//\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_rvalid,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_rready,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_rid,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_rdata,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_rlast,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_rresp\");\n\n\treturn new STRING(str);\n}\n// }}}\n\nSTRINGP\tAXIBUS::slave_ansi_portlist(PERIPHP p) {\n\t// {{{\n\tSTRING\tstr;\n\n\tif (!p->read_only())\n\t\tstr = str + STRING(\n\t\".@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)AWVALID(@$(SLAVE.PREFIX)_awvalid),\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)AWREADY(@$(SLAVE.PREFIX)_awready),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)AWID(   @$(SLAVE.PREFIX)_awid),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)AWADDR( @$(SLAVE.PREFIX)_awaddr[\")\n\t\t+ std::to_string(p->get_slave_address_width())\n\t\t+ STRING(\"-1:0]),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)AWLEN(  @$(SLAVE.PREFIX)_awlen),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)AWSIZE( @$(SLAVE.PREFIX)_awsize),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)AWBURST(@$(SLAVE.PREFIX)_awburst),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)AWLOCK( @$(SLAVE.PREFIX)_awlock),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)AWCACHE(@$(SLAVE.PREFIX)_awcache),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)AWPROT( @$(SLAVE.PREFIX)_awprot),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)AWQOS(  @$(SLAVE.PREFIX)_awqos),\\n\"\n\t\"\\t\\t//\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)WVALID(@$(SLAVE.PREFIX)_wvalid),\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)WREADY(@$(SLAVE.PREFIX)_wready),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)WDATA( @$(SLAVE.PREFIX)_wdata),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)WSTRB( @$(SLAVE.PREFIX)_wstrb),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)WLAST( @$(SLAVE.PREFIX)_wlast),\\n\"\n\t\"\\t\\t//\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)BVALID(@$(SLAVE.PREFIX)_bvalid),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)BREADY(@$(SLAVE.PREFIX)_bready),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)BID(   @$(SLAVE.PREFIX)_bid),\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)BRESP( @$(SLAVE.PREFIX)_bresp)\");\n\tif (!p->read_only() && !p->write_only())\n\t\tstr = str + STRING(\",\\n\\t\\t// Read connections\\n\");\n\tif (!p->write_only())\n\t\tstr = str + STRING(\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)ARVALID(@$(SLAVE.PREFIX)_arvalid),\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)ARREADY(@$(SLAVE.PREFIX)_arready),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)ARID(   @$(SLAVE.PREFIX)_arid),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)ARADDR( @$(SLAVE.PREFIX)_araddr[\")\n\t\t+ std::to_string(p->get_slave_address_width())\n\t\t+ STRING(\"-1:0]),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)ARLEN(  @$(SLAVE.PREFIX)_arlen),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)ARSIZE( @$(SLAVE.PREFIX)_arsize),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)ARBURST(@$(SLAVE.PREFIX)_arburst),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)ARLOCK( @$(SLAVE.PREFIX)_arlock),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)ARCACHE(@$(SLAVE.PREFIX)_arcache),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)ARPROT( @$(SLAVE.PREFIX)_arprot),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)ARQOS(  @$(SLAVE.PREFIX)_arqos),\\n\"\n\t\"//\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)RVALID(@$(SLAVE.PREFIX)_rvalid),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)RREADY(@$(SLAVE.PREFIX)_rready),\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)RID(   @$(SLAVE.PREFIX)_rid),\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)RDATA( @$(SLAVE.PREFIX)_rdata),\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)RLAST( @$(SLAVE.PREFIX)_rlast),\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)RRESP( @$(SLAVE.PREFIX)_rresp)\");\n\n\treturn new STRING(str);\n}\n// }}}\n\n////////////////////////////////////////////////////////////////////////\n//\n// Bus class logic\n//\n// The bus class describes the logic above in a way that it can be\n// chosen, selected, and enacted within a design.  Hence if a design\n// has four wishbone buses and one AXI4 bus, the bus class logic\n// will recognize the four WB buses and generate WB bus generators,\n// and then an AXI4 bus and bus generator, etc.\n//\n////////////////////////////////////////////////////////////////////////\nSTRINGP\tAXIBUSCLASS::name(void) {\n\treturn new STRING(\"axil\");\n}\n\nSTRINGP\tAXIBUSCLASS::longname(void) {\n\treturn new STRING(\"AXI4\");\n}\n\nbool\tAXIBUSCLASS::matchtype(STRINGP str) {\n\tif (!str)\n\t\t// We are not the default\n\t\treturn false;\n\tif (strcasecmp(str->c_str(), \"axi\")==0)\n\t\treturn true;\n\tif (strcasecmp(str->c_str(), \"axi4\")==0)\n\t\treturn true;\n\tif (strcasecmp(str->c_str(), \"axi4full\")==0)\n\t\treturn true;\n// printf(\"ERR: No match for bus type %s\\n\",str->c_str());\n\treturn false;\n}\n\nbool\tAXIBUSCLASS::matchfail(MAPDHASH *bhash) {\n\treturn false;\n}\n\nGENBUS *AXIBUSCLASS::create(BUSINFO *bi) {\n\tAXIBUS\t*busclass;\n\n\tbusclass = new AXIBUS(bi);\n\treturn busclass;\n}\n"
  },
  {
    "path": "sw/bus/axi.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bus/axi.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tAXI4 (full) interface--for high speed AXI4 cores--or any AXI4\n//\t\tspecification compliant cores.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tAXI_H\n#define\tAXI_H\n\n#include \"../genbus.h\"\n#include \"axil.h\"\n\nclass\tAXIBUS : public AXILBUS {\n\tint\t\tm_id_width;\n\t// PLIST\t\t*m_slist, *m_dlist;\n\t// MAPDHASH\t*m_interconnect;\n\t// unsigned\tm_num_total, m_num_double, m_num_single;\n\t// bool\t\tm_is_single, m_is_double;\n\n\t// void\txbarcon_master(FILE *fp, const char *, const char *,\n\t//\t\tconst char *, bool comma=true);\n\t// void\txbarcon_slave(FILE *fp, PLIST *pl,\n\t//\t\tconst char *, const char *, const char *, bool comma=true);\n\t// virtual\tSTRINGP\tmaster_name(int k);\n\tvoid\tallocate_subbus(void);\n\n\tBUSINFO *create_sio(void);\n\tBUSINFO *create_dio(void);\n\t// void\tcountsio(void);\npublic:\n\tAXIBUS(BUSINFO *bi);\n\t~AXIBUS() {};\n\tvirtual\tint\tid_width(void);\n\tvirtual\tint\taddress_width(void);\n\tvirtual\tbool\tword_addressing(void) { return false; };\n\t//\n\tvirtual\tvoid\tassign_addresses(void);\n\tvirtual\tbool\tget_base_address(MAPDHASH *phash, unsigned &base);\n\n\t// void\t\twrite_addr_range(FILE *fp, const PERIPHP p,\n\t//\t\t\tconst int dalines);\n\tvirtual\tvoid\twriteout_defn_v(FILE *fp, const char *mstype,\n\t\t\t\tconst char *pname,\n\t\t\t\tconst char *busp, const char *btyp = \"\");\n\tvirtual\tvoid\twriteout_bus_slave_defns_v(FILE *fp);\n\tvirtual\tvoid\twriteout_bus_master_defns_v(FILE *fp);\n\n\tvirtual\tvoid\twriteout_bus_logic_v(FILE *fp);\n\n\t// virtual\tvoid\twriteout_no_slave_v(FILE *fp, STRINGP prefix);\n\t// virtual\tvoid\twriteout_no_master_v(FILE *fp);\n\t//\n\t//\n\tvirtual\tSTRINGP\tiansi(BMASTERP);\n\tvirtual\tSTRINGP\toansi(BMASTERP);\n\tvirtual\tSTRINGP\tmaster_ansprefix(BMASTERP);\n\tvirtual\tSTRINGP\tmaster_portlist(BMASTERP);\n\tvirtual\tSTRINGP\tmaster_ansi_portlist(BMASTERP);\n\tvirtual\tSTRINGP\tslave_ansprefix(PERIPHP);\n\tvirtual\tSTRINGP\tslave_portlist(PERIPHP);\n\tvirtual\tSTRINGP\tslave_ansi_portlist(PERIPHP);\n\n\t// virtual\tvoid\tintegrity_check(void);\n};\n\nclass\tAXIBUSCLASS : public BUSCLASS {\npublic:\n\tvirtual\tSTRINGP\tname(void);\t// i.e. WB\n\tvirtual\tSTRINGP\tlongname(void);\t// i.e. \"Wishbone\"\n\tvirtual\tbool\tmatchtype(STRINGP strp);\n\tvirtual\tbool\tmatchfail(MAPDHASH *);\n\t// virtual\tbool\tmatches(BUSINFO *bi);\n\tGENBUS\t*create(BUSINFO *bi);\n};\n\n#endif\n"
  },
  {
    "path": "sw/bus/axil.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bus/axil.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\n// Tags used:\n//\n//\tBUS.WIDTH\n//\tBUS.AWID\n//\n//\tSLAVE.TYPE:\n//\t- SINGLE\n//\t- DOUBLE\n//\t- OTHER/MEMORY/BUS\n//\tSLAVE.OPTIONS=\n//\t// string of case-insensitive options\n//\t\tROM\t(slave has no write ports)\n//\t\tWOM\t(slave has no read ports)\n//\t\tFULL\t(default:slave has no all ports, not just the ports used)\n//\tSLAVE.SHARE=\n//\t// slave shares parts of the interface with the other listed slaves\n//\n//\tMASTER.TYPE=\n//\t(currently ignored)\n//\n//\tINTERCONNECT.TYPE\n//\t- SINGLE\n//\t- CROSSBAR\n//\n//\tINTERCONNECT.MASTERS\n//\t= list of the PREFIXs of all of the masters of this bus\n//\n//\tINTERCONNECT.OPTIONS\n//\t= string of case-insensitive options\n//\tOPT_STARVATION_TIMEOUT\n//\tOPT_LOWPOWER\n//\tOPT_DBLBUFFER\n//\n//\n//\tINTERCONNECT.OPTVAL=\n//\t= Options that require values\n//\t- OPT_TIMEOUT\n//\t- LGMAXBURST\n//\n// Creates tags:\n//\n//\tBLIST:\tA list of bus interconnect parameters, somewhat like:\n//\t\t\t@$(SLAVE.BUS)_cyc,\n//\t\t\t@$(SLAVE.BUS)_stb,\n//\t(if !ROM&!WOM)\t@$(SLAVE.BUS)_we,\n//\t(if AWID>0)\t@$(SLAVE.BUS)_addr[@$(SLAVE.AWID)-1:0],\n//\t(if !ROM)\t@$(SLAVE.BUS)_data,\n//\t(if !ROM)\t@$(SLAVE.BUS)_sel,\n//\t\t\t@$(PREFIX)_stall,\n//\t\t\t@$(PREFIX)_ack,\n//\t(if !WOM)\t@$(PREFIX)_data,\n//\t(and possibly)\t@$(PREFIX)_err\n//\n//\tASCBLIST.PREFIX: [%io] prefix\n//\tASCBLIST.SUFFIX:\n//\tASCBLIST.CAPS:\n//\tASCBLIST.DATA:\n//\t\t.@$(ASCBLIST.PREFIX)cyc@$(ASCBLIST.SUFFIX)(@$SLAVE.BUS)_cyc),\n//\t\t.@$(ASCBLIST.PREFIX)stb@$(ASCBLIST.SUFFIX)(@$SLAVE.BUS)_stb),\n//\t\t.@$(ASCBLIST.PREFIX)we@$(ASCBLIST.SUFFIX)(@$SLAVE.BUS)_we),\n//\t\t\t.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <string.h>\n#include <unistd.h>\n#include <ctype.h>\n\n#include \"../parser.h\"\n#include \"../mapdhash.h\"\n#include \"../keys.h\"\n#include \"../kveval.h\"\n#include \"../legalnotice.h\"\n#include \"../bldtestb.h\"\n#include \"../bitlib.h\"\n#include \"../plist.h\"\n#include \"../bldregdefs.h\"\n#include \"../ifdefs.h\"\n#include \"../bldsim.h\"\n#include \"../predicates.h\"\n#include \"../businfo.h\"\n#include \"../globals.h\"\n#include \"../subbus.h\"\n#include \"../msgs.h\"\n#include \"../genbus.h\"\n\n#include \"axil.h\"\n\n#define\tPREFIX\n\nextern\tAXILBUSCLASS\taxilclass;\nconst\tunsigned\tAXI_MIN_ADDRESS_WIDTH = 12;\n\nAXILBUS::AXILBUS(BUSINFO *bi) {\n\t// {{{\n\tm_info = bi;\n\tm_slist = NULL;\n\tm_dlist = NULL;\n\n\tm_is_single = false;\n\tm_is_double = false;\n\n\tm_num_single = 0;\n\tm_num_double = 0;\n\tm_num_total = 0;\n}\n// }}}\n\nvoid\tAXILBUS::allocate_subbus(void) {\n\t// {{{\n\tPLIST\t*pl = m_info->m_plist;\n\tBUSINFO\t*sbi = NULL, *dbi = NULL;\n\n\tif (NULL == pl || pl->size() == 0) {\n\t\tgbl_msg.warning(\"Bus %s has no attached slaves\\n\",\n\t\t\t(name()) ? name()->c_str() : \"(No-name)\");\n\t}\n\n\tgbl_msg.info(\"Generating AXI-Lite bus logic generator for %s\\n\",\n\t\t(name()) ? name()->c_str() : \"(No-name)\");\n\tcountsio();\n\n\tif (m_num_single == m_num_total) {\n\t\tm_num_single = 0;\n\t\tm_is_single = true;\n\t} else if ((m_num_single <= 2)&&(m_num_double > 0)) {\n\t\t// Merge single and double busses, making single\n\t\t// slaves into double slaves\n\t\tm_num_double += m_num_single;\n\t\tm_num_single = 0;\n\t}\n\n\tif (!m_is_single && m_num_single + m_num_double == m_num_total) {\n\t\tm_is_double  = true;\n\t\tm_num_double = 0;\n\t}\n\n\tassert(!m_is_single || !m_is_double);\n\tassert(m_num_single < 50);\n\tassert(m_num_double < 50);\n\tassert(m_num_total >= m_num_single + m_num_double);\n\n\t//\n\t// Master of multiple classes\n\t//\n\tif (!m_is_single && m_num_single > 0) {\n\t\tsbi = create_sio();\n\t\tm_num_total++;\n\t}\n\n\tif (!m_is_double && m_num_double > 0) {\n\t\tm_num_total++;\n\t\tdbi = create_dio();\n\t}\n\n\tif (!m_is_single && !m_is_double && pl) {\n\t\t//\n\t\t// There exist peripherals that are neither singles nor doubles\n\t\t//\n\t\tfor(unsigned pi = 0; pi< pl->size(); pi++) {\n\t\t\tPERIPHP\tp = (*pl)[pi];\n\t\t\tSTRINGP\tptyp;\n\n\t\t\tptyp = getstring(p->p_phash, KYSLAVE_TYPE);\n\t\t\tif (m_slist && ptyp != NULL\n\t\t\t\t&& ptyp->compare(KYSINGLE) == 0) {\n\t\t\t\tm_info->m_plist->erase(pl->begin()+pi);\n\t\t\t\tpi--;\n\t\t\t\tm_slist->add(p);\n\t\t\t} else if (m_dlist && ptyp != NULL\n\t\t\t\t\t&& ((ptyp->compare(KYDOUBLE) == 0)\n\t\t\t\t\t|| (ptyp->compare(KYSINGLE) == 0))) {\n\t\t\t\tm_info->m_plist->erase(pl->begin()+pi);\n\t\t\t\tpi--;\n\t\t\t\tm_dlist->add(p);\n\t\t\t} else {\n\t\t\t// Leave this peripheral in m_info->m_plist\n\t\t\t}\n\t\t}\n\t}\n\n\tif (sbi)\n\t\tsetstring(sbi->m_hash, KY_TYPE, axilclass.name());\n\tif (dbi)\n\t\tsetstring(dbi->m_hash, KY_TYPE, axilclass.name());\n\tREHASH;\n}\n// }}}\n\nint\tAXILBUS::address_width(void) {\n\t// {{{\n\tassert(m_info);\n\treturn m_info->m_address_width;\n}\n// }}}\n\nbool\tAXILBUS::get_base_address(MAPDHASH *phash, unsigned &base) {\n\t// {{{\n\tif (!m_info || !m_info->m_plist) {\n\t\tgbl_msg.error(\"BUS[%s] has no peripherals!\\n\",\n\t\t\t(name()) ? name()->c_str() : \"(No name)\");\n\t\treturn false;\n\t} else\n\t\treturn m_info->m_plist->get_base_address(phash, base);\n}\n// }}}\n\nvoid\tAXILBUS::assign_addresses(void) {\n\t// {{{\n\tint\taddress_width;\n\n\tif (m_info->m_addresses_assigned)\n\t\treturn;\n\tif ((NULL == m_slist)&&(NULL == m_dlist))\n\t\tallocate_subbus();\n\n\tif (!m_info)\n\t\treturn;\n\tgbl_msg.info(\"AXIL: Assigning addresses for bus %s\\n\",\n\t\t(name()) ? name()->c_str() : \"(No name bus)\");\n\tif (!m_info->m_plist||(m_info->m_plist->size() < 1)) {\n\t\tm_info->m_address_width = 0;\n\t} else if (!m_info->m_addresses_assigned) {\n\t\tint\tdw = m_info->data_width(),\n\t\t\tnullsz;\n\n\t\tif (m_slist)\n\t\t\tm_slist->assign_addresses(dw, 0);\n\n\t\tif (m_dlist)\n\t\t\tm_dlist->assign_addresses(dw, 0);\n\n\t\tif (!getvalue(*m_info->m_hash, KY_NULLSZ, nullsz))\n\t\t\tnullsz = 0;\n\n\t\tm_info->m_plist->assign_addresses(dw, nullsz, AXI_MIN_ADDRESS_WIDTH);\n\t\taddress_width = m_info->m_plist->get_address_width();\n\t\tm_info->m_address_width = address_width;\n\t\tif (m_info->m_hash) {\n\t\t\tsetvalue(*m_info->m_hash, KY_AWID, m_info->m_address_width);\n\t\t\tREHASH;\n\t\t}\n\t} m_info->m_addresses_assigned = true;\n}\n// }}}\n\nBUSINFO *AXILBUS::create_sio(void) {\n\t// {{{\n\tassert(m_info);\n\n\tBUSINFO\t*sbi;\n\tSUBBUS\t*subp;\n\tSTRINGP\tsioname;\n\tMAPDHASH *bushash, *shash;\n\tMAPT\telm;\n\n\tsioname = new STRING(STRING(\"\" PREFIX) + (*name()) + \"_sio\");\n\tbushash = new MAPDHASH();\n\tshash   = new MAPDHASH();\n\tsetstring(*shash, KYPREFIX, sioname);\n\tsetstring(*shash, KYSLAVE_TYPE, new STRING(KYDOUBLE));\n\tsetstring(*shash, KYSLAVE_PREFIX, sioname);\n\n\telm.m_typ = MAPT_MAP;\n\telm.u.m_m = bushash;\n\tshash->insert(KEYVALUE(KYSLAVE_BUS, elm));\n\n\telm.u.m_m = m_info->m_hash;\n\tshash->insert(KEYVALUE(KYMASTER_BUS, elm));\n\tsetstring(shash, KYMASTER_TYPE, KYARBITER);\n\n\tsbi  = new BUSINFO(sioname);\n\tsbi->prefix(new STRING(\"_sio\"));\n\tsetstring(bushash, KY_TYPE, new STRING(\"axil\"));\n\tsbi->m_data_width = m_info->m_data_width;\n\tsbi->m_clock      = m_info->m_clock;\n\tsbi->addmaster(m_info->m_hash);\n\tsubp = new SUBBUS(shash, sioname, sbi);\n\tsubp->p_slave_bus = m_info;\n\t// subp->p_master_bus = set by the SUBBUS to be sbi\n\tm_info->m_plist->add(subp);\nassert(subp->p_master_bus);\nassert(subp->p_slave_bus == m_info);\nassert(subp->p_master_bus == sbi);\n\t// m_plist->integrity_check();\n\tsbi->add();\n\tm_slist = sbi->m_plist;\n\n\treturn sbi;\n}\n// }}}\n\nBUSINFO *AXILBUS::create_dio(void) {\n\t// {{{\n\tassert(m_info);\n\n\tBUSINFO\t*dbi;\n\tSUBBUS\t*subp;\n\tSTRINGP\tdioname;\n\tMAPDHASH\t*bushash, *shash;\n\tMAPT\telm;\n\n\tdioname = new STRING(STRING(\"\" PREFIX) + (*name()) + \"_dio\");\n\tbushash = new MAPDHASH();\n\tshash   = new MAPDHASH();\n\tsetstring(*bushash, KY_NAME, dioname);\n\tsetstring(*shash, KYPREFIX, dioname);\n\tsetstring(*shash, KYSLAVE_TYPE, new STRING(KYOTHER));\n\tsetstring(*shash, KYSLAVE_PREFIX, dioname);\n\n\telm.m_typ = MAPT_MAP;\n\telm.u.m_m = m_info->m_hash;\n\tshash->insert(KEYVALUE(KYSLAVE_BUS, elm));\n\n\telm.u.m_m = bushash;\n\tshash->insert(KEYVALUE(KYMASTER_BUS, elm));\n\tsetstring(shash, KYMASTER_TYPE, KYARBITER);\n\n\tdbi  = new BUSINFO(dioname);\n\tdbi->prefix(new STRING(\"_dio\"));\n\tsetstring(bushash, KY_TYPE, new STRING(\"axil\"));\nassert(m_info->data_width() > 0);\n\tsetvalue(*bushash, KY_WIDTH, m_info->data_width());\n\tdbi->m_data_width = m_info->m_data_width;\n\tdbi->m_clock      = m_info->m_clock;\n\tdbi->addmaster(m_info->m_hash);\n\tsubp = new SUBBUS(shash, dioname, dbi);\n\tsubp->p_slave_bus = m_info;\n\tm_info->m_plist->add(subp);\nassert(subp->p_master_bus);\nassert(subp->p_master_bus == dbi);\nassert(subp->p_slave_bus == m_info);\n\t// subp->p_master_bus = set by the slave to be dbi\n\tdbi->add();\n\tm_dlist = dbi->m_plist;\nassert(isbusmaster(*shash));\nassert(isarbiter(*shash));\n\n\treturn dbi;\n}\n// }}}\n\nvoid\tAXILBUS::countsio(void) {\n\t// {{{\n\tPLIST\t*pl = m_info->m_plist;\n\tSTRINGP\tstrp;\n\n\tm_num_single = 0;\n\tm_num_double = 0;\n\tm_num_total = 0;\n\n\tif (NULL == pl)\n\t\treturn;\n\n\tfor(unsigned pi=0; pi< pl->size(); pi++) {\n\t\tstrp = getstring((*pl)[pi]->p_phash, KYSLAVE_TYPE);\n\t\tif (NULL != strp) {\n\t\t\tif (0==strp->compare(KYSINGLE)) {\n\t\t\t\tm_num_single++;\n\t\t\t} else if (0==strp->compare(KYDOUBLE)) {\n\t\t\t\tm_num_double++;\n\t\t\t} m_num_total++;\n\t\t} else\n\t\t\tm_num_total++;\t// Default to OTHER if no type is given\n\t}\n}\n// }}}\n\nvoid\tAXILBUS::integrity_check(void) {\n\t// {{{\n\t// GENBUS::integrity_check();\n\n\tif (m_info && m_info->m_data_width <= 0) {\n\t\tgbl_msg.error(\"ERR: BUS width not defined for %s\\n\",\n\t\t\tname()->c_str());\n\t}\n}\n// }}}\n\nvoid\tAXILBUS::writeout_defn_v(FILE *fp, const char *mstype,\n\t\tconst char *pname, const char* busp, const char *btyp){\n\t// {{{\n\tSTRINGP\tn = name();\n\tint\taw = address_width();\n\n\tfprintf(fp, \"\\t//\\n\\t// AXI-lite %s definitions for bus %s%s,\\n\"\n\t\t\"\\t// component %s, with prefix %s\\n\\t// {{{\\n\",\n\t\tmstype, n->c_str(), btyp, pname, busp);\n\tfprintf(fp, \"\\t// Verilator lint_off UNUSED\\n\");\n\tfprintf(fp, \"\\twire\\t\\t%s_awready, %s_wready,\\n\\t\\t\\t%s_arready;\\n\",\n\t\t\tbusp, busp, busp);\n\tfprintf(fp, \"\\twire\\t\\t%s_bvalid, %s_rvalid;\\n\",\n\t\t\tbusp, busp);\n\tfprintf(fp, \"\\twire\\t[1:0]\\t%s_bresp, %s_rresp;\\n\",\n\t\t\tbusp, busp);\n\tfprintf(fp, \"\\twire\\t[%d:0]\\t%s_rdata;\\n\\n\",\n\t\t\tm_info->data_width()-1, busp);\n\tfprintf(fp, \"\\twire\\t\\t%s_awvalid, %s_wvalid,\\n\\t\\t\\t%s_arvalid,\\n\"\n\t\t\"\\t\\t\\t%s_bready, %s_rready;\\n\"\n\t\t\"\\twire\\t[%d:0]\\t%s_araddr, %s_awaddr;\\n\"\n\t\t\"\\twire\\t[2:0]\\t%s_arprot, %s_awprot;\\n\"\n\t\t\"\\twire\\t[%d:0]\\t%s_wdata;\\n\"\n\t\t\"\\twire\\t[%d:0]\\t%s_wstrb;\\n\\n\",\n\t\tbusp, busp, busp,\n\t\tbusp, busp,\n\t\t\taw-1, busp, busp,\n\t\tbusp, busp,\n\t\t\tm_info->data_width()-1, busp,\n\t\t\t(m_info->data_width()/8)-1, busp);\n\tfprintf(fp,\n\t\t\"\\t// Verilator lint_on  UNUSED\\n\"\n\t\t\"\\t// }}}\\n\");\n}\n// }}}\n\nvoid\tAXILBUS::writeout_bus_slave_defns_v(FILE *fp) {\n\t// {{{\n\tPLIST\t*p = m_info->m_plist;\n\tSTRINGP\tn = name();\n\n\tif (m_slist) {\n\t\tfor(PLIST::iterator pp=m_slist->begin();\n\t\t\t\tpp != m_slist->end(); pp++) {\n\t\t\twriteout_defn_v(fp, \"slave\", (*pp)->p_name->c_str(),\n\t\t\t\t(*pp)->bus_prefix()->c_str(), \"(SIO)\");\n\t\t}\n\t} else if (!m_is_single)\n\t\tfprintf(fp, \"\\n\\t// Bus %s has no SINGLE slaves\\n\\t//\\n\", n->c_str());\n\telse\n\t\tfprintf(fp, \"\\n\\t// Bus %s is all SINGLE slaves\\n\\t//\\n\", n->c_str());\n\n\tif (m_dlist) {\n\t\tfor(PLIST::iterator pp=m_dlist->begin();\n\t\t\t\tpp != m_dlist->end(); pp++) {\n\t\t\twriteout_defn_v(fp, \"slave\", (*pp)->p_name->c_str(),\n\t\t\t\t(*pp)->bus_prefix()->c_str(), \"(DIO)\");\n\t\t}\n\t} else if (!m_is_double)\n\t\tfprintf(fp, \"\\n\\t// Bus %s has no DOUBLE slaves\\n\\t//\\n\", n->c_str());\n\telse\n\t\tfprintf(fp, \"\\n\\t// Bus %s is all DOUBLE slaves\\n\\t//\\n\", n->c_str());\n\n\n\tif (p) {\n\t\tfor(PLIST::iterator pp=p->begin(); pp != p->end(); pp++) {\n\t\t\twriteout_defn_v(fp, \"slave\", (*pp)->p_name->c_str(),\n\t\t\t\t(*pp)->bus_prefix()->c_str());\n\t\t}\n\t} else {\n\t\tgbl_msg.error(\"%s has no slaves\\n\", n->c_str());\n\t}\n}\n// }}}\n\nvoid\tAXILBUS::writeout_bus_master_defns_v(FILE *fp) {\n\t// {{{\n\tMLIST\t*m = m_info->m_mlist;\n\tSTRINGP\tn = name();\n\n\tif (m) {\n\t\tfor(MLIST::iterator pp=m->begin(); pp != m->end(); pp++) {\n\t\t\twriteout_defn_v(fp, \"master\", (*pp)->name()->c_str(),\n\t\t\t(*pp)->bus_prefix()->c_str());\n\t\t}\n\t} else {\n\t\tgbl_msg.warning(\"Bus %s has no masters\\n\", n->c_str());\n\t}\n}\n// }}}\n\nvoid\tAXILBUS::write_addr_range(FILE *fp, const PERIPHP p, const int dalines) {\n\t// {{{\n\tunsigned\tw = address_width();\n\tw = (w+3)/4;\n\tif (p->p_naddr == 1)\n\t\tfprintf(fp, \" // 0x%0*lx\", w, p->p_base);\n\telse\n\t\tfprintf(fp, \" // 0x%0*lx - 0x%0*lx\", w, p->p_base,\n\t\t\tw, p->p_base + (p->p_naddr << (dalines))-1);\n}\n// }}}\n\nvoid\tAXILBUS::writeout_no_slave_v(FILE *fp, STRINGP prefix) {\n\t// {{{\n}\n// }}}\n\nvoid\tAXILBUS::writeout_no_master_v(FILE *fp) {\n\tif (!m_info || !name())\n\t\tgbl_msg.error(\"(Unnamed bus) has no name!\\n\");\n}\n\nSTRINGP\tAXILBUS::master_name(int k) {\n\t// {{{\n\tMLISTP ml = m_info->m_mlist;\n\n\treturn (*ml)[k]->name();\n}\n// }}}\n\n//\n// Connect this master to the crossbar.  Specifically, we want to output\n// a list of master connections to fill the given port.\n//\nvoid AXILBUS::xbarcon_master(FILE *fp, const char *tabs,\n\t\t\tconst char *pfx,const char *sig, bool comma) {\n\tSTRING lcase = STRING(sig);\n\n\tfor(unsigned k=0; k<lcase.size(); k++)\n\t\tlcase[k] = tolower(lcase[k]);\n\n\tfprintf(fp, \"%s%s%s({\\n\", tabs, pfx, sig);\n\tfor(unsigned k=m_info->m_mlist->size()-1; k> 0; k--) {\n\t\tBMASTER *m = (*m_info->m_mlist)[k];\n\t\tSTRINGP busp = m->bus_prefix();\n\t\tfprintf(fp, \"%s\\t%s_%s,\\n\", tabs, busp->c_str(), lcase.c_str());\n\t}\n\tfprintf(fp, \"%s\\t%s_%s\\n\", tabs, (*m_info->m_mlist)[0]->bus_prefix()->c_str(),\n\t\tlcase.c_str());\n\tfprintf(fp, \"%s})%s\\n\", tabs, comma ? \",\":\"\");\n}\n\n//\n// Output a list of connections to slave bus wires.  Used in connecting the\n// slaves to the various crossbar inputs.\n//\nvoid AXILBUS::xbarcon_slave(FILE *fp, PLIST *pl, const char *tabs,\n\t\t\tconst char *pfx,const char *sig, bool comma) {\n\tSTRING lcase = STRING(sig);\n\n\tfor(unsigned k=0; k<lcase.size(); k++)\n\t\tlcase[k] = tolower(lcase[k]);\n\n\tfprintf(fp, \"%s%s%s({\\n\", tabs, pfx, sig);\n\tfor(unsigned k=pl->size()-1; k> 0; k--)\n\t\tfprintf(fp, \"%s\\t%s_%s,\\n\", tabs, (*pl)[k]->bus_prefix()->c_str(), lcase.c_str());\n\tfprintf(fp, \"%s\\t%s_%s\\n\", tabs, (*pl)[0]->bus_prefix()->c_str(), lcase.c_str());\n\tfprintf(fp, \"%s})%s\\n\", tabs, comma ? \",\":\"\");\n}\n\nvoid\tAXILBUS::writeout_bus_logic_v(FILE *fp) {\n\tSTRINGP\t\tn = name(), rst;\n\tCLOCKINFO\t*c = m_info->m_clock;\n\tPLIST::iterator\tpp;\n\tPLISTP\t\tpl;\n\t// unsigned\tunused_lsbs;\n\tMLISTP\t\tm_mlist = m_info->m_mlist;\n\n\tif (NULL == m_info->m_plist)\n\t\treturn;\n\n\tif (NULL == m_info->m_mlist) {\n\t\tgbl_msg.warning(\"No masters assigned to bus %s\\n\",\n\t\t\t\tn->c_str());\n\t}\n\tif (NULL == (rst = m_info->reset_wire())) {\n\t\tgbl_msg.warning(\"Bus %s has no associated reset wire, using \\'i_reset\\'\\n\", n->c_str());\n\t\trst = new STRING(\"i_reset\");\n\t\tsetstring(m_info->m_hash, KY_RESET, rst);\n\t\tREHASH;\n\t}\n\n\tif (NULL == c || NULL == c->m_wire) {\n\t\tgbl_msg.fatal(\"Bus %s has no associated clock\\n\", n->c_str());\n\t}\n\n\n\t// unused_lsbs = nextlg(m_info->data_width())-3;\n\tif (m_info->m_plist->size() == 0) {\t// No slaves\n\t\t// {{{\n\t\tfprintf(fp, \"\\t//\\n\"\n\t\t\t\"\\t// Bus %s has no slaves\\n\"\n\t\t\t\"\\t//\\n\\n\", n->c_str());\n\n\t\t// Since this bus has no slaves, any attempt to access it\n\t\t// needs to cause a bus error.\n\t\t//\n\t\t// Need to loop through all possible masters ...\n\t\tfor(unsigned m=0; m_info && m < m_info->m_mlist->size(); m++) {\n\t\t\tSTRINGP\tmstr = master_name(m);\n\t\t\tconst\tchar *mp = mstr->c_str();\n\t\t\tfprintf(fp,\n\t\t\t\t\"\\t//\\n\"\n\t\t\t\t\"\\t// The %s bus has no slaves assigned to it\\n\"\n\t\t\t\t\"\\t//\\n\", mp);\n\n\t\t\tfprintf(fp,\n\t\t\t\t\"\\t// The no-slave peripheral\\n\"\n\t\t\t\t\"\\t//\\n\"\n\t\"\\taxilempty #(\\n\"\n\t\"\\t\\t// {{{\\n\"\n\t\"\\t\\t.C_AXI_ADDR_WIDTH(%d),\\n\"\n\t\"\\t\\t.C_AXI_DATA_WIDTH(%d)\\n\"\n\t\"\\t\\t// }}}\\n\",\n\t\t\t\taddress_width(),\n\t\t\t\tm_info->data_width());\n\t\t\tfprintf(fp,\n\t\"\\t) %s_no_slavep (\\n\"\n\t\t\"\\t\\t// {{{\\n\"\n\t\t\"\\t\\t.S_AXI_ACLK(%s), .S_AXI_ARESETN(%s),\\n\"\n\t\t\"\\t\\t//\\n\",\n\t\t\tmp, c->m_wire->c_str(), rst->c_str());\n\t\t\tfprintf(fp,\n\t\t\"\\t\\t.S_AXI_AWVALID(%s_awvalid), .S_AXI_AWREADY(%s_awready),\\n\"\n\t\t\"\\t\\t.S_AXI_WVALID(%s_wvalid),   .S_AXI_WREADY(%s_wready),\\n\"\n\t\t\"\\t\\t.S_AXI_BVALID(%s_bvalid),   .S_AXI_BREADY(%s_bready),\\n\"\n\t\t\"\\t\\t.S_AXI_BRESP(%s_bresp),\\n\"\n\t\t\"\\t\\t//\\n\"\n\t\t\"\\t\\t.S_AXI_ARVALID(%s_arvalid), .S_AXI_ARREADY(%s_arready),\\n\"\n\t\t\"\\t\\t.S_AXI_RVALID(%s_rvalid),   .S_AXI_RREADY(%s_rready),\\n\"\n\t\t\"\\t\\t.S_AXI_RDATA(%s_rdata),   .S_AXI_RRESP(%s_rresp)\\n\"\n\t\t\"\\t);\\n\\n\",\n\t\t\t\tmp, mp, mp, mp, mp, mp, mp,\n\t\t\t\tmp, mp, mp, mp, mp, mp);\n\t\t}\n\n\t\treturn;\n\t\t// }}}\n\t} else if (NULL == m_mlist || m_mlist->size() == 0) { // No masters\n\t\t// {{{\n\t\tfor(unsigned p=0; p < m_info->m_plist->size(); p++) {\n\t\t\tSTRINGP\tpstr = (*m_info->m_plist)[p]->bus_prefix();\n\t\t\tfprintf(fp,\n\t\t\"\\t//\\n\"\n\t\t\"\\t// The %s bus has no masters assigned to it\\n\"\n\t\t\"\\t//\\n\"\n\t\t\"\\tassign\t%s_awvalid = 1\\'b0;\\n\"\n\t\t\"\\tassign\t%s_awaddr  = 0;\\n\"\n\t\t\"\\tassign\t%s_awprot  = 3\\'h0;\\n\"\n\t\t\"\\t//\\n\",\n\t\t\tpstr->c_str(), pstr->c_str(), pstr->c_str(), pstr->c_str());\n\n\t\t\tfprintf(fp,\n\t\t\"\\tassign\t%s_wvalid  = 1\\'b0;\\n\"\n\t\t\"\\tassign\t%s_wdata   = 0;\\n\"\n\t\t\"\\tassign\t%s_wstrb   = 0;\\n\"\n\t\t\"\\t//\\n\",\n\t\t\tpstr->c_str(), pstr->c_str(),\n\t\t\tpstr->c_str());\n\n\t\t\tfprintf(fp,\n\t\t\"\\tassign\t%s_bready  = 1\\'b0;\\n\",\n\t\t\tpstr->c_str());\n\n\t\t\tfprintf(fp,\n\t\t\"\\t//\\n\"\n\t\t\"\\tassign\t%s_arvalid = 1\\'b0;\\n\"\n\t\t\"\\tassign\t%s_araddr  = 0;\\n\"\n\t\t\"\\tassign\t%s_arprot  = 3\\'h0;\\n\"\n\t\t\"\\t//\\n\",\n\t\t\tpstr->c_str(), pstr->c_str(), pstr->c_str());\n\n\t\t\tfprintf(fp,\n\t\t\"\\tassign\t%s_rready  = 1\\'b1;\\n\",\n\t\t\tpstr->c_str());\n\n\t\t\tfprintf(fp,\n\t\t\"\\t//\\n\"\n\t\t\"\\t//\\n\"\n\t\t\"\\twire\t%s_unused;\\n\"\n\t\t\"\\tassign\t%s_unused = &{ 1\\'b0, %s_awready, %s_wready,\\n\"\n\t\t\t\"\\t\\t%s_bvalid, %s_bresp,\\n\"\n\t\t\t\"\\t\\t%s_arready,\\n\"\n\t\t\t\"\\t\\t%s_rvalid, %s_rdata, %s_rresp\\n\"\n\t\t\t\"\\t\\t};\\n\",\n\t\t\tpstr->c_str(), pstr->c_str(),\n\t\t\tpstr->c_str(), pstr->c_str(),\n\t\t\tpstr->c_str(), pstr->c_str(),\n\t\t\tpstr->c_str(),\n\t\t\tpstr->c_str(),pstr->c_str(),pstr->c_str()\n\t\t\t);\n\t\t}\n\n\t\treturn;\n\t\t// }}}\n\t} else if ((m_info->m_plist->size() == 1)&&(m_mlist && m_mlist->size() == 1)) {\n\t\t// {{{\n\t\t// Only one master connected to only one slave--skip all the\n\t\t// extra connection logic.\n\t\t//\n\t\t// Can only simplify if there's only one peripheral and only\n\t\t// one master\n\t\t//\n\t\tSTRINGP\tslv  = (*m_info->m_plist)[0]->bus_prefix();\n\t\tSTRINGP\tmstr = (*m_mlist)[0]->bus_prefix();\n\t\tconst char *sp = slv->c_str(),\n\t\t\t*mp = mstr->c_str();\n\n\t\tfprintf(fp,\n\t\t\"\\t//\\n\"\n\t\t\"\\t// Bus %s has only one master (%s) and one slave (%s)\\n\"\n\t\t\"\\t// connected to it -- skipping the interconnect\\n\"\n\t\t\"\\t//\\n\",\n\t\tn->c_str(), master_name(0)->c_str(), sp);\n\n\t\t\tfprintf(fp,\n\t\t\"\\tassign\t%s_awvalid = %s_awvalid;\\n\"\n\t\t\"\\tassign\t%s_awready = %s_awready;\\n\"\n\t\t\"\\tassign\t%s_awaddr  = %s_awaddr;\\n\"\n\t\t\"\\tassign\t%s_awprot  = %s_awprot;\\n\"\n\t\t\"\\t//\\n\",\n\t\t\tsp, mp, mp, sp,\n\t\t\tsp, mp, sp, mp);\n\n\t\t\tfprintf(fp,\n\t\t\"\\tassign\t%s_wvalid  = %s_wvalid;\\n\"\n\t\t\"\\tassign\t%s_wready  = %s_wready;\\n\"\n\t\t\"\\tassign\t%s_wdata   = %s_wdata;\\n\"\n\t\t\"\\tassign\t%s_wstrb   = %s_wstrb;\\n\"\n\t\t\"\\t//\\n\",\n\t\t\tsp, mp, mp, sp,\n\t\t\tsp, mp, sp, mp);\n\n\t\t\tfprintf(fp,\n\t\t\"\\tassign\t%s_bvalid  = %s_bvalid;\\n\"\n\t\t\"\\tassign\t%s_bready  = %s_bready;\\n\"\n\t\t\"\\tassign\t%s_bresp   = %s_bresp;\\n\",\n\t\t\tmp, sp, sp, mp,\n\t\t\tmp, sp);\n\n\t\t\tfprintf(fp,\n\t\t\"\\t//\\n\"\n\t\t\"\\tassign\t%s_arvalid = %s_arvalid;\\n\"\n\t\t\"\\tassign\t%s_arready = %s_arready;\\n\"\n\t\t\"\\tassign\t%s_araddr  = %s_araddr;\\n\"\n\t\t\"\\tassign\t%s_arprot  = %s_arprot;\\n\"\n\t\t\"\\t//\\n\",\n\t\t\tsp, mp, mp, sp,\n\t\t\tsp, mp, sp, mp);\n\n\t\t\tfprintf(fp,\n\t\t\"\\tassign\t%s_rvalid  = %s_rvalid;\\n\"\n\t\t\"\\tassign\t%s_rready  = %s_rready;\\n\"\n\t\t\"\\tassign\t%s_rdata   = %s_rdata;\\n\"\n\t\t\"\\tassign\t%s_rresp   = %s_rresp;\\n\\n\",\n\t\t\tmp, sp, sp, mp,\n\t\t\tmp, sp, mp, sp);\n\t\treturn;\n\t\t// }}}\n\t}\n\n\t// Start with the slist\n\tif (m_is_single || m_slist) {\n\t\t// {{{\n\t\tassert(1 == m_info->m_mlist->size());\n\n\t\tPLIST\t*slist = (m_is_single) ? m_info->m_plist : m_slist;\n\t\tconst char *np = n->c_str();\n\t\tSTRING\ts = STRING(*(*m_mlist)[0]->bus_prefix());\n\t\tint\taw = nextlg(slist->size())+nextlg(m_info->data_width())-3;\n\n\t\tfprintf(fp,\n\t\t\t\"\\t// Some extra wires to capture combined values--values\\n\"\n\t\t\t\"\\t// that will be the same across all slaves of the\\n\"\n\t\t\t\"\\t// class\\n\"\n\t\t\t\"\\twire [2:0]\\t%s_siow_awprot;\\n\"\n\t\t\t\"\\twire [%d:0]\\t%s_siow_wdata;\\n\"\n\t\t\t\"\\twire [%d:0]\\t%s_siow_wstrb;\\n\"\n\t\t\t\"\\twire [2:0]\\t%s_siow_arprot;\\n\\n\",\n\t\t\tn->c_str(), m_info->data_width()-1, n->c_str(),\n\t\t\tm_info->data_width()/8-1, n->c_str(), n->c_str());\n\n\t\tfprintf(fp,\n\t\t\"\\taxilsingle #(\\n\"\n\t\t\t\"\\t\\t// {{{\\n\"\n\t\t\t\"\\t\\t// .C_AXI_ADDR_WIDTH(%d), // must be only one word address\\n\"\n\t\t\t\"\\t\\t.C_AXI_DATA_WIDTH(%d),\\n\"\n\t\t\t\"\\t\\t.NS(%ld)\",\n\t\t\taw, m_info->data_width(),\n\t\t\tslist->size());\n\t\txbar_option(fp, KY_OPT_LOWPOWER,  \",\\n\\t\\t.OPT_LOWPOWER(%)\",\n\t\t\t\"1\\'b1\");\n\t\tfprintf(fp,\n\t\t\"\\n\\t\\t// }}}\\n\"\n\t\t\"\\t) %s_axilsingle(\\n\", np);\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t// {{{\\n\"\n\t\t\t\"\\t\\t.S_AXI_ACLK(%s),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARESETN(%s),\\n\",\n\t\t\t\tc->m_wire->c_str(), rst->c_str());\n\n\t\tfprintf(fp, \"\\t\\t// Connect our SIO slave wires to axilsingle\\n\"\n\t\t\t\"\\t\\t// {{{\\n\");\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t.S_AXI_AWVALID(%s_awvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWREADY(%s_awready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWADDR( %s_awaddr[%d:0]),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWPROT( %s_awprot),\\n\"\n\t\t\t\"\\t\\t//\\n\"\n\t\t\t\"\\t\\t.S_AXI_WVALID( %s_wvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_WREADY( %s_wready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_WDATA(  %s_wdata),\\n\"\n\t\t\t\"\\t\\t.S_AXI_WSTRB(  %s_wstrb),\\n\"\n\t\t\t\"\\t\\t//\\n\"\n\t\t\t\"\\t\\t.S_AXI_BVALID( %s_bvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_BREADY( %s_bready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_BRESP(  %s_bresp),\\n\"\n\t\t\t\"\\t\\t// Read connections\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARVALID(%s_arvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARREADY(%s_arready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARADDR( %s_araddr[%d:0]),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARPROT( %s_arprot),\\n\"\n\t\t\t\"\\t\\t//\\n\"\n\t\t\t\"\\t\\t.S_AXI_RVALID( %s_rvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_RREADY( %s_rready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_RDATA(  %s_rdata),\\n\"\n\t\t\t\"\\t\\t.S_AXI_RRESP(  %s_rresp),\\n\"\n\t\t\t\"\\t\\t// }}}\\n\"\n\t\t\t\"\\t\\t// Connections to varous AXI-lite (SINGLE) slaves\\n\"\n\t\t\t\"\\t\\t// {{{\\n\",\n\t\t\ts.c_str(), s.c_str(), s.c_str(), aw-1, s.c_str(),\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str(),\n\t\t\ts.c_str(), s.c_str(), s.c_str(),\n\t\t\ts.c_str(), s.c_str(), s.c_str(), aw-1, s.c_str(),\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str());\n\n\t\txbarcon_slave(fp, slist, \"\\t\\t\",\".M_AXI_\",\"AWVALID\");\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t.M_AXI_AWPROT(%s_siow_awprot),\\n\"\n\t\t\t\"\\t\\t.M_AXI_WDATA( %s_siow_wdata),\\n\"\n\t\t\t\"\\t\\t.M_AXI_WSTRB( %s_siow_wstrb),\\n\",\n\t\t\tn->c_str(), n->c_str(), n->c_str());\n\t\tfprintf(fp, \"\\t\\t//\\n\"\n\t\t\t\"\\t\\t//\\n\");\n\t\txbarcon_slave(fp, slist, \"\\t\\t\",\".M_AXI_\",\"BRESP\");\n\t\tfprintf(fp, \"\\t\\t// Read connections\\n\");\n\t\txbarcon_slave(fp, slist, \"\\t\\t\",\".M_AXI_\",\"ARVALID\");\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t.M_AXI_ARPROT(%s_siow_arprot),\\n\"\n\t\t\t\"\\t\\t//\\n\", n->c_str());\n\t\txbarcon_slave(fp, slist, \"\\t\\t\",\".M_AXI_\",\"RDATA\");\n\t\txbarcon_slave(fp, slist, \"\\t\\t\",\".M_AXI_\",\"RRESP\", false);\n\t\tfprintf(fp, \"\\t\\t// }}}\\n\"\n\t\t\t\"\\t\\t// }}}\\n\"\n\t\t\t\"\\t);\\n\\n\");\n\t\tfprintf(fp,\"\\t//\\n\\t// Now connecting the extra slaves wires \"\n\t\t\t\"to the AXILSINGLE controller\\n\"\n\t\t\t\"\\t// {{{\\n\");\n\n\t\tfor(int k=slist->size(); k>0; k--) {\n\t\t\tPERIPHP p = (*slist)[k-1];\n\t\t\tconst char *pn = p->p_name->c_str(),\n\t\t\t\t*ns = n->c_str();\n\n\t\t\tfprintf(fp, \"\\t// %s\\n\", pn);\n\t\t\tpn = p->bus_prefix()->c_str();\n\t\t\tfprintf(fp, \"\\tassign %s_awaddr = 0;\\n\", pn);\n\t\t\tfprintf(fp, \"\\tassign %s_awprot = %s_siow_awprot;\\n\", pn, ns);\n\t\t\tfprintf(fp, \"\\tassign %s_wvalid = %s_awvalid;\\n\", pn, pn);\n\t\t\tfprintf(fp, \"\\tassign %s_wdata = %s_siow_wdata;\\n\", pn, ns);\n\t\t\tfprintf(fp, \"\\tassign %s_wstrb = %s_siow_wstrb;\\n\", pn, ns);\n\t\t\tfprintf(fp, \"\\tassign %s_bready = 1\\'b1;\\n\", pn);\n\t\t\tfprintf(fp, \"\\tassign %s_araddr = 0;\\n\", pn);\n\t\t\tfprintf(fp, \"\\tassign %s_arprot = %s_siow_arprot;\\n\", pn, ns);\n\t\t\tfprintf(fp, \"\\tassign %s_rready = 1\\'b1;\\n\", pn);\n\t\t} fprintf(fp, \"\\t// }}}\\n\");\n\t\t// }}}\n\t\treturn;\n\t\t// }}}\n\t} else if (!m_slist)\n\t\tfprintf(fp, \"\\t//\\n\\t// No class SINGLE peripherals on the \\\"%s\\\" bus\\n\\t//\\n\\n\", n->c_str());\n\n\t// Then the dlist\n\tif (m_is_double || m_dlist) {\n\t\t// {{{\n\t\tif (m_dlist)\n\t\t\tpl = m_dlist;\n\t\telse\n\t\t\tpl = m_info->m_plist;\n\t\tSTRING\ts = STRING(*(*m_mlist)[0]->bus_prefix());\n\t\tint\taw = address_width();\n\n\t\tif (!m_is_double)\n\t\t\ts = (*n) + \"_dio\";\n\n\t\tfprintf(fp,\n\t\t\t\"\\t//\\n\"\n\t\t\t\"\\t// %s Bus logic to handle %ld DOUBLE slaves\\n\"\n\t\t\t\"\\t//\\n\"\n\t\t\t\"\\t//\\n\", n->c_str(), pl->size());\n\n\t\tfprintf(fp,\n\t\t\t\"\\t// Some extra wires to capture combined values--values\\n\"\n\t\t\t\"\\t// that will be the same across all slaves of the\\n\"\n\t\t\t\"\\t// class\\n\"\n\t\t\t\"\\twire [%d:0]\\t%s_diow_awaddr;\\n\"\n\t\t\t\"\\twire [2:0]\\t%s_diow_awprot;\\n\"\n\t\t\t\"\\twire [%d:0]\\t%s_diow_wdata;\\n\"\n\t\t\t\"\\twire [%d:0]\\t%s_diow_wstrb;\\n\"\n\t\t\t\"\\twire [%d:0]\\t%s_diow_araddr;\\n\"\n\t\t\t\"\\twire [2:0]\\t%s_diow_arprot;\\n\\n\",\n\t\t\taddress_width()-1, n->c_str(),\n\t\t\tn->c_str(),\n\t\t\tm_info->data_width()-1, n->c_str(),\n\t\t\tm_info->data_width()/8-1, n->c_str(),\n\t\t\taddress_width()-1, n->c_str(),\n\t\t\tn->c_str());\n\n\t\tfprintf(fp,\n\t\t\"\\taxildouble #(\\n\"\n\t\t\t\"\\t\\t// {{{\\n\"\n\t\t\t\"\\t\\t.C_AXI_ADDR_WIDTH(%d),\\n\"\n\t\t\t\"\\t\\t.C_AXI_DATA_WIDTH(%d),\\n\"\n\t\t\t\"\\t\\t.NS(%ld),\\n\",\n\t\t\taddress_width(), m_info->data_width(),\n\t\t\tpl->size());\n\t\txbar_option(fp, KY_OPT_LOWPOWER,  \"\\t\\t.OPT_LOWPOWER(%),\\n\",\n\t\t\t\"1\\'b1\");\n\t\tslave_addr(fp, pl); fprintf(fp, \",\\n\");\n\t\tslave_mask(fp, pl); fprintf(fp, \"\\n\");\n\t\tfprintf(fp,\n\t\t\"\\t\\t// }}}\\n\"\n\t\t\"\\t) %s_axildouble(\\n\",\n\t\t\tn->c_str());\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t// {{{\\n\"\n\t\t\t\"\\t\\t.S_AXI_ACLK(%s),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARESETN(%s),\\n\",\n\t\t\t\tc->m_wire->c_str(), rst->c_str());\n\n\t\tfprintf(fp, \"\\t\\t//\\n\");\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t// Slave port\\n\"\n\t\t\t\"\\t\\t// {{{\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWVALID(%s_awvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWREADY(%s_awready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWADDR( %s_awaddr[%d:0]),\\n\"\n\t\t\t\"\\t\\t.S_AXI_AWPROT( %s_awprot),\\n\"\n\t\t\t\"\\t\\t//\\n\"\n\t\t\t\"\\t\\t.S_AXI_WVALID( %s_wvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_WREADY( %s_wready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_WDATA(  %s_wdata),\\n\"\n\t\t\t\"\\t\\t.S_AXI_WSTRB(  %s_wstrb),\\n\"\n\t\t\t\"\\t\\t//\\n\"\n\t\t\t\"\\t\\t.S_AXI_BVALID( %s_bvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_BREADY( %s_bready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_BRESP(  %s_bresp),\\n\"\n\t\t\t\"\\t\\t//\\n\",\n\t\t\t// AW\n\t\t\ts.c_str(), s.c_str(), s.c_str(), aw-1, s.c_str(),\n\t\t\t// W\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str(),\n\t\t\t// B\n\t\t\ts.c_str(), s.c_str(), s.c_str());\n\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t// Read connections\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARVALID(%s_arvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARREADY(%s_arready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARADDR( %s_araddr[%d:0]),\\n\"\n\t\t\t\"\\t\\t.S_AXI_ARPROT( %s_arprot),\\n\"\n\t\t\t\"\\t\\t//\\n\"\n\t\t\t\"\\t\\t.S_AXI_RVALID( %s_rvalid),\\n\"\n\t\t\t\"\\t\\t.S_AXI_RREADY( %s_rready),\\n\"\n\t\t\t\"\\t\\t.S_AXI_RDATA(  %s_rdata),\\n\"\n\t\t\t\"\\t\\t.S_AXI_RRESP(  %s_rresp),\\n\"\n\t\t\t\"\\t\\t// }}}\\n\"\n\t\t\t\"\\t\\t// Connections to slaves\\n\"\n\t\t\t\"\\t\\t// {{{\\n\",\n\t\t\t// AR\n\t\t\ts.c_str(), s.c_str(), s.c_str(), aw-1, s.c_str(),\n\t\t\t// R\n\t\t\ts.c_str(), s.c_str(), s.c_str(), s.c_str());\n\n\t\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWVALID\");\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t.M_AXI_AWADDR( %s_diow_awaddr),\\n\"\n\t\t\t\"\\t\\t.M_AXI_AWPROT( %s_diow_awprot),\\n\",\n\t\t\tn->c_str(), n->c_str());\n\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t.M_AXI_WDATA(  %s_diow_wdata),\\n\"\n\t\t\t\"\\t\\t.M_AXI_WSTRB(  %s_diow_wstrb),\\n\",\n\t\t\tn->c_str(), n->c_str());\n\t\tfprintf(fp, \"\\t\\t//\\n\");\n\t\tfprintf(fp, \"\\t\\t//\\n\");\n\t\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"BRESP\");\n\t\tfprintf(fp, \"\\t\\t// Read connections\\n\");\n\t\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARVALID\");\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t.M_AXI_ARADDR( %s_diow_araddr),\\n\"\n\t\t\t\"\\t\\t.M_AXI_ARPROT( %s_diow_arprot),\\n\"\n\t\t\t\"\\t\\t//\\n\",\n\t\t\tn->c_str(), n->c_str());\n\t\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"RDATA\");\n\t\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"RRESP\", false);\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t// }}}\\n\"\n\t\t\t\"\\t\\t// }}}\\n\"\n\t\t\t\"\\t);\\n\\n\");\n\t\tfprintf(fp,\"\\t//\\n\\t// Now connecting the extra slaves wires \"\n\t\t\t\"to the AXILDOUBLE controller\\n\\t//\\n\");\n\n\t\tfor(int k=pl->size(); k>0; k--) {\n\t\t\tPERIPHP p = (*pl)[k-1];\n\t\t\tconst char *pn = p->p_name->c_str(),\n\t\t\t\t*pfx = p->bus_prefix()->c_str();\n\t\t\t// int\taw = p->p_awid + unused_lsbs;\n\n\t\t\tfprintf(fp, \"\\t// %s\\n\"\n\t\t\t\t\"\\t// {{{\\n\", pn);\n\t\t\tfprintf(fp, \"\\tassign %s_awaddr = %s_diow_awaddr;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_awprot = %s_diow_awprot;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_wvalid = %s_awvalid;\\n\", pfx, pfx);\n\t\t\tfprintf(fp, \"\\tassign %s_wdata = %s_diow_wdata;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_wstrb = %s_diow_wstrb;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_bready = 1\\'b1;\\n\", pfx);\n\t\t\tfprintf(fp, \"\\tassign %s_araddr = %s_diow_araddr;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_arprot = %s_diow_arprot;\\n\", pfx, n->c_str());\n\t\t\tfprintf(fp, \"\\tassign %s_rready = 1\\'b1;\\n\"\n\t\t\t\t\"\\t// }}}\\n\", pfx);\n\t\t}\n\n\t\tif (m_is_double)\n\t\t\treturn;\n\t\t// }}}\n\t} else if (!m_dlist)\n\t\tfprintf(fp, \"\\t//\\n\\t// No class DOUBLE peripherals on the \\\"%s\\\" bus\\n\\t//\\n\\n\", n->c_str());\n\n\t//\n\t//\n\t// Now for the main set of slaves\n\t//\n\t//\n\tpl = m_info->m_plist;\n\n\tunsigned\tslave_name_width = 4;\n\t// Find the maximum width of any slaves name, for our comment tables\n\t// below\n\tfor(unsigned k=0; k<m_info->m_plist->size(); k++) {\n\t\tPERIPHP\tp = (*m_info->m_plist)[k];\n\t\tunsigned\tsz;\n\n\t\tsz = p->name()->size();\n\t\tif (slave_name_width < sz)\n\t\t\tslave_name_width = sz;\n\t}\n\n\t//\n\t// Now create the crossbar interconnect\n\t//\n\t// if ((m_mlist->size() == 1)&&(m_info->m_plist->size() == 1))\n\t//\tspecial case we dealt with above\n\n\tfprintf(fp,\n\t\"\\t////////////////////////////////////////////////////////////////////////\\n\"\n\t\"\\t//\\n\"\n\t\"\\t// Connect the %s bus components together using the axilxbar()\\n\"\n\t\"\\t// {{{\\n\"\n\t\"\\t//\\n\", n->c_str());\n\n\tfprintf(fp,\n\t\"\\taxilxbar #(\\n\"\n\t\"\\t\\t// {{{\\n\"\n\t\"\\t\\t.C_AXI_ADDR_WIDTH(%d),\\n\"\n\t\"\\t\\t.C_AXI_DATA_WIDTH(%d),\\n\"\n\t\"\\t\\t.NM(%ld), .NS(%ld),\\n\",\n\t\taddress_width(),\n\t\tm_info->data_width(),\n\t\tm_mlist->size(),\n\t\tm_info->m_plist->size());\n\tslave_addr(fp, m_info->m_plist); fprintf(fp, \",\\n\");\n\tslave_mask(fp, m_info->m_plist);\n\n\txbar_option(fp, KY_OPT_LOWPOWER,  \",\\n\\t\\t.OPT_LOWPOWER(%)\", \"1\\'b1\");\n\txbar_option(fp, KY_OPT_LINGER,    \",\\n\\t\\t.OPT_LINGER(%)\");\n\txbar_option(fp, KY_OPT_LGMAXBURST,\",\\n\\t\\t.LGMAXBURST(%)\");\n\t//\n\tfprintf(fp,\n\t\"\\n\\t\\t// }}}\\n\"\n\t\"\\t) %s_xbar(\\n\"\n\t\t\"\\t\\t// {{{\\n\"\n\t\t\"\\t\\t.S_AXI_ACLK(%s),\\n\",\n\t\tn->c_str(), m_info->m_clock->m_wire->c_str());\n\tfprintf(fp, \"\\t\\t.S_AXI_ARESETN(%s),\\n\", rst->c_str());\n\n\tfprintf(fp, \"\\t\\t// Connections from masters\\n\"\n\t\t\"\\t\\t// {{{\\n\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"AWVALID\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"AWREADY\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"AWADDR\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"AWPROT\");\n\tfprintf(fp, \"\\t\\t//\\n\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"WVALID\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"WREADY\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"WDATA\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"WSTRB\");\n\tfprintf(fp, \"\\t\\t//\\n\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"BVALID\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"BREADY\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"BRESP\");\n\tfprintf(fp, \"\\t\\t// Read connections\\n\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"ARVALID\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"ARREADY\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"ARADDR\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"ARPROT\");\n\tfprintf(fp, \"\\t\\t//\\n\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"RVALID\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"RREADY\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"RDATA\");\n\txbarcon_master(fp, \"\\t\\t\",\".S_AXI_\",\"RRESP\");\n\tfprintf(fp, \"\\t\\t// }}}\\n\");\n\tfprintf(fp, \"\\t\\t// Connections to slaves\\n\");\n\tfprintf(fp, \"\\t\\t// {{{\\n\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWVALID\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWREADY\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWADDR\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"AWPROT\");\n\tfprintf(fp, \"\\t\\t//\\n\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"WVALID\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"WREADY\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"WDATA\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"WSTRB\");\n\tfprintf(fp, \"\\t\\t//\\n\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"BVALID\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"BREADY\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"BRESP\");\n\tfprintf(fp, \"\\t\\t// Read connections\\n\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARVALID\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARREADY\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARADDR\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"ARPROT\");\n\tfprintf(fp, \"\\t\\t//\\n\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"RVALID\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"RREADY\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"RDATA\");\n\txbarcon_slave(fp, pl, \"\\t\\t\",\".M_AXI_\",\"RRESP\", false);\n\tfprintf(fp, \"\\t\\t// }}}\\n\"\n\t\t\"\\t\\t// }}}\\n\\t);\\n\\n\");\n\n\tfor(unsigned k=0; k < m_info->m_plist->size(); k++) {\n\t\t// Handle read only or write only slaves\n\t\t// {{{\n\t\tPERIPHP p = (*m_info->m_plist)[k];\n\t\tSTRINGP\tbusp = p->bus_prefix();\n\t\tconst char\t*bp = busp->c_str();\n\n\t\tif (p->write_only()) {\n\t\t\tfprintf(fp,\n\t\"\\taxilempty #(\\n\"\n\t\"\\t\\t// {{{\\n\"\n\t\"\\t\\t.C_AXI_ADDR_WIDTH(%d),\\n\"\n\t\"\\t\\t.C_AXI_DATA_WIDTH(%d)\\n\"\n\t\"\\t\\t// }}}\\n\",\n\t\t\t\taddress_width(),\n\t\t\t\tm_info->data_width());\n\n\t\t\tfprintf(fp,\n\t\"\\t) %s_no_slavep (\\n\"\n\t\t\"\\t\\t// {{{\\n\"\n\t\t\"\\t\\t.S_AXI_ACLK(%s), .S_AXI_ARESETN(%s),\\n\"\n\t\t\"\\t\\t//\\n\",\n\t\t\tbp, c->m_wire->c_str(), rst->c_str());\n\n\t\t\tfprintf(fp,\n\t\t\"\\t\\t// Verilator lint_off PINCONNECTEMPTY\\n\"\n\t\t\"\\t\\t.S_AXI_AWVALID(1\\'b0), .S_AXI_AWREADY(),\\n\"\n\t\t\"\\t\\t.S_AXI_WVALID(1\\'b0),  .S_AXI_WREADY(),\\n\"\n\t\t\"\\t\\t//\\n\"\n\t\t\"\\t\\t.S_AXI_BVALID(),   .S_AXI_BREADY(1\\'b1),\\n\"\n\t\t\"\\t\\t.S_AXI_BRESP(),\\n\"\n\t\t\"\\t\\t// Verilator lint_on PINCONNECTEMPTY\\n\"\n\t\t\"\\t\\t//\\n\"\n\t\t\"\\t\\t.S_AXI_ARVALID(%s_arvalid), .S_AXI_ARREADY(%s_arready),\\n\"\n\t\t\"\\t\\t.S_AXI_RVALID(%s_rvalid),   .S_AXI_RREADY(%s_rready),\\n\"\n\t\t\"\\t\\t.S_AXI_RDATA(%s_rdata),   .S_AXI_RRESP(%s_rresp)\\n\"\n\t\t\"\\t\\t// }}}\\n\"\n\t\t\"\\t);\\n\\n\",\n\t\t\t\t// AW, W, B\n\t\t\t\t// AR\n\t\t\t\tbp, bp,\n\t\t\t\t// R\n\t\t\t\tbp, bp, bp, bp);\n\n\t\t}\n\t\tif (p->read_only()) {\n\t\t\tfprintf(fp,\n\t\"\\taxilempty #(\\n\"\n\t\"\\t\\t// {{{\\n\"\n\t\"\\t\\t.C_AXI_ADDR_WIDTH(%d),\\n\"\n\t\"\\t\\t.C_AXI_DATA_WIDTH(%d)\\n\"\n\t\"\\t\\t// }}}\\n\",\n\t\t\t\taddress_width(),\n\t\t\t\tm_info->data_width());\n\t\t\tfprintf(fp,\n\t\"\\t) %s_no_slavep (\\n\"\n\t\t\"\\t\\t// {{{\\n\"\n\t\t\"\\t\\t.S_AXI_ACLK(%s), .S_AXI_ARESETN(%s),\\n\"\n\t\t\"\\t\\t//\\n\",\n\t\t\tbp, c->m_wire->c_str(), rst->c_str());\n\n\t\t\tfprintf(fp,\n\t\t\"\\t\\t.S_AXI_AWVALID(%s_awvalid), .S_AXI_AWREADY(%s_awready),\\n\"\n\t\t\"\\t\\t.S_AXI_WVALID(%s_wvalid),  .S_AXI_WREADY(%s_wready),\\n\"\n\t\t\"\\t\\t//\\n\"\n\t\t\"\\t\\t.S_AXI_BVALID(%s_bvalid),   .S_AXI_BREADY(%s_bready),\\n\"\n\t\t\"\\t\\t.S_AXI_BRESP(%s_bresp),\\n\"\n\t\t\"\\t\\t//\\n\"\n\t\t\"\\t\\t// Verilator lint_off PINCONNECTEMPTY\\n\"\n\t\t\"\\t\\t.S_AXI_ARVALID(1\\'b0), .S_AXI_ARREADY(),\\n\"\n\t\t\"\\t\\t.S_AXI_RVALID(),   .S_AXI_RREADY(1\\'b1),\\n\"\n\t\t\"\\t\\t.S_AXI_RDATA(),   .S_AXI_RRESP()\\n\"\n\t\t\"\\t\\t// Verilator lint_on PINCONNECTEMPTY\\n\"\n\t\t\"\\t);\\n\\n\",\n\t\t\t\t// AW, W, B\n\t\t\t\tbp, bp, bp, bp, bp, bp, bp);\n\t\t}\n\t\t// }}}\n\t}\n\tfprintf(fp, \"\\t\\t// }}}\\n\");\n}\n\nSTRINGP\tAXILBUS::master_portlist(BMASTERP m) {\n\t// {{{\n\tSTRING\tstr;\n\n\tif (m->write_only())\n\t\tstr = str + STRING(\"// Master is write-only\\n\");\n\tif (m->read_only())\n\t\tstr = str + STRING(\"// Master is read only\\n\\t\\t\");\n\telse\n\t\tstr = str + STRING(\n\t\"@$(MASTER.PREFIX)_awvalid,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_awready,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_awaddr[@$(MASTER.BUS.AWID)-1:0],\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_awprot,\\n\"\n\t\"\\t\\t//\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_wvalid,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_wready,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_wdata,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_wstrb,\\n\"\n\t\"\\t\\t//\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_bvalid,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_bready,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_bresp\");\n\tif (!m->read_only() && !m->write_only())\n\t\tstr = str + STRING(\",\\n\\t\\t// Read connections\\n\\t\\t\");\n\tif (!m->write_only())\n\t\tstr = str + STRING(\n\t\"@$(MASTER.PREFIX)_arvalid,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_arready,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_araddr[@$(MASTER.BUS.AWID)-1:0],\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_arprot,\\n\"\n\t\"\\t\\t//\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_rvalid,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_rready,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_rdata,\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_rresp\");\n\n\treturn new STRING(str);\n}\n// }}}\n\nSTRINGP\tAXILBUS::iansi(BMASTERP m) {\n\treturn new STRING(\"\");\n}\n\nSTRINGP\tAXILBUS::oansi(BMASTERP m) {\n\treturn new STRING(\"\");\n}\n\nSTRINGP\tAXILBUS::master_ansprefix(BMASTERP m) {\n\treturn new STRING(\"M_AXI_\");\n}\n\nSTRINGP\tAXILBUS::master_ansi_portlist(BMASTERP m) {\n\t// {{{\n\tSTRING\tstr;\n\n\tif (!m->read_only())\n\t\tstr = str + STRING(\n\t\".@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)AWVALID(@$(MASTER.PREFIX)_awvalid),\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)AWREADY(@$(MASTER.PREFIX)_awready),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)AWADDR( @$(MASTER.PREFIX)_awaddr[@$(MASTER.BUS.AWID)-1:0]),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)AWPROT( @$(MASTER.PREFIX)_awprot),\\n\"\n\t\"\\t\\t//\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)WVALID(@$(MASTER.PREFIX)_wvalid),\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)WREADY(@$(MASTER.PREFIX)_wready),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)WDATA( @$(MASTER.PREFIX)_wdata),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)WSTRB( @$(MASTER.PREFIX)_wstrb),\\n\"\n\t\"\\t\\t//\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)BVALID(@$(MASTER.PREFIX)_bvalid),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)BREADY(@$(MASTER.PREFIX)_bready),\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)BRESP( @$(MASTER.PREFIX)_bresp)\");\n\tif (!m->read_only() && !m->write_only())\n\t\tstr = str + STRING(\",\\n\\t\\t// Read connections\\n\\t\\t\");\n\tif (!m->write_only())\n\t\tstr = str + STRING(\n\t\".@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)ARVALID(@$(MASTER.PREFIX)_arvalid),\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)ARREADY(@$(MASTER.PREFIX)_arready),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)ARADDR( @$(MASTER.PREFIX)_araddr[@$(MASTER.BUS.AWID)-1:0]),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)ARPROT( @$(MASTER.PREFIX)_arprot),\\n\"\n\t\"//\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)RVALID(@$(MASTER.PREFIX)_rvalid),\\n\"\n\t\"\\t\\t.@$(MASTER.IANSI)@$(MASTER.ANSPREFIX)RREADY(@$(MASTER.PREFIX)_rready),\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)RDATA( @$(MASTER.PREFIX)_rdata),\\n\"\n\t\"\\t\\t.@$(MASTER.OANSI)@$(MASTER.ANSPREFIX)RRESP( @$(MASTER.PREFIX)_rresp)\");\n\n\treturn new STRING(str);\n}\n// }}}\n\nSTRINGP\tAXILBUS::slave_ansprefix(PERIPHP m) {\n\treturn new STRING(\"S_AXI_\");\n}\n\nSTRINGP\tAXILBUS::slave_portlist(PERIPHP p) {\n\t// {{{\n\tSTRING\tstr;\n\n\tif (p->write_only())\n\t\tstr = str + STRING(\"// Slave is write-only\\n\\t\\t\");\n\tif (p->read_only())\n\t\tstr = str + STRING(\"// Slave is read only\\n\\t\\t\");\n\telse {\n\t\tstr = str + STRING(\n\t\"\\t\\t@$(SLAVE.PREFIX)_awvalid,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_awready,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_awaddr[\")\n\t\t+ std::to_string(p->get_slave_address_width())\n\t\t+ STRING(\"-1:0],\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_awprot,\\n\"\n\t\"//\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_wvalid,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_wready,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_wdata,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_wstrb,\\n\"\n\t\"//\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_bvalid,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_bready,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_bresp\");\n\t}\n\tif (!p->read_only() && !p->write_only())\n\t\tstr = str + STRING(\",\\n\\t\\t// Read connections\\n\");\n\tif (!p->write_only())\n\t\tstr = str + STRING(\n\t\"\\t\\t@$(SLAVE.PREFIX)_arvalid,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_arready,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_araddr[\")\n\t\t+ std::to_string(p->get_slave_address_width())\n\t\t+ STRING(\"-1:0],\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_arprot,\\n\"\n\t\"//\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_rvalid,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_rready,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_rdata,\\n\"\n\t\"\\t\\t@$(SLAVE.PREFIX)_rresp\");\n\n\treturn new STRING(str);\n}\n// }}}\n\nSTRINGP\tAXILBUS::slave_ansi_portlist(PERIPHP p) {\n\t// {{{\n\tSTRING\tstr;\n\n\tif (!p->read_only())\n\t\tstr = str + STRING(\n\t\".@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)AWVALID(@$(SLAVE.PREFIX)_awvalid),\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)AWREADY(@$(SLAVE.PREFIX)_awready),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)AWADDR( @$(SLAVE.PREFIX)_awaddr[\")\n\t\t+ std::to_string(p->get_slave_address_width())\n\t\t+ STRING(\"-1:0]),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)AWPROT( @$(SLAVE.PREFIX)_awprot),\\n\"\n\t\"//\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)WVALID(@$(SLAVE.PREFIX)_wvalid),\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)WREADY(@$(SLAVE.PREFIX)_wready),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)WDATA( @$(SLAVE.PREFIX)_wdata),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)WSTRB( @$(SLAVE.PREFIX)_wstrb),\\n\"\n\t\"//\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)BVALID(@$(SLAVE.PREFIX)_bvalid),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)BREADY(@$(SLAVE.PREFIX)_bready),\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)BRESP( @$(SLAVE.PREFIX)_bresp),\\n\");\n\tif (!p->read_only() && !p->write_only())\n\t\tstr = str + STRING(\"\\t\\t// Read connections\\n\");\n\tif (!p->write_only())\n\t\tstr = str + STRING(\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)ARVALID(@$(SLAVE.PREFIX)_arvalid),\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)ARREADY(@$(SLAVE.PREFIX)_arready),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)ARADDR( @$(SLAVE.PREFIX)_araddr[\")\n\t\t+ std::to_string(p->get_slave_address_width())\n\t\t+ STRING(\"-1:0]),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)ARPROT( @$(SLAVE.PREFIX)_arprot),\\n\"\n\t\"//\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)RVALID(@$(SLAVE.PREFIX)_rvalid),\\n\"\n\t\"\\t\\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)RREADY(@$(SLAVE.PREFIX)_rready),\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)RDATA( @$(SLAVE.PREFIX)_rdata),\\n\"\n\t\"\\t\\t.@$(SLAVE.OANSI)@$(SLAVE.ANSPREFIX)RRESP( @$(SLAVE.PREFIX)_rresp)\");\n\n\treturn new STRING(str);\n}\n// }}}\n\n////////////////////////////////////////////////////////////////////////\n//\n// Bus class logic\n//\n// The bus class describes the logic above in a way that it can be\n// chosen, selected, and enacted within a design.  Hence if a design\n// has four wishbone buses and one AXI-lite bus, the bus class logic\n// will recognize the four WB buses and generate WB bus generators,\n// and then an AXI-lite bus and bus generator, etc.\n//\n////////////////////////////////////////////////////////////////////////\nSTRINGP\tAXILBUSCLASS::name(void) {\n\treturn new STRING(\"axil\");\n}\n\nSTRINGP\tAXILBUSCLASS::longname(void) {\n\treturn new STRING(\"AXI-lite\");\n}\n\nbool\tAXILBUSCLASS::matchtype(STRINGP str) {\n\tif (!str)\n\t\t// We are not the default\n\t\treturn false;\n\tif (strcasecmp(str->c_str(), \"axil\")==0)\n\t\treturn true;\n\tif (strcasecmp(str->c_str(), \"axi-lite\")==0)\n\t\treturn true;\n\tif (strcasecmp(str->c_str(), \"axi lite\")==0)\n\t\treturn true;\n// printf(\"ERR: No match for bus type %s\\n\",str->c_str());\n\treturn false;\n}\n\nbool\tAXILBUSCLASS::matchfail(MAPDHASH *bhash) {\n\treturn false;\n}\n\nGENBUS *AXILBUSCLASS::create(BUSINFO *bi) {\n\tAXILBUS\t*busclass;\n\n\tbusclass = new AXILBUS(bi);\n\treturn busclass;\n}\n"
  },
  {
    "path": "sw/bus/axil.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bus/axil.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tAXI-lite interface--for high speed AXI-lite cores.  (Slow speed\n//\t\tones should work too if they follow the spec)\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tAXIL_H\n#define\tAXIL_H\n\n#include \"../genbus.h\"\n\nclass\tAXILBUS : public GENBUS {\nprotected:\n\tPLIST\t\t*m_slist, *m_dlist;\n\tMAPDHASH\t*m_interconnect;\n\tunsigned\tm_num_total, m_num_double, m_num_single;\n\tbool\t\tm_is_single, m_is_double;\n\n\tvoid\txbarcon_master(FILE *fp, const char *, const char *,\n\t\t\tconst char *, bool comma=true);\n\tvoid\txbarcon_slave(FILE *fp, PLIST *pl,\n\t\t\tconst char *, const char *, const char *, bool comma=true);\n\tSTRINGP\tmaster_name(int k);\n\tvoid\tallocate_subbus(void);\n\n\tBUSINFO *create_sio(void);\n\tBUSINFO *create_dio(void);\n\tvoid\tcountsio(void);\npublic:\n\tAXILBUS(BUSINFO *bi);\n\t~AXILBUS() {};\n\tvirtual\tint\taddress_width(void);\n\tvirtual\tbool\tword_addressing(void) { return false; };\n\t//\n\tvirtual\tvoid\tassign_addresses(void);\n\tvirtual\tbool\tget_base_address(MAPDHASH *phash, unsigned &base);\n\n\tvoid\t\twrite_addr_range(FILE *fp, const PERIPHP p,\n\t\t\t\tconst int dalines);\n\tvirtual\tvoid\twriteout_defn_v(FILE *fp, const char *mstype,\n\t\t\t\tconst char *pname,\n\t\t\t\tconst char *busp, const char *btyp = \"\");\n\tvirtual\tvoid\twriteout_bus_slave_defns_v(FILE *fp);\n\tvirtual\tvoid\twriteout_bus_master_defns_v(FILE *fp);\n\n\tvirtual\tvoid\twriteout_bus_logic_v(FILE *fp);\n\n\tvirtual\tvoid\twriteout_no_slave_v(FILE *fp, STRINGP prefix);\n\tvirtual\tvoid\twriteout_no_master_v(FILE *fp);\n\t//\n\t//\n\tvirtual\tSTRINGP\tiansi(BMASTERP);\n\tvirtual\tSTRINGP\toansi(BMASTERP);\n\tvirtual\tSTRINGP\tmaster_ansprefix(BMASTERP);\n\tvirtual\tSTRINGP\tmaster_portlist(BMASTERP);\n\tvirtual\tSTRINGP\tmaster_ansi_portlist(BMASTERP);\n\tvirtual\tSTRINGP\tslave_ansprefix(PERIPHP);\n\tvirtual\tSTRINGP\tslave_portlist(PERIPHP);\n\tvirtual\tSTRINGP\tslave_ansi_portlist(PERIPHP);\n\n\tvirtual\tvoid\tintegrity_check(void);\n};\n\nclass\tAXILBUSCLASS : public BUSCLASS {\npublic:\n\tvirtual\tSTRINGP\tname(void);\t// i.e. WB\n\tvirtual\tSTRINGP\tlongname(void);\t// i.e. \"Wishbone\"\n\tvirtual\tbool\tmatchtype(STRINGP strp);\n\tvirtual\tbool\tmatchfail(MAPDHASH *);\n\t// virtual\tbool\tmatches(BUSINFO *bi);\n\tGENBUS\t*create(BUSINFO *bi);\n};\n\n#endif\n"
  },
  {
    "path": "sw/bus/wb.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bus/wb.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\n// Tags used:\n//\n//\tBUS.WIDTH\n//\tBUS.AWID\n//\n//\tSLAVE.TYPE:\n//\t- SINGLE\n//\t- DOUBLE\n//\t- OTHER/MEMORY/BUS\n//\tSLAVE.PREFIX:\n//\t\tA string to use to prefix all of the slave's bus wires when\n//\t\t\tnaming\n//\tSLAVE.OPTIONS= (unused)\n//\t\tRO (read only slave)\n//\t\tWO (write only slave)\n//\t\t(default: read and write)\n//\tSLAVE.SHARE=\n//\t// slave shares parts of the interface with the other listed slaves\n//\n//\tMASTER.TYPE=\n//\t(currently ignored)\n//\tMASTER.PREFIX:\n//\t\tA string to use to prefix all of the master's bus wires when\n//\t\t\tnaming\n//\tMASTER.OPTIONS= (unused)\n//\t\tRO (read only master)\n//\t\tWO (write only master)\n//\t\t(default: read and write)\n//\n//\t// INTERCONNECT.TYPE (Not used)\n//\t// - SINGLE\t(Deprecated interconnect)\n//\t// - CROSSBAR\n//\n//\tBUS.OPT_LOWPOWER\n//\t\tIf set, forces bus wires to zero when stb (or ack) is low.\n//\tBUS.OPT_DBLBUFFER\n//\t\tIf set, uses an extra clock on the return--for better clock\n//\t\tspeed performance\n//\tBUS.OPT_LGMAXBURST\n//\t\tLog_2 of the maximum number of transactions \"in-flight\" at any\n//\t\tgiven time.  This sets the bit-width of the internal transaction\n//\t\tcounter\n//\tBUS.OPT_TIMEOUT\n//\t\tBus cycles before timing out on any operation\n//\tBUS.OPT_STARVATION_TIMEOUT\n//\t\t(Currently ignored)\n//\n// Creates tags:\n//\n//\tSLAVE.PORTLIST:\tA list of bus interconnect parameters, somewhat like:\n//\t\t\t@$(SLAVE.PREFIX)_cyc,\n//\t\t\t@$(SLAVE.PREFIX)_stb,\n//\t(if !RO&!WO)\t@$(SLAVE.PREFIX)_we,\n//\t(if AWID>0)\t@$(SLAVE.PREFIX)_addr[@$(SLAVE.AWID)-1:0],\n//\t(if !RO)\t@$(SLAVE.PREFIX)_data,\n//\t(if !RO)\t@$(SLAVE.PREFIX)_sel,\n//\t\t\t@$(SLAVE.PREFIX)_stall,\n//\t\t\t@$(SLAVE.PREFIX)_ack,\n//\t(if !WO)\t@$(SLAVE.PREFIX)_data,\n//\t(and possibly)\t@$(SLAVE.PREFIX)_err\n//\n//\t... only, I've currently chosen to do this in a slave independent\n//\tfashion, and so the ROM, WOM, and AWID strings get set as a default\n//\n//\tSLAVE.ANSIPORTLIST ... same thing,\n//\n//\tSLAVE.IANSI: i_\n//\tSLAVE.OANSI: o_\n//\tSLAVE.ANSPREFIX:\n//\tSLAVE.ANSSUFFIX:\n//\t\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)cyc@$(SLAVE.ANSSUFFIX)(@$SLAVE.BUS)_cyc),\n//\t\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)stb@$(SLAVE.ANSSUFFIX)(@$SLAVE.BUS)_stb),\n//\t\t.@$(SLAVE.IANSI)@$(SLAVE.ANSPREFIX)we@$(SLAVE.ANSSUFFIX)(@$SLAVE.BUS)_we),\n//\t\t\t.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <string.h>\n#include <unistd.h>\n#include <ctype.h>\n\n#include \"../parser.h\"\n#include \"../mapdhash.h\"\n#include \"../keys.h\"\n#include \"../kveval.h\"\n#include \"../legalnotice.h\"\n#include \"../bldtestb.h\"\n#include \"../bitlib.h\"\n#include \"../plist.h\"\n#include \"../bldregdefs.h\"\n#include \"../ifdefs.h\"\n#include \"../bldsim.h\"\n#include \"../predicates.h\"\n#include \"../businfo.h\"\n#include \"../globals.h\"\n#include \"../subbus.h\"\n#include \"../msgs.h\"\n#include \"../genbus.h\"\n\n#include \"wb.h\"\n\n#define\tPREFIX\n\nextern\tWBBUSCLASS\twbclass;\n\nWBBUS::WBBUS(BUSINFO *bi) {\n\t// {{{\n\tm_info = bi;\n\tm_slist = NULL;\n\tm_dlist = NULL;\n\n\tm_is_single = false;\n\tm_is_double = false;\n\n\tm_num_single = 0;\n\tm_num_double = 0;\n\tm_num_total = 0;\n}\n// }}}\n\nvoid\tWBBUS::allocate_subbus(void) {\n\t// {{{\n\tPLIST\t*pl = m_info->m_plist;\n\tBUSINFO\t*sbi = NULL, *dbi = NULL;\n\n\tif (NULL == pl || pl->size() == 0) {\n\t\tgbl_msg.warning(\"Bus %s has no attached slaves\\n\",\n\t\t\t(name()) ? name()->c_str() : \"(No-name)\");\n\t}\n\n\tgbl_msg.info(\"Generating WB bus logic generator for %s\\n\",\n\t\t(name()) ? name()->c_str() : \"(No-name)\");\n\tcountsio();\n\n\tif (m_num_single == m_num_total) {\n\t\tm_num_single = 0;\n\t\tm_is_single = true;\n\t} else if ((m_num_single <= 2)&&(m_num_double > 0)) {\n\t\tm_num_double += m_num_single;\n\t\tm_num_single = 0;\n\t}\n\n\tif (!m_is_single && m_num_single + m_num_double == m_num_total) {\n\t\tm_num_double = 0;\n\t\tm_is_double  = true;\n\t} else if (m_num_double <= 2)\n\t\tm_num_double = 0;\n\n\tassert(!m_is_single || !m_is_double);\n\tassert(m_num_single < 50);\n\tassert(m_num_double < 50);\n\tassert(m_num_total >= m_num_single + m_num_double);\n\n\t//\n\t// Master of multiple classes\n\t//\n\tif (!m_is_single && m_num_single > 0) {\n\t\tsbi = create_sio();\n\t\tm_num_total++;\n\t}\n\n\tif (!m_is_double && m_num_double > 0) {\n\t\tm_num_total++;\n\t\tdbi = create_dio();\n\t}\n\n\tif (!m_is_double && !m_is_single && pl) {\n\t\t//\n\t\t// There exist peripherals that are neither singles nor doubles\n\t\t//\n\t\tfor(unsigned pi = 0; pi< pl->size(); pi++) {\n\t\t\tPERIPHP\tp = (*pl)[pi];\n\t\t\tSTRINGP\tptyp;\n\n\t\t\tptyp = getstring(p->p_phash, KYSLAVE_TYPE);\n\t\t\tif (m_slist && ptyp != NULL\n\t\t\t\t&& ptyp->compare(KYSINGLE) == 0) {\n\t\t\t\tm_info->m_plist->erase(pl->begin()+pi);\n\t\t\t\tpi--;\n\t\t\t\tm_slist->add(p);\n\t\t\t} else if (m_dlist && ptyp != NULL\n\t\t\t\t\t\t&& ptyp->compare(KYDOUBLE) == 0) {\n\t\t\t\tm_info->m_plist->erase(pl->begin()+pi);\n\t\t\t\tpi--;\n\t\t\t\tm_dlist->add(p);\n\t\t\t} else {\n\t\t\t// Leave this peripheral in m_info->m_plist\n\t\t\t}\n\t\t}\n\t}\n\n//\tcountsio();\n\n\tif (sbi)\n\t\tsetstring(sbi->m_hash, KY_TYPE, wbclass.name());\n\tif (dbi)\n\t\tsetstring(dbi->m_hash, KY_TYPE, wbclass.name());\n\tREHASH;\n}\n// }}}\n\nint\tWBBUS::address_width(void) {\n\tassert(m_info);\n\treturn m_info->m_address_width;\n}\n\nbool\tWBBUS::get_base_address(MAPDHASH *phash, unsigned &base) {\n\t// {{{\n\tif (!m_info || !m_info->m_plist) {\n\t\tgbl_msg.error(\"BUS[%s] has no peripherals!\\n\",\n\t\t\t(name()) ? name()->c_str() : \"(No name)\");\n\t\treturn false;\n\t} else\n\t\treturn m_info->m_plist->get_base_address(phash, base);\n}\n// }}}\n\nvoid\tWBBUS::assign_addresses(void) {\n\t// {{{\n\tint\taddress_width;\n\n\tif (m_info->m_addresses_assigned)\n\t\treturn;\n\tif ((NULL == m_slist)&&(NULL == m_dlist))\n\t\tallocate_subbus();\n\n\tif (!m_info)\n\t\treturn;\n\tgbl_msg.info(\"WB: Assigning addresses for bus %s\\n\",\n\t\t(name()) ? name()->c_str() : \"(No name bus)\");\n\tif (!m_info->m_plist||(m_info->m_plist->size() < 1)) {\n\t\tm_info->m_address_width = 0;\n\t} else if (!m_info->m_addresses_assigned) {\n\t\tint\tdw = m_info->data_width(),\n\t\t\tnullsz;\n\n\t\tif (m_slist)\n\t\t\tm_slist->assign_addresses(dw, 0);\n\n\t\tif (m_dlist)\n\t\t\tm_dlist->assign_addresses(dw, 0);\n\n\t\tif (!getvalue(*m_info->m_hash, KY_NULLSZ, nullsz))\n\t\t\tnullsz = 0;\n\n\t\tm_info->m_plist->assign_addresses(dw, nullsz);\n\t\taddress_width = m_info->m_plist->get_address_width();\n\t\tm_info->m_address_width = address_width;\n\t\tif (m_info->m_hash) {\n\t\t\tsetvalue(*m_info->m_hash, KY_AWID, m_info->m_address_width);\n\t\t\tREHASH;\n\t\t}\n\t} m_info->m_addresses_assigned = true;\n}\n// }}}\n\nBUSINFO *WBBUS::create_sio(void) {\n\t// {{{\n\tassert(m_info);\n\n\tBUSINFO\t*sbi;\n\tSUBBUS\t*subp;\n\tSTRINGP\tsioname;\n\tMAPDHASH *bushash, *shash;\n\tMAPT\telm;\n\n\tsioname = new STRING(STRING(\"\" PREFIX) + (*name()) + \"_sio\");\n\tbushash = new MAPDHASH();\n\tshash   = new MAPDHASH();\n\tsetstring(*shash, KYPREFIX, sioname);\n\tsetstring(*shash, KYSLAVE_TYPE, new STRING(KYDOUBLE));\n\tsetstring(*shash, KYSLAVE_PREFIX, sioname);\n\n\telm.m_typ = MAPT_MAP;\n\telm.u.m_m = bushash;\n\tshash->insert(KEYVALUE(KYSLAVE_BUS, elm));\n\n\telm.u.m_m = m_info->m_hash;\n\tshash->insert(KEYVALUE(KYMASTER_BUS, elm));\n\tsetstring(shash, KYMASTER_TYPE, KYARBITER);\n\n\tsbi  = new BUSINFO(sioname);\n\tsbi->prefix(new STRING(\"_sio\"));\n\tsetstring(bushash, KY_TYPE, new STRING(\"wb\"));\n\tsbi->m_data_width = m_info->m_data_width;\n\tsbi->m_clock      = m_info->m_clock;\n\tsbi->addmaster(m_info->m_hash);\n\tsubp = new SUBBUS(shash, sioname, sbi);\n\tsubp->p_slave_bus = m_info;\n\t// subp->p_master_bus = set by the SUBBUS to be sbi\n\tm_info->m_plist->add(subp);\nassert(subp->p_master_bus);\nassert(subp->p_slave_bus == m_info);\nassert(subp->p_master_bus == sbi);\n\t// m_plist->integrity_check();\n\tsbi->add();\n\tm_slist = sbi->m_plist;\n\n\treturn sbi;\n}\n// }}}\n\nBUSINFO *WBBUS::create_dio(void) {\n\t// {{{\n\tassert(m_info);\n\n\tBUSINFO\t*dbi;\n\tSUBBUS\t*subp;\n\tSTRINGP\tdioname;\n\tMAPDHASH\t*bushash, *shash;\n\tMAPT\telm;\n\n\tdioname = new STRING(STRING(\"\" PREFIX) + (*name()) + \"_dio\");\n\tbushash = new MAPDHASH();\n\tshash   = new MAPDHASH();\n\tsetstring(*bushash, KY_NAME, dioname);\n\tsetstring(*shash, KYPREFIX, dioname);\n\tsetstring(*shash, KYSLAVE_TYPE, new STRING(KYOTHER));\n\tsetstring(*shash, KYSLAVE_PREFIX, dioname);\n\n\telm.m_typ = MAPT_MAP;\n\telm.u.m_m = m_info->m_hash;\n\tshash->insert(KEYVALUE(KYSLAVE_BUS, elm));\n\n\telm.u.m_m = bushash;\n\tshash->insert(KEYVALUE(KYMASTER_BUS, elm));\n\tsetstring(shash, KYMASTER_TYPE, KYARBITER);\n\n\tdbi  = new BUSINFO(dioname);\n\tdbi->prefix(new STRING(\"_dio\"));\n\tsetstring(bushash, KY_TYPE, new STRING(\"wb\"));\nassert(m_info->data_width() > 0);\n\tsetvalue(*bushash, KY_WIDTH, m_info->data_width());\n\tdbi->m_data_width = m_info->m_data_width;\n\tdbi->m_clock      = m_info->m_clock;\n\tdbi->addmaster(m_info->m_hash);\n\tsubp = new SUBBUS(shash, dioname, dbi);\n\tsubp->p_slave_bus = m_info;\n\tm_info->m_plist->add(subp);\nassert(subp->p_master_bus);\nassert(subp->p_master_bus == dbi);\nassert(subp->p_slave_bus == m_info);\n\t// subp->p_master_bus = set by the slave to be dbi\n\tdbi->add();\n\tm_dlist = dbi->m_plist;\nassert(isbusmaster(*shash));\nassert(isarbiter(*shash));\n\n\treturn dbi;\n}\n// }}}\n\nvoid\tWBBUS::countsio(void) {\n\t// {{{\n\tPLIST\t*pl = m_info->m_plist;\n\tSTRINGP\tstrp;\n\n\tm_num_single = 0;\n\tm_num_double = 0;\n\tm_num_total = 0;\n\n\tif (NULL == pl)\n\t\treturn;\n\n\tfor(unsigned pi=0; pi< pl->size(); pi++) {\n\t\tstrp = getstring((*pl)[pi]->p_phash, KYSLAVE_TYPE);\n\t\tif (NULL != strp) {\n\t\t\tif (0==strp->compare(KYSINGLE)) {\n\t\t\t\tm_num_single++;\n\t\t\t} else if (0==strp->compare(KYDOUBLE)) {\n\t\t\t\tm_num_double++;\n\t\t\t} m_num_total++;\n\t\t} else\n\t\t\tm_num_total++;\t// Default to OTHER if no type is given\n\t}\n}\n// }}}\n\nvoid\tWBBUS::integrity_check(void) {\n\t// {{{\n\t// GENBUS::integrity_check();\n\n\tif (m_info && m_info->m_data_width <= 0) {\n\t\tgbl_msg.error(\"ERR: BUS width not defined for %s\\n\",\n\t\t\tname()->c_str());\n\t}\n}\n// }}}\n\nvoid\tWBBUS::writeout_defn_v(FILE *fp, const char* pname,\n\t\tconst char *pfx,\n\t\tconst int aw, const int dw,\n\t\tconst char *errwire, const char *btyp) {\n\t// {{{\n\tSTRINGP\tn = name();\n\n\tfprintf(fp, \"\\t// Wishbone definitions for bus %s%s, component %s\\n\",\n\t\tn->c_str(), btyp, pname);\n\tfprintf(fp, \"\\t// Verilator lint_off UNUSED\\n\");\n\tfprintf(fp, \"\\twire\\t\\t%s_cyc, %s_stb, %s_we;\\n\",\n\t\tpfx, pfx, pfx);\n\tfprintf(fp, \"\\twire\\t[%d:0]\\t%s_addr;\\n\", address_width()-1, pfx);\n\tfprintf(fp, \"\\twire\\t[%d:0]\\t%s_data;\\n\", dw-1, pfx);\n\tfprintf(fp, \"\\twire\\t[%d:0]\\t%s_sel;\\n\", dw/8-1, pfx);\n\tfprintf(fp, \"\\twire\\t\\t%s_stall, %s_ack, %s_err\", pfx, pfx, pfx);\n\tif ((errwire)&&(errwire[0] != '\\0')\n\t\t\t&&(STRING(STRING(pfx)+\"_err\").compare(errwire)!=0))\n\t\tfprintf(fp, \", %s;\\n\"\n\t\t\t\"\\tassign\\t\\t%s_err = %s; // P\\n\", errwire, pfx, errwire);\n\telse\n\t\tfprintf(fp, \";\\n\");\n\tfprintf(fp, \"\\twire\\t[%d:0]\\t%s_idata;\\n\", dw-1, pfx);\n\tfprintf(fp, \"\\t// Verilator lint_on UNUSED\\n\");\n}\n// }}}\n\nvoid\tWBBUS::writeout_bus_slave_defns_v(FILE *fp) {\n\t// {{{\n\tPLIST\t*p = m_info->m_plist;\n\tSTRINGP\tn = name();\n\n\tif (m_slist) {\n\t\tfor(PLIST::iterator pp=m_slist->begin();\n\t\t\t\tpp != m_slist->end(); pp++) {\n\t\t\tSTRINGP\terrwire = getstring((*pp)->p_phash, KYERROR_WIRE);\n\t\t\tSTRINGP\tprefix = (*pp)->bus_prefix();\n\t\t\twriteout_defn_v(fp, (*pp)->p_name->c_str(),\n\t\t\t\tprefix->c_str(),\n\t\t\t\t0, m_info->data_width(),\n\t\t\t\t(errwire)?errwire->c_str(): NULL,\n\t\t\t\t\"(SIO)\");\n\t\t}\n\t}\n\n\tif (m_dlist) {\n\t\tfor(PLIST::iterator pp=m_dlist->begin();\n\t\t\t\tpp != m_dlist->end(); pp++) {\n\t\t\tSTRINGP\terrwire = getstring((*pp)->p_phash, KYERROR_WIRE);\n\t\t\tSTRINGP\tprefix = (*pp)->bus_prefix();\n\t\t\twriteout_defn_v(fp, (*pp)->p_name->c_str(),\n\t\t\t\tprefix->c_str(),\n\t\t\t\t(*pp)->p_awid, m_info->data_width(),\n\t\t\t\t(errwire)?errwire->c_str(): NULL,\n\t\t\t\t\"(DIO)\");\n\t\t}\n\t}\n\n\tif (p) {\n\t\tfor(PLIST::iterator pp=p->begin(); pp != p->end(); pp++) {\n\t\t\tSTRINGP\terrwire = getstring((*pp)->p_phash, KYERROR_WIRE);\n\t\t\tSTRINGP\tprefix = (*pp)->bus_prefix();\n\t\t\twriteout_defn_v(fp, (*pp)->p_name->c_str(),\n\t\t\t\tprefix->c_str(),\n\t\t\t\t(*pp)->p_awid, m_info->data_width(),\n\t\t\t\t(errwire) ? errwire->c_str() : NULL);\n\t\t}\n\t} else {\n\t\tgbl_msg.error(\"%s has no slaves\\n\", n->c_str());\n\t}\n}\n// }}}\n\nvoid\tWBBUS::writeout_bus_master_defns_v(FILE *fp) {\n\t// {{{\n\tMLIST\t*m = m_info->m_mlist;\n\tif (m) {\n\t\tfor(MLIST::iterator pp=m->begin(); pp != m->end(); pp++) {\n\t\t\twriteout_defn_v(fp, (*pp)->name()->c_str(),\n\t\t\t\t(*pp)->bus_prefix()->c_str(),\n\t\t\t\taddress_width(), m_info->data_width(),\n\t\t\t\tNULL);\n\t\t}\n\t} else {\n\t\tgbl_msg.warning(\"Bus %s has no masters\\n\", name()->c_str());\n\t}\n}\n// }}}\n\nvoid\tWBBUS::write_addr_range(FILE *fp, const PERIPHP p, const int dalines) {\n\t// {{{\n\tunsigned\tw = address_width();\n\tw = (w+3)/4;\n\tif (p->p_naddr == 1)\n\t\tfprintf(fp, \" // 0x%0*lx\", w, p->p_base);\n\telse\n\t\tfprintf(fp, \" // 0x%0*lx - 0x%0*lx\", w, p->p_base,\n\t\t\tw, p->p_base + (p->p_naddr << (dalines))-1);\n}\n// }}}\n\nvoid\tWBBUS::writeout_bus_select_v(FILE *fp) {\n\t// {{{\n#ifdef\tDEPRECATED_CODE\n\t// {{{\n\tSTRINGP\tn = name();\n\tSTRING\taddrbus = STRING((*n)+\"_addr\");\n\tunsigned\tsbaw = address_width();\n\tunsigned\tdw   = m_info->data_width();\n\tunsigned\tdalines = nextlg(dw/8);\n\tunsigned\tunused_lsbs = 0, mask = 0;\n\n\tPLIST\t*p = m_info->m_plist;\n\n\tif (NULL == p) {\n\t\tgbl_msg.error(\"Bus[%s] has no peripherals\\n\", n->c_str());\n\t\treturn;\n\t}\n\n\tfprintf(fp, \"\\t//\\n\\t//\\n\\t//\\n\\t// Select lines for bus: %s\\n\\t//\\n\", n->c_str());\n\tfprintf(fp, \"\\t// Address width: %d\\n\",\n\t\tp->get_address_width());\n\tfprintf(fp, \"\\t// Data width:    %d\\n\\t//\\n\\t//\\n\\t\\n\",\n\t\tm_info->data_width());\n\n\tif (m_slist) {\n\t\tsbaw = m_slist->get_address_width();\n\t\tmask = 0; unused_lsbs = 0;\n\t\tfor(unsigned i=0; i<m_slist->size(); i++)\n\t\t\tmask |= (*m_slist)[i]->p_mask;\n\t\tfor(unsigned tmp=mask; ((tmp)&&((tmp&1)==0)); tmp>>=1)\n\t\t\tunused_lsbs++;\n\t\tfor(unsigned i=0; i<m_slist->size(); i++) {\n\t\t\tif ((*m_slist)[i]->p_mask == 0) {\n\t\t\t\tfprintf(fp, \"\\tassign\\t%12s_sel = 1\\'b0; // ERR: (SIO) address mask == 0\\n\",\n\t\t\t\t\t(*m_slist)[i]->p_name->c_str());\n\t\t\t} else {\n\t\t\t\tassert(sbaw > unused_lsbs);\n\t\t\t\tassert(sbaw > 0);\n\t\t\t\tfprintf(fp, \"\\tassign\\t%12s_sel = ((\" PREFIX \"%s_sio_sel)&&(%s_addr[%2d:%2d] == %2d\\'h%0*lx)); \",\n\t\t\t\t\t(*m_slist)[i]->p_name->c_str(), n->c_str(),\n\t\t\t\t\tn->c_str(),\n\t\t\t\t\tsbaw-1, unused_lsbs,\n\t\t\t\t\tsbaw-unused_lsbs,\n\t\t\t\t\t(sbaw-unused_lsbs+3)/4,\n\t\t\t\t\t(*m_slist)[i]->p_base >> (unused_lsbs+dalines));\n\t\t\t\t\twrite_addr_range(fp, (*m_slist)[i], dalines);\n\t\t\t\t\tfprintf(fp, \"\\n\");\n\t\t\t}\n\t\t}\n\t}\n\n\tif (m_dlist) {\n\t\tsbaw = m_dlist->get_address_width();\n\t\tmask = 0; unused_lsbs = 0;\n\t\tfor(unsigned i=0; i<m_dlist->size(); i++)\n\t\t\tmask |= (*m_dlist)[i]->p_mask;\n\t\tfor(unsigned tmp=mask; ((tmp)&&((tmp&1)==0)); tmp>>=1)\n\t\t\tunused_lsbs++;\n\t\tfor(unsigned i=0; i<m_dlist->size(); i++) {\n\t\t\tif ((*m_dlist)[i]->p_mask == 0) {\n\t\t\t\tfprintf(fp, \"\\tassign\\t%12s_sel = 1\\'b0; // ERR: (DIO) address mask == 0\\n\",\n\t\t\t\t\t(*m_dlist)[i]->p_name->c_str());\n\t\t\t} else {\n\t\t\t\tassert(sbaw > unused_lsbs);\n\t\t\t\tassert(sbaw > 0);\n\t\t\t\tfprintf(fp, \"\\tassign\\t%12s_sel \"\n\t\t\t\t\t\"= ((\" PREFIX \"%s_dio_sel)&&((%s[%2d:%2d] & %2d\\'h%lx) == %2d\\'h%0*lx)); \",\n\t\t\t\t(*m_dlist)[i]->p_name->c_str(),\n\t\t\t\tn->c_str(),\n\t\t\t\taddrbus.c_str(),\n\t\t\t\tsbaw-1,\n\t\t\t\tunused_lsbs,\n\t\t\t\tsbaw-unused_lsbs, (*m_dlist)[i]->p_mask >> unused_lsbs,\n\t\t\t\tsbaw-unused_lsbs,\n\t\t\t\t(sbaw-unused_lsbs+3)/4,\n\t\t\t\t(*m_dlist)[i]->p_base>>(dalines+unused_lsbs));\n\t\t\t\twrite_addr_range(fp, (*m_dlist)[i], dalines);\n\t\t\t\tfprintf(fp, \"\\n\");\n\t\t\t}\n\t\t}\n\t}\n\n\tsbaw = address_width();\n\tmask = 0; unused_lsbs = 0;\n\tfor(unsigned i=0; i< p->size(); i++)\n\t\tmask |= (*p)[i]->p_mask;\n\tfor(unsigned tmp=mask; ((tmp)&&((tmp&1)==0)); tmp>>=1)\n\t\tunused_lsbs++;\n\n\tif (m_info->m_plist->size() == 1) {\n\t\tif ((*m_info->m_plist)[0]->p_name)\n\t\t\tfprintf(fp, \"\\tassign\\t%12s_sel = (%s_cyc); \"\n\t\t\t\t\t\"// Only one peripheral on this bus\\n\",\n\t\t\t\t(*m_info->m_plist)[0]->p_name->c_str(),\n\t\t\t\tn->c_str());\n\t} else for(unsigned i=0; i< m_info->m_plist->size(); i++) {\n\t\tPERIPHP p = (*m_info->m_plist)[i];\n\t\tconst char *pn = p->p_name->c_str();\n\n\t\tif (pn) {\n\t\t\tif (p->p_mask == 0) {\n\t\t\t\tfprintf(fp, \"\\tassign\\t%12s_sel = 1\\'b0; // ERR: address mask == 0\\n\",\n\t\t\t\t\tpn);\n\t\t\t} else {\n\t\t\t\tassert(sbaw > unused_lsbs);\n\t\t\t\tassert(sbaw > 0);\n\t\t\t\tfprintf(fp, \"\\tassign\\t%12s_sel \"\n\t\t\t\t\t\"= ((%s[%2d:%2d] & %2d\\'h%lx) == %2d\\'h%0*lx);\",\n\t\t\t\t\tpn, addrbus.c_str(), sbaw-1,\n\t\t\t\t\tunused_lsbs,\n\t\t\t\t\tsbaw-unused_lsbs, p->p_mask >> unused_lsbs,\n\t\t\t\t\tsbaw-unused_lsbs,\n\t\t\t\t\t(sbaw-unused_lsbs+3)/4,\n\t\t\t\t\tp->p_base>>(dalines+unused_lsbs));\n\t\t\t\twrite_addr_range(fp, p, dalines);\n\t\t\t\tfprintf(fp, \"\\n\");\n\t\t\t}\n\t\t} if (p->p_master_bus) {\n\t\t\tfprintf(fp, \"//x2\\tWas a master bus as well\\n\");\n\t\t}\n\t} fprintf(fp, \"\\t//\\n\\n\");\n\t// }}}\n#endif\n}\n// }}}\n\nvoid\tWBBUS::writeout_no_slave_v(FILE *fp, STRINGP prefix) {\n\t// {{{\n\tSTRINGP\tn = m_info->name();\n\n\tfprintf(fp, \"\\n\\t//\\n\");\n\tfprintf(fp, \"\\t// In the case that there is no %s peripheral\\n\"\n\t\t\"\\t// responding on the %s bus\\n\",\n\t\t\tprefix->c_str(), n->c_str());\n\tfprintf(fp, \"\\tassign\\t%s_ack   = 1\\'b0;\\n\", prefix->c_str());\n\tfprintf(fp, \"\\tassign\\t%s_err   = (%s_stb);\\n\",\n\t\t\tprefix->c_str(), prefix->c_str());\n\tfprintf(fp, \"\\tassign\\t%s_stall = 0;\\n\", prefix->c_str());\n\tfprintf(fp, \"\\tassign\\t%s_idata = 0;\\n\", prefix->c_str());\n\tfprintf(fp, \"\\n\");\n}\n// }}}\n\nvoid\tWBBUS::writeout_no_master_v(FILE *fp) {\n\t// {{{\n/*\n\tif (!m_info || !m_info->m_name)\n\t\tgbl_msg.error(\"(Unnamed bus) has no name!\\n\");\n\n\t// PLIST\t*p = m_info->m_plist;\n\tSTRINGP\tp = m_info->bus_prefix();\n\n\tfprintf(fp, \"\\n\");\n\tfprintf(fp, \"\\t// In the case that nothing drives the %s bus ...\\n\", n->c_str());\n\tfprintf(fp, \"\\tassign\\t%s_cyc = 1\\'b0;\\n\", n->c_str());\n\tfprintf(fp, \"\\tassign\\t%s_stb = 1\\'b0;\\n\", n->c_str());\n\tfprintf(fp, \"\\tassign\\t%s_we  = 1\\'b0;\\n\", n->c_str());\n\tfprintf(fp, \"\\tassign\\t%s_sel = 0;\\n\", n->c_str());\n\tfprintf(fp, \"\\tassign\\t%s_addr= 0;\\n\", n->c_str());\n\tfprintf(fp, \"\\tassign\\t%s_data= 0;\\n\", n->c_str());\n\n\tfprintf(fp, \"\\t// verilator lint_off UNUSED\\n\");\n\tfprintf(fp, \"\\twire\\t[%d:0]\\tunused_bus_%s;\\n\",\n\t\t\t3+m_info->data_width(), n->c_str());\n\tfprintf(fp, \"\\tassign\\tunused_bus_%s = \"\n\t\t\"{ %s_ack, %s_stall, %s_err, %s_data };\\n\",\n\t\tn->c_str(), n->c_str(), n->c_str(),\n\t\tn->c_str(), n->c_str());\n\tfprintf(fp, \"\\t// verilator lint_on  UNUSED\\n\");\n\tfprintf(fp, \"\\n\");\n*/\n}\n// }}}\n\n//\n// Connect this master to the crossbar.  Specifically, we want to output\n// a list of master connections to fill the given port.\n//\nvoid\tWBBUS::xbarcon_master(FILE *fp, const char *tabs,\n\t\tconst char *pfx, const char *sig, bool comma) {\n\t// {{{\n\tfprintf(fp, \"%s%s({\\n\", tabs, pfx);\n\tfor(unsigned k = m_info->m_mlist->size()-1; k>0; k--) {\n\t\tBMASTERP m = (*m_info->m_mlist)[k];\n\t\tSTRINGP busp = m->bus_prefix();\n\t\tfprintf(fp, \"%s\\t%s_%s,\\n\", tabs, busp->c_str(), sig);\n\t} fprintf(fp, \"%s\\t%s_%s\\n%s})%s\\n\", tabs,\n\t\t\t (*m_info->m_mlist)[0]->bus_prefix()->c_str(),\n\t\t\tsig, tabs, (comma) ? \",\":\"\");\n}\n// }}}\n\n//\n// Output a list of connections to slave bus wires.  Used in connecting the\n// slaves to the various crossbar inputs.\n//\nvoid\tWBBUS::xbarcon_slave(FILE *fp, PLIST *pl, const char *tabs,\n\t\tconst char *pfx, const char *sig, bool comma) {\n\t// {{{\n\tfprintf(fp, \"%s%s({\\n\", tabs, pfx);\n\tfor(unsigned k = pl->size()-1; k>0; k--) {\n\t\tPERIPHP p = (*pl)[k];\n\t\tSTRINGP busp = p->bus_prefix();\n\t\tfprintf(fp, \"%s\\t%s_%s,\\n\", tabs, busp->c_str(), sig);\n\t} fprintf(fp, \"%s\\t%s_%s\\n%s})%s\\n\", tabs,\n\t\t(*pl)[0]->bus_prefix()->c_str(), sig,\n\t\ttabs, (comma) ? \",\":\"\");\n}\n// }}}\n\nvoid\tWBBUS::writeout_bus_logic_v(FILE *fp) {\n\t// {{{\n\tSTRINGP\t\tn = name(), rst;\n\tCLOCKINFO\t*c = m_info->m_clock;\n\tPLIST::iterator\tpp;\n\tPLISTP\t\tpl;\n\tunsigned\tunused_lsbs;\n\n\tif (NULL == m_info->m_plist)\n\t\treturn;\n\n\tif (NULL == m_info->m_mlist) {\n\t\tgbl_msg.warning(\"No masters assigned to bus %s\\n\",\n\t\t\t\tn->c_str());\n\t\t// return;\n\t}\n\tif (NULL == (rst = m_info->reset_wire())) {\n\t\tgbl_msg.warning(\"Bus %s has no associated reset wire, using \\'i_reset\\'\\n\", n->c_str());\n\t\trst = new STRING(\"i_reset\");\n\t\tsetstring(m_info->m_hash, KY_RESET, rst);\n\t\tREHASH;\n\t}\n\n\tif (NULL == c || NULL == c->m_wire) {\n\t\tgbl_msg.fatal(\"Bus %s has no associated clock\\n\", n->c_str());\n\t}\n\n\n\tif (m_info->m_plist->size() == 0) {\n\t\tfprintf(fp, \"\\t//\\n\"\n\t\t\t\"\\t// Bus %s has no slaves\\n\"\n\t\t\t\"\\t//\\n\\n\", n->c_str());\n\n\t\t// Since this bus has no slaves, any attempt to access it\n\t\t// needs to cause a bus error.\n\t\t//\n\t\t// Need to loop through all possible masters ...\n\t\tfor(MLIST::iterator pp=m_info->m_mlist->begin(); pp != m_info->m_mlist->end(); pp++) {\n\t\t\tSTRINGP\tpfx= (*pp)->bus_prefix();\n\t\t\tconst char *pfxc = pfx->c_str();\n\n\t\t\tfprintf(fp,\n\t\t\t\t\"\\t//\\n\"\n\t\t\t\t\"\\t// Master %s has no slaves attached to its bus, %s\\n\"\n\t\t\t\t\"\\t//\\n\"\n\t\t\t\t\"\\t\\tassign\\t%s_err   = %s_stb;\\n\"\n\t\t\t\t\"\\t\\tassign\\t%s_stall = 1\\'b0;\\n\"\n\t\t\t\t\"\\t\\tassign\\t%s_ack   = 1\\'b0;\\n\"\n\t\t\t\t\"\\t\\tassign\\t%s_idata = 0;\\n\",\n\t\t\t\tpfxc, m_info->name()->c_str(),\n\t\t\t\tpfxc, pfxc, pfxc, pfxc, pfxc);\n\t\t}\n\n\t\treturn;\n\t} else if (NULL == m_info->m_mlist || m_info->m_mlist->size() == 0) {\n\t\tfor(unsigned p=0; p < m_info->m_plist->size(); p++) {\n\t\t\tSTRINGP\tpstr = (*m_info->m_plist)[p]->bus_prefix();\n\t\t\tfprintf(fp,\n\t\t\"\\t//\\n\"\n\t\t\"\\t// The %s bus has no masters assigned to it\\n\"\n\t\t\"\\t//\\n\"\n\t\t\"\\tassign\t%s_cyc = 1\\'b0;\\n\"\n\t\t\"\\tassign\t%s_stb = 1\\'b0;\\n\"\n\t\t\"\\tassign\t%s_we  = 1\\'b0;\\n\"\n\t\t\"\\tassign\t%s_addr= 0;\\n\"\n\t\t\"\\tassign\t%s_data= 0;\\n\"\n\t\t\"\\tassign\t%s_sel = 0;\\n\\n\",\n\t\tpstr->c_str(),\n\t\t//\n\t\tpstr->c_str(), pstr->c_str(), pstr->c_str(),\n\t\tpstr->c_str(), pstr->c_str(), pstr->c_str());\n\t\t}\n\n\t\treturn;\n\t} else if ((m_info->m_plist->size() == 1)&&(m_info->m_mlist->size() == 1)) {\n\t\tMLIST::iterator\tmp = m_info->m_mlist->begin();\n\t\tPLIST::iterator\tpp = m_info->m_plist->begin();\n\t\tSTRINGP\tstrp;\n\t\t// Only one master connected to only one slave--skip all the\n\t\t// extra connection logic.\n\t\t//\n\t\t// Can only simplify if there's only one peripheral and only\n\t\t// one master\n\t\t//\n\t\tSTRINGP\tslv  = (*m_info->m_plist)[0]->bus_prefix();\n\t\tSTRINGP\tmstr = (*m_info->m_mlist)[0]->bus_prefix();\n\n\t\tfprintf(fp,\n\t\t\"//\\n\"\n\t\t\"// Bus %s has only one master (%s) and one slave (%s)\\n\"\n\t\t\"// connected to it -- skipping the interconnect\\n\"\n\t\t\"//\\n\", n->c_str(), mstr->c_str(), slv->c_str());\n\n\t\tfprintf(fp,\n\t\t\t\"\\tassign\\t%s_cyc  = %s_cyc;\\n\"\n\t\t\t\"\\tassign\\t%s_stb  = %s_stb;\\n\"\n\t\t\t\"\\tassign\\t%s_we   = %s_we;\\n\"\n\t\t\t\"\\tassign\\t%s_addr = %s_addr;\\n\"\n\t\t\t\"\\tassign\\t%s_data = %s_data;\\n\"\n\t\t\t\"\\tassign\\t%s_sel  = %s_sel;\\n\",\n\t\t\t(*pp)->bus_prefix()->c_str(),\n\t\t\t\t(*mp)->bus_prefix()->c_str(),\n\t\t\t(*pp)->bus_prefix()->c_str(),\n\t\t\t\t(*mp)->bus_prefix()->c_str(),\n\t\t\t(*pp)->bus_prefix()->c_str(),\n\t\t\t\t(*mp)->bus_prefix()->c_str(),\n\t\t\t(*pp)->bus_prefix()->c_str(),\n\t\t\t\t(*mp)->bus_prefix()->c_str(),\n\t\t\t(*pp)->bus_prefix()->c_str(),\n\t\t\t\t(*mp)->bus_prefix()->c_str(),\n\t\t\t(*pp)->bus_prefix()->c_str(),\n\t\t\t\t(*mp)->bus_prefix()->c_str());\n\n\t\tif (NULL != (strp = getstring((*m_info->m_plist)[0]->p_phash,\n\t\t\t\t\t\tKYERROR_WIRE))) {\n\t\t\tif (strp->compare(STRING(STRING(*(*pp)->bus_prefix())\n\t\t\t\t\t\t+ STRING(\"_err\"))) != 0)\n\t\t\t\tfprintf(fp, \"\\tassign\\t%s_err = %s; // X\\n\",\n\t\t\t\t\t(*pp)->bus_prefix()->c_str(),\n\t\t\t\t\tstrp->c_str());\n\t\t} else\n\t\t\tfprintf(fp, \"\\tassign\\t%s_err = 1\\'b0;\\n\",\n\t\t\t\t(*pp)->bus_prefix()->c_str());\n\t\tfprintf(fp, \"\\tassign\\t%s_err = %s_err; // Y\\n\",\n\t\t\t(*mp)->bus_prefix()->c_str(), (*pp)->bus_prefix()->c_str());\n\t\tfprintf(fp,\n\t\t\t\"\\tassign\\t%s_stall = %s_stall;\\n\"\n\t\t\t\"\\tassign\\t%s_ack   = %s_ack;\\n\"\n\t\t\t\"\\tassign\\t%s_idata = %s_idata;\\n\",\n\t\t\t(*mp)->bus_prefix()->c_str(),\n\t\t\t\t(*pp)->bus_prefix()->c_str(),\n\t\t\t(*mp)->bus_prefix()->c_str(),\n\t\t\t\t(*pp)->bus_prefix()->c_str(),\n\t\t\t(*mp)->bus_prefix()->c_str(),\n\t\t\t\t(*pp)->bus_prefix()->c_str());\n\t\treturn;\n\t}\n\n\t// Start with the slist\n\tif (m_slist) {\n\t\tSTRING\tsio_bus_prefix = STRING(*m_info->name()) + \"_sio\";\n\t\tSTRINGP\tslp = &sio_bus_prefix;\n\n\t\tfprintf(fp,\n\t\t\t\"\\t//\\n\"\n\t\t\t\"\\t// %s Bus logic to handle SINGLE slaves\\n\"\n\t\t\t\"\\t//\\n\", n->c_str());\n\n\t\tfprintf(fp, \"\\treg\\t\\t\" PREFIX \"r_%s_ack;\\n\", slp->c_str());\n\t\tfprintf(fp, \"\\treg\\t[%d:0]\\t\" PREFIX \"r_%s_data;\\n\\n\",\n\t\t\tm_info->data_width()-1, slp->c_str());\n\n\t\tfprintf(fp, \"\\tassign\\t\" PREFIX \"%s_stall = 1\\'b0;\\n\\n\", slp->c_str());\n\t\tfprintf(fp, \"\\tinitial \" PREFIX \"r_%s_ack = 1\\'b0;\\n\"\n\t\t\t\"\\talways\\t@(posedge %s)\\n\"\n\t\t\t\"\\t\\t\" PREFIX \"r_%s_ack <= (%s_stb);\\n\",\n\t\t\t\tslp->c_str(), c->m_wire->c_str(),\n\t\t\t\tslp->c_str(), slp->c_str());\n\t\tfprintf(fp, \"\\tassign\\t\" PREFIX \"%s_ack = \" PREFIX \"r_%s_ack;\\n\\n\",\n\t\t\t\tslp->c_str(), slp->c_str());\n\n\t\tunsigned mask = 0, lgdw;\n\t\tunused_lsbs = 0;\n\n\t\tfor(unsigned k=0; k<m_slist->size(); k++) {\n\t\t\tmask |= (*m_slist)[k]->p_mask;\n\t\t} for(unsigned tmp=mask; ((tmp!=0)&&((tmp & 1)==0)); tmp >>= 1)\n\t\t\tunused_lsbs++;\n\t\tlgdw = nextlg(m_info->data_width())-3;\n\n\t\tfprintf(fp, \"\\talways\\t@(posedge %s)\\n\", c->m_wire->c_str());\n\t\t\t// \"\\t\\t// mask        = %08x\\n\"\n\t\t\t// \"\\t\\t// lgdw        = %d\\n\"\n\t\t\t// \"\\t\\t// unused_lsbs = %d\\n\"\n\t\tfprintf(fp, \"\\tcasez( %s_addr[%d:%d] )\\n\",\n\t\t\t\t// mask, lgdw, unused_lsbs,\n\t\t\t\tslp->c_str(),\n\t\t\t\tnextlg(mask)-1, unused_lsbs);\n\t\tfor(unsigned j=0; j<m_slist->size(); j++) {\n\t\t\tfprintf(fp, \"\\t%d'h%lx: \" PREFIX \"r_%s_data <= %s_idata;\\n\",\n\t\t\t\tnextlg(mask)-unused_lsbs,\n\t\t\t\t((*m_slist)[j]->p_base) >> (unused_lsbs + lgdw),\n\t\t\t\tslp->c_str(),\n\t\t\t\t(*m_slist)[j]->bus_prefix()->c_str());\n\t\t}\n\n\t\tif (m_slist->size() != (1u<<nextlg(m_slist->size()))) {\n\t\t\t// We need a default option\n\t\tif (bus_option(KY_OPT_LOWPOWER)) {\n\t\t\tint\tv;\n\t\t\tSTRINGP str;\n\t\t\tif (getvalue(*m_info->m_hash, KY_OPT_LOWPOWER, v))\n\t\t\t\tfprintf(fp,\n\t\t\t\t\"\\tdefault: \" PREFIX\n\t\t\t\t\t\"r_%s_data <= (%d) ? 0 : %s_idata;\\n\",\n\t\t\t\tslp->c_str(), v,\n\t\t\t\t(*m_slist)[m_slist->size()-1]->bus_prefix()->c_str());\n\t\t\telse {\n\t\t\t\tstr = getstring(*m_info->m_hash, KY_OPT_LOWPOWER);\n\t\t\t\tfprintf(fp, \"\\tdefault: \" PREFIX \"r_%s_data <= (%s) ? 0 : %s_idata;\\n\",\n\t\t\t\tslp->c_str(), (str) ? str->c_str() : \"1\\'b0\",\n\t\t\t\t(*m_slist)[m_slist->size()-1]->bus_prefix()->c_str());\n\t\t\t}\n\n\t\t} else {\n\t\t\tfprintf(fp, \"\\tdefault: \" PREFIX \"r_%s_data <= %s_idata;\\n\",\n\t\t\t\tslp->c_str(),\n\t\t\t\t(*m_slist)[m_slist->size()-1]->bus_prefix()->c_str());\n\t\t}} else {\n\t\t\tfprintf(fp, \"\\t// No default: SIZE = %d, [Guru meditation: %d != %d]\\n\",\n\t\t\t\t(int)m_slist->size(),\n\t\t\t\t(int)nextlg(m_slist->size()-1),\n\t\t\t\t(int)nextlg(m_slist->size()));\n\t\t}\n\t\tfprintf(fp, \"\\tendcase\\n\");\n\t\tfprintf(fp, \"\\tassign\\t\" PREFIX \"%s_idata = \" PREFIX \"r_%s_data;\\n\\n\",\n\t\t\tslp->c_str(), slp->c_str());\n\n\t\tfprintf(fp, \"\\n\\t//\\n\"\n\t\t\t\"\\t// Now to translate this logic to the various SIO slaves\\n\\t//\\n\"\n\t\t\t\"\\t// In this case, the SIO bus has the prefix %s\\n\"\n\t\t\t\"\\t// and all of the slaves have various wires beginning\\n\"\n\t\t\t\"\\t// with their own respective bus prefixes.\\n\"\n\t\t\t\"\\t// Our goal here is to make certain that all of\\n\"\n\t\t\t\"\\t// the slave bus inputs match the SIO bus wires\\n\",\n\t\t\tslp->c_str());\n\n\t\tunsigned\tsbaw;\n\t\tunsigned\tdw   = m_info->data_width();\n\t\tunsigned\tdalines = nextlg(dw/8);\n\t\tmask = 0;\n\n\t\tsbaw = m_slist->get_address_width();\n\t\tfor(unsigned j=0; j<m_slist->size(); j++) {\n\t\t\tconst char *pn = (*m_slist)[j]->bus_prefix()->c_str();\n\n\t\t\tfprintf(fp, \"\\tassign\\t%s_cyc = %s_cyc;\\n\",\n\t\t\t\tpn, slp->c_str());\n\n\t\t\tif ((*m_slist)[j]->p_mask == 0) {\n\t\t\t\tfprintf(fp, \"\\tassign\\t%s_stb = 1\\'b0; // ERR: (SIO) address mask == 0\\n\",\n\t\t\t\t\tpn);\n\t\t\t} else {\n\t\t\t\tassert(sbaw > unused_lsbs);\n\t\t\t\tassert(sbaw > 0);\n\t\t\t\tfprintf(fp, \"\\tassign\\t%s_stb = %s_stb \"\n\t\t\t\t\t\"&& (%s_addr[%2d:%2d] == %2d\\'h%0*lx); \",\n\t\t\t\t\tpn, slp->c_str(), slp->c_str(),\n\t\t\t\t\tsbaw-1, unused_lsbs,\n\t\t\t\t\tsbaw-unused_lsbs,\n\t\t\t\t\t(sbaw-unused_lsbs+3)/4,\n\t\t\t\t\t(*m_slist)[j]->p_base >> (unused_lsbs+dalines));\n\t\t\t\twrite_addr_range(fp, (*m_slist)[j], dalines);\n\t\t\t\tfprintf(fp, \"\\n\");\n\t\t\t}\n\t\t\tfprintf(fp,\n\t\t\t\"\\tassign\\t%s_we  = %s_we;\\n\"\n\t\t\t\"\\tassign\\t%s_data= %s_data;\\n\"\n\t\t\t\"\\tassign\\t%s_sel = %s_sel;\\n\",\n\t\t\t\tpn, slp->c_str(),\n\t\t\t\tpn, slp->c_str(),\n\t\t\t\tpn, slp->c_str());\n\t\t}\n\t} else\n\t\tfprintf(fp, \"\\t//\\n\\t// No class SINGLE peripherals on the \\\"%s\\\" bus\\n\\t//\\n\\n\", n->c_str());\n\n\t// Then the dlist\n\tif (m_dlist) {\n\t\tSTRING\tdio_bus_prefix = STRING(*m_info->name()) + \"_dio\";\n\t\tSTRINGP\tdlp = &dio_bus_prefix;\n\n\t\tfprintf(fp,\n\t\t\t\"\\t//\\n\"\n\t\t\t\"\\t// %s Bus logic to handle %ld DOUBLE slaves\\n\"\n\t\t\t\"\\t//\\n\"\n\t\t\t\"\\t//\\n\", n->c_str(), m_dlist->size());\n\n\t\tunsigned mask = 0, lgdw, maskbits;\n\t\tunused_lsbs = 0;\n\t\tfor(unsigned k=0; k<m_dlist->size(); k++) {\n\t\t\tmask |= (*m_dlist)[k]->p_mask;\n\t\t} for(unsigned tmp=mask; ((tmp!=0)&&((tmp & 1)==0)); tmp >>= 1)\n\t\t\tunused_lsbs++;\n\t\tmaskbits = nextlg(mask)-unused_lsbs;\n\t\tif (maskbits < 1)\n\t\t\tmaskbits=1;\n\t\t// lgdw is the log of the data width in bytes.  We require it\n\t\t// here because the bus addresses words rather than the bytes\n\t\t// within them\n\t\tlgdw = nextlg(m_info->data_width())-3;\n\n\n\t\tfprintf(fp, \"\\treg\\t[1:0]\\t\" PREFIX \"r_%s_ack;\\n\",\n\t\t\t\tdlp->c_str());\n\t\tfprintf(fp, \"\\t// # dlist = %d, nextlg(#dlist) = %d\\n\",\n\t\t\t(int)m_dlist->size(),\n\t\t\tnextlg(m_dlist->size()));\n\t\tfprintf(fp, \"\\treg\\t[%d:0]\\t\" PREFIX \"r_%s_bus_select;\\n\",\n\t\t\tnextlg((int)m_dlist->size())-1, dlp->c_str());\n\t\tfprintf(fp, \"\\treg\\t[%d:0]\\t\" PREFIX \"r_%s_data;\\n\",\n\t\t\tm_info->data_width()-1, dlp->c_str());\n\t\tfprintf(fp, \"\\n\");\n\n\t\t//\n\t\t// The stall line\n\t\tfprintf(fp, \"\\t// DOUBLE peripherals are not allowed to stall.\\n\"\n\t\t\t\"\\tassign\\t\" PREFIX \"%s_stall = 1\\'b0;\\n\\n\",\n\t\t\tdlp->c_str());\n\t\t//\n\t\t// The ACK line\n\t\tfprintf(fp,\n\t\t\"\\t// DOUBLE peripherals return their acknowledgments in two\\n\"\n\t\t\"\\t// clocks--always, allowing us to collect this logic together\\n\"\n\t\t\"\\t// in a slave independent manner.  Here, the acknowledgment\\n\"\n\t\t\"\\t// is treated as a two stage shift register, cleared on any\\n\"\n\t\t\"\\t// reset, or any time the cycle line drops.  (Dropping the\\n\"\n\t\t\"\\t// cycle line aborts the transaction.)\\n\"\n\t\t\"\\tinitial\\t\" PREFIX \"r_%s_ack = 0;\\n\"\n\t\t\"\\talways\\t@(posedge %s)\\n\"\n\t\t\t\"\\tif (%s || !%s_cyc)\\n\",\n\t\t\t\tdlp->c_str(), c->m_wire->c_str(),\n\t\t\t\trst->c_str(), dlp->c_str());\n\t\tfprintf(fp,\n\t\t\t\"\\t\\t\" PREFIX \"r_%s_ack <= 0;\\n\"\n\t\t\t\"\\telse\\n\"\n\t\t\t\"\\t\\t\" PREFIX \"r_%s_ack <= { \" PREFIX \"r_%s_ack[0], (%s_stb) };\\n\",\n\t\t\t\tdlp->c_str(), dlp->c_str(),\n\t\t\t\tdlp->c_str(), dlp->c_str());\n\t\tfprintf(fp, \"\\tassign\\t\" PREFIX \"%s_ack = \"\n\t\t\tPREFIX \"r_%s_ack[1];\\n\",\n\t\t\tdlp->c_str(), dlp->c_str());\n\t\tfprintf(fp, \"\\n\");\n\n\t\t//\n\t\t// The data return lines\n\t\t//\n\t\tfprintf(fp,\n\t\t\t\"\\t// Since it costs us two clocks to go through this\\n\"\n\t\t\t\"\\t// logic, we'll take one of those clocks here to set\\n\"\n\t\t\t\"\\t// a selection index, and then on the next clock we'll\\n\"\n\t\t\t\"\\t// use this index to select from among the vaious\\n\"\n\t\t\t\"\\t// possible bus return values\\n\"\n\t\t\t\"\\talways @(posedge %s)\\n\"\n\t\t\t\"\\tcasez(%s_addr[%d:%d])\\n\",\n\t\t\t\tc->m_wire->c_str(),\n\t\t\t\tdlp->c_str(),\n\t\t\t\tmaskbits+unused_lsbs-1, unused_lsbs);\n\t\tfor(unsigned k=0; k<m_dlist->size(); k++) {\n\t\t\tfprintf(fp, \"\\t%d'b\", maskbits);\n\t\t\tfor(unsigned b=0; b<maskbits; b++) {\n\t\t\t\tunsigned\tshift = maskbits + unused_lsbs-b-1;\n\t\t\t\tif (((*m_dlist)[k]->p_mask & (1<<shift))==0)\n\t\t\t\t\tfprintf(fp, \"?\");\n\t\t\t\telse if ((*m_dlist)[k]->p_base & (1<<(shift+lgdw)))\n\t\t\t\t\tfprintf(fp, \"1\");\n\t\t\t\telse\n\t\t\t\t\tfprintf(fp, \"0\");\n\n\t\t\t\tif ((shift > lgdw)&&(((shift-lgdw)&3)==0)\n\t\t\t\t\t&&(b<maskbits-1))\n\t\t\t\t\tfprintf(fp, \"_\");\n\t\t\t}\n\t\t\tfprintf(fp, \": \" PREFIX \"r_%s_bus_select <= %d\\'d%d;\\n\",\n\t\t\t\tdlp->c_str(), nextlg(m_dlist->size()), k);\n\t\t}\n\t\tfprintf(fp, \"\\tdefault: \" PREFIX \"r_%s_bus_select <= 0;\\n\",\n\t\t\tdlp->c_str());\n\t\tfprintf(fp, \"\\tendcase\\n\\n\");\n\n\t\tfprintf(fp, \"\\talways\\t@(posedge %s)\\n\"\n\t\t\t\"\\tcasez(\" PREFIX \"r_%s_bus_select)\\n\",\n\t\t\tc->m_wire->c_str(), dlp->c_str());\n\n\t\tfor(unsigned k=0; k<m_dlist->size(); k++) {\n\t\t\tfprintf(fp, \"\\t%d'd%d\", nextlg(m_dlist->size()), k);\n\t\t\tfprintf(fp, \": \" PREFIX \"r_%s_data <= %s_idata;\\n\",\n\t\t\t\tdlp->c_str(),\n\t\t\t\t(*m_dlist)[k]->bus_prefix()->c_str());\n\t\t}\n\n\t\tif ((1u<<nextlg(m_dlist->size())) != m_dlist->size()) {\n\t\t\t// Only place the default value into the case if there\n\t\t\t// are empty values there.\n\t\t\tif (bus_option(KY_OPT_LOWPOWER)) {\n\t\t\t\tfprintf(fp, \"\\tdefault: \"\n\t\t\t\t\tPREFIX \"r_%s_data <= 0;\\n\", dlp->c_str());\n\t\t\t} else\n\t\t\tfprintf(fp, \"\\tdefault: \"\n\t\t\t\tPREFIX \"r_%s_data <= %s_idata;\\n\", dlp->c_str(),\n\t\t\t(*m_dlist)[m_dlist->size()-1]->bus_prefix()->c_str());\n\t\t}\n\t\tfprintf(fp, \"\\tendcase\\n\\n\");\n\t\tfprintf(fp, \"\\tassign\\t\" PREFIX \"%s_idata = \" PREFIX \"r_%s_data;\\n\\n\",\n\t\t\tdlp->c_str(), dlp->c_str());\n\n\t\t//\n\t\t// Connect the dio bus wires together to send to the various\n\t\t// slave buses the dio bus drives\n\t\t//\n\t\tunsigned\tsbaw;\n\t\tunsigned\tdw   = m_info->data_width();\n\t\tunsigned\tdalines = nextlg(dw/8);\n\t\tmask = 0;\n\n\t\tsbaw = m_dlist->get_address_width();\n\t\tfor(unsigned j=0; j<m_dlist->size(); j++) {\n\t\t\tconst char *pn = (*m_dlist)[j]->bus_prefix()->c_str();\n\n\t\t\tfprintf(fp, \"\\tassign\\t%s_cyc = %s_cyc;\\n\",\n\t\t\t\tpn, dlp->c_str());\n\n\t\t\tif ((*m_dlist)[j]->p_mask == 0) {\n\t\t\t\tfprintf(fp, \"\\tassign\\t%s_stb = 1\\'b0; // ERR: (DIO) address mask == 0\\n\",\n\t\t\t\t\tpn);\n\t\t\t} else {\n\t\t\t\tassert(sbaw > unused_lsbs);\n\t\t\t\tassert(sbaw > 0);\n\t\t\t\tfprintf(fp, \"\\tassign\\t%s_stb = %s_stb \"\n\t\t\t\t\t\"&& ((%s_addr[%2d:%2d] & %2d\\'h%0*lx) == %2d\\'h%0*lx); \",\n\t\t\t\t\tpn, dlp->c_str(), dlp->c_str(),\n\t\t\t\t\t// Relevant address bits\n\t\t\t\t\tsbaw-1, unused_lsbs,\n\t\t\t\t\t//\n\t\t\t\t\t// Mask bits\n\t\t\t\t\tsbaw-unused_lsbs,\n\t\t\t\t\t(sbaw-unused_lsbs+3)/4,\n\t\t\t\t\t(*m_dlist)[j]->p_mask >> unused_lsbs,\n\t\t\t\t\t//\n\t\t\t\t\tsbaw-unused_lsbs,\n\t\t\t\t\t(sbaw-unused_lsbs+3)/4,\n\t\t\t\t\t(*m_dlist)[j]->p_base >> (unused_lsbs+dalines));\n\t\t\t\twrite_addr_range(fp, (*m_dlist)[j], dalines);\n\t\t\t\tfprintf(fp, \"\\n\");\n\t\t\t}\n\t\t\tfprintf(fp,\n\t\t\t\"\\tassign\\t%s_we  = %s_we;\\n\"\n\t\t\t\"\\tassign\\t%s_addr= %s_addr;\\n\"\n\t\t\t\"\\tassign\\t%s_data= %s_data;\\n\"\n\t\t\t\"\\tassign\\t%s_sel = %s_sel;\\n\",\n\t\t\t\tpn, dlp->c_str(),\n\t\t\t\tpn, dlp->c_str(),\n\t\t\t\tpn, dlp->c_str(),\n\t\t\t\tpn, dlp->c_str());\n\t\t}\n\t} else\n\t\tfprintf(fp, \"\\t//\\n\\t// No class DOUBLE peripherals on the \\\"%s\\\" bus\\n\\t//\\n\\n\", n->c_str());\n\n\t//\n\t//\n\t// Now for the main set of slaves\n\t//\n\t//\n\n\tunsigned\tslave_name_width = 4;\n\t// Find the maximum width of any slaves name, for our comment tables\n\t// below\n\tfor(unsigned k=0; k<m_info->m_plist->size(); k++) {\n\t\tPERIPHP\tp = (*m_info->m_plist)[k];\n\t\tunsigned\tsz;\n\n\t\tsz = p->name()->size();\n\t\tif (slave_name_width < sz)\n\t\t\tslave_name_width = sz;\n\t}\n\n\t//\n\t// First make certain any slaves that cannot produce error wires\n\t// can define\n\t//\n\tfor(unsigned k=0; k<m_info->m_plist->size(); k++) {\n\t\tPERIPHP\tp = (*m_info->m_plist)[k];\n\t\tconst char *pn = (*m_info->m_plist)[k]->bus_prefix()->c_str();\n\t\tSTRINGP\terr;\n\n\t\tif (NULL != (err = getstring(p->p_phash, KYERROR_WIRE))) {\n\t\t\tSTRING buserr = STRING(pn) + STRING(\"_err\");\n\t\t\tif (buserr.compare(*err) == 0) {\n\t\t\t\tfprintf(fp, \"\\t// info: @ERROR.WIRE for %s \"\n\t\t\t\t\t\"matches the buses error name, \"\n\t\t\t\t\t\"%s_err\\n\",\n\t\t\t\t\tp->name()->c_str(), pn);\n\t\t\t} else {\n\t\t\t\tfprintf(fp, \"\\t// info: @ERROR.WIRE %s != %s\\n\",\n\t\t\t\t\terr->c_str(), pn);\n\t\t\t\tfprintf(fp, \"\\t// info: @ERROR.WIRE for %s, = %s, doesn\\'t match the buses wire %s_err\\n\",\n\t\t\t\t\tp->name()->c_str(), err->c_str(),\n\t\t\t\t\tpn);\n\t\t\t\tfprintf(fp, \"\\tassign\\t%s_err = %s; // Z\\n\",\n\t\t\t\t\tpn, err->c_str());\n\t\t\t}\n\t\t} else\n\t\t\tfprintf(fp, \"\\tassign\\t%s_err= 1\\'b0;\\n\", pn);\n\t}\n\n\t//\n\t// Now create the crossbar interconnect\n\t//\n\tfprintf(fp,\n\t\"\\t//\\n\"\n\t\"\\t// Connect the %s bus components together using the wbxbar()\\n\"\n\t\"\\t//\\n\"\n\t\"\\t//\\n\", n->c_str());\n\n\tunused_lsbs = nextlg(m_info->data_width())-3;\n\tfprintf(fp,\n\t\"\\twbxbar #(\\n\"\n\t\t\"\\t\\t.NM(%ld), .NS(%ld), .AW(%d), .DW(%d),\\n\",\n\t\tm_info->m_mlist->size(), m_info->m_plist->size(),\n\t\taddress_width(), m_info->data_width());\n\n\tslave_addr(fp, m_info->m_plist, unused_lsbs); fprintf(fp, \",\\n\");\n\tslave_mask(fp, m_info->m_plist, unused_lsbs);\n\n\txbar_option(fp, KY_OPT_LOWPOWER,   \",\\n\\t\\t.OPT_LOWPOWER(%)\");\n\txbar_option(fp, KY_OPT_LGMAXBURST, \",\\n\\t\\t.LGNMAXBURST(%)\");\n\txbar_option(fp, KY_OPT_TIMEOUT,    \",\\n\\t\\t.OPT_TIMEOUT(%)\");\n\txbar_option(fp, KY_OPT_DBLBUFFER,  \",\\n\\t\\t.OPT_DBLBUFFER(%)\", \"1\\'b1\");\n\t// OPT_STARVATION_TIMEOUT?\n\n\tfprintf(fp,\n\t\")\\n\\t%s_xbar(\\n\"\n\t\"\\t\\t.i_clk(%s), .i_reset(%s),\\n\",\n\t\tn->c_str(), c->m_wire->c_str(), rst->c_str());\n\txbarcon_master(fp, \"\\t\\t\", \".i_mcyc\",  \"cyc\");\n\txbarcon_master(fp, \"\\t\\t\", \".i_mstb\",  \"stb\");\n\txbarcon_master(fp, \"\\t\\t\", \".i_mwe\",   \"we\");\n\txbarcon_master(fp, \"\\t\\t\", \".i_maddr\", \"addr\");\n\txbarcon_master(fp, \"\\t\\t\", \".i_mdata\", \"data\");\n\txbarcon_master(fp, \"\\t\\t\", \".i_msel\",  \"sel\");\n\txbarcon_master(fp, \"\\t\\t\", \".o_mstall\",\"stall\");\n\txbarcon_master(fp, \"\\t\\t\", \".o_mack\",  \"ack\");\n\txbarcon_master(fp, \"\\t\\t\", \".o_mdata\", \"idata\");\n\txbarcon_master(fp, \"\\t\\t\", \".o_merr\",  \"err\");\n\tfprintf(fp, \"\\t\\t// Slave connections\\n\");\n\tpl = m_info->m_plist;\n\txbarcon_slave(fp, pl, \"\\t\\t\", \".o_scyc\",  \"cyc\");\n\txbarcon_slave(fp, pl, \"\\t\\t\", \".o_sstb\",  \"stb\");\n\txbarcon_slave(fp, pl, \"\\t\\t\", \".o_swe\",   \"we\");\n\txbarcon_slave(fp, pl, \"\\t\\t\", \".o_saddr\", \"addr\");\n\txbarcon_slave(fp, pl, \"\\t\\t\", \".o_sdata\", \"data\");\n\txbarcon_slave(fp, pl, \"\\t\\t\", \".o_ssel\",  \"sel\");\n\txbarcon_slave(fp, pl, \"\\t\\t\", \".i_sstall\",\"stall\");\n\txbarcon_slave(fp, pl, \"\\t\\t\", \".i_sack\",  \"ack\");\n\txbarcon_slave(fp, pl, \"\\t\\t\", \".i_sdata\", \"idata\");\n\txbarcon_slave(fp, pl, \"\\t\\t\", \".i_serr\",  \"err\",  false);\n\tfprintf(fp, \"\\t\\t);\\n\\n\");\n\n}\n// }}}\n\nSTRINGP\tWBBUS::master_portlist(BMASTERP) {\n\t// {{{\n\treturn new STRING(\n\t\"@$(MASTER.PREFIX)_cyc, \"\n\t\"@$(MASTER.PREFIX)_stb, \"\n\t\"@$(MASTER.PREFIX)_we,\\n\"\n\t\"\\t\\t\\t@$(MASTER.PREFIX)_addr[@$(MASTER.BUS.AWID)-1:0],\\n\"\n\t\"\\t\\t\\t@$(MASTER.PREFIX)_data, // @$(MASTER.BUS.WIDTH) bits wide\\n\"\n\t\"\\t\\t\\t@$(MASTER.PREFIX)_sel,  // @$(MASTER.BUS.WIDTH)/8 bits wide\\n\"\n\t\"\\t\\t@$(MASTER.PREFIX)_stall, \"\n\t\"@$(MASTER.PREFIX)_ack, \"\n\t\"@$(MASTER.PREFIX)_idata,\"\n\t\"@$(MASTER.PREFIX)_err\");\n}\n// }}}\n\nSTRINGP\tWBBUS::iansi(BMASTERP) {\n\treturn new STRING(\"i_\");\n}\n\nSTRINGP\tWBBUS::oansi(BMASTERP) {\n\treturn new STRING(\"o_\");\n}\n\nSTRINGP\tWBBUS::master_ansprefix(BMASTERP) {\n\treturn new STRING(\"wb_\");\n}\n\nSTRINGP\tWBBUS::master_ansi_portlist(BMASTERP) {\n\t// {{{\n\treturn new STRING(\n\t\".@$(OANSI)@$(MASTER.ANSPREFIX)cyc(@$(MASTER.PREFIX)_cyc), \"\n\t\".@$(OANSI)@$(MASTER.ANSPREFIX)stb(@$(MASTER.PREFIX)_stb), \"\n\t\".@$(OANSI)@$(MASTER.ANSPREFIX)we(@$(MASTER.PREFIX)_we),\\n\"\n\t\"\\t\\t\\t.@$(OANSI)@$(MASTER.ANSPREFIX)addr(@$(MASTER.PREFIX)_addr[@$(MASTER.BUS.AWID)-1:0]),\\n\"\n\t\"\\t\\t\\t.@$(OANSI)@$(MASTER.ANSPREFIX)data(@$(MASTER.PREFIX)_data), // @$(MASTER.BUS.WIDTH) bits wide\\n\"\n\t\"\\t\\t\\t.@$(OANSI)@$(MASTER.ANSPREFIX)sel(@$(MASTER.PREFIX)_sel),  // @$(MASTER.BUS.WIDTH)/8 bits wide\\n\"\n\t\"\\t\\t.@$(IANSI)@$(MASTER.ANSPREFIX)stall(@$(MASTER.PREFIX)_stall), \"\n\t\".@$(IANSI)@$(MASTER.ANSPREFIX)ack(@$(MASTER.PREFIX)_ack), \"\n\t\".@$(IANSI)@$(MASTER.ANSPREFIX)data(@$(MASTER.PREFIX)_idata), \"\n\t\".@$(IANSI)@$(MASTER.ANSPREFIX)err(@$(MASTER.PREFIX)_err)\");\n}\n// }}}\n\nSTRINGP\tWBBUS::slave_ansprefix(PERIPHP p) {\n\treturn new STRING(\"wb_\");\n}\n\n\nSTRINGP\tWBBUS::slave_portlist(PERIPHP p) {\n\t// {{{\n\tSTRINGP\terrp = getstring(p->p_phash, KYERROR_WIRE);\n\tSTRING\tstr = STRING(\n\t\"@$(SLAVE.PREFIX)_cyc, \"\n\t\"@$(SLAVE.PREFIX)_stb,\");\n\n\tif (!p->read_only() && !p->write_only())\n\t\tstr = str + STRING(\" @$(SLAVE.PREFIX)_we,\");\n\tstr = str + STRING(\"\\n\");\n\tif (p->get_slave_address_width() > 0) {\n\t\tchar\ttmp[64];\n\t\tSTRING\tstmp;\n\t\tsprintf(tmp, \"_addr[%d-1:0],\\n\", p->get_slave_address_width());\n\t\tstmp = STRING(\"\\t\\t\\t@$(SLAVE.PREFIX)\") + STRING(tmp);\n\t\tstr = str + stmp;\n\t}\n\tif (!p->read_only())\n\t\tstr = str + STRING(\n\t\t\"\\t\\t\\t@$(SLAVE.PREFIX)_data, // @$(SLAVE.BUS.WIDTH) bits wide\\n\"\n\t\t\"\\t\\t\\t@$(SLAVE.PREFIX)_sel,  // @$(SLAVE.BUS.WIDTH)/8 bits wide\\n\");\n\tstr = str + STRING(\n\t\t\"\\t\\t@$(SLAVE.PREFIX)_stall, @$(SLAVE.PREFIX)_ack\");\n\tif (!p->write_only())\n\t\tstr = str + STRING(\", @$(SLAVE.PREFIX)_idata\");\n\tif (NULL != errp)\n\t\tstr = str + STRING(\", @$(SLAVE.PREFIX)_err\");\n\n\treturn new STRING(str);\n}\n// }}}\n\nSTRINGP\tWBBUS::slave_ansi_portlist(PERIPHP p) {\n\t// {{{\n\tSTRINGP\terrp = getstring(p->p_phash, KYERROR_WIRE);\n\tSTRING\tstr = STRING(\n\n\t\".@$(IANSI)@$(SLAVE.ANSPREFIX)cyc(@$(SLAVE.PREFIX)_cyc), \"\n\t\".@$(IANSI)@$(SLAVE.ANSPREFIX)stb(@$(SLAVE.PREFIX)_stb), \");\n\tif (!p->read_only() && !p->write_only())\n\t\tstr = str + STRING(\".@$(IANSI)@$(SLAVE.ANSPREFIX)we(@$(SLAVE.PREFIX)_we),\\n\");\n\tif (p->get_slave_address_width() > 0) {\n\t\tchar\ttmp[64];\n\t\tSTRING\tstmp;\n\t\tsprintf(tmp, \"_addr[%d-1:0]),\\n\", p->get_slave_address_width());\n\t\tstmp = STRING(\"\\t\\t\\t.@$(IANSI)@$(SLAVE.ANSPREFIX)addr(@$(SLAVE.PREFIX)\") + STRING(tmp);\n\t\tstr = str + stmp;\n\t}\n\tif (!p->read_only())\n\t\tstr = str + STRING(\n\t\"\\t\\t\\t.@$(IANSI)@$(SLAVE.ANSPREFIX)data(@$(SLAVE.PREFIX)_data), // @$(SLAVE.BUS.WIDTH) bits wide\\n\"\n\t\"\\t\\t\\t.@$(IANSI)@$(SLAVE.ANSPREFIX)sel(@$(SLAVE.PREFIX)_sel),  // @$(SLAVE.BUS.WIDTH)/8 bits wide\\n\");\n\tstr = str + STRING(\n\t\"\\t\\t.@$(OANSI)@$(SLAVE.ANSPREFIX)stall(@$(SLAVE.PREFIX)_stall),\"\n\t\".@$(OANSI)@$(SLAVE.ANSPREFIX)ack(@$(SLAVE.PREFIX)_ack)\");\n\n\tif (!p->write_only())\n\t\tstr = str + STRING(\", .@$(OANSI)@$(SLAVE.ANSPREFIX)data(@$(SLAVE.PREFIX)_idata)\");\n\tif (NULL != errp)\n\t\tstr = str + STRING(\", .@$(OANSI)@$(SLAVE.ANSPREFIX)err(@$(SLAVE.PREFIX)_err)\");\n\treturn new STRING(str);\n}\n// }}}\n\n////////////////////////////////////////////////////////////////////////\n//\n// Bus class logic\n//\n// The bus class describes the logic above in a way that it can be\n// chosen, selected, and enacted within a design.  Hence if a design\n// has four wishbone buses and one AXI-lite bus, the bus class logic\n// will recognize the four WB buses and generate WB bus generators,\n// and then an AXI-lite bus and bus generator, etc.\n//\n////////////////////////////////////////////////////////////////////////\nSTRINGP\tWBBUSCLASS::name(void) {\n\treturn new STRING(\"wb\");\n}\n\nSTRINGP\tWBBUSCLASS::longname(void) {\n\treturn new STRING(\"Wishbone\");\n}\n\nbool\tWBBUSCLASS::matchtype(STRINGP str) {\n\tif (!str)\n\t\t// Wishbone is the default type\n\t\treturn true;\n\tif (str->compare(\"wb\")==0)\n\t\treturn true;\n\tif (str->compare(\"wbp\")==0)\n\t\treturn true;\n// printf(\"ERR: No match for bus type %s\\n\",str->c_str());\n\treturn false;\n}\n\nbool\tWBBUSCLASS::matchfail(MAPDHASH *bhash) {\n\treturn false;\n}\n\nGENBUS *WBBUSCLASS::create(BUSINFO *bi) {\n\tWBBUS\t*busclass;\n\n\tbusclass = new WBBUS(bi);\n\treturn busclass;\n}\n"
  },
  {
    "path": "sw/bus/wb.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/bus/wb.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\t\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tWB_H\n#define\tWB_H\n\n#include \"../genbus.h\"\n\nclass\tWBBUS : public GENBUS {\n\tPLIST\t*m_slist, *m_dlist;\n\tunsigned\tm_num_total, m_num_double, m_num_single;\n\tbool\t\tm_is_single, m_is_double;\n\n\tvoid\txbarcon_master(FILE *fp, const char *,\n\t\t\t\tconst char *, const char *, bool comma = true);\n\tvoid\txbarcon_slave(FILE *fp, PLIST *pl, const char *,\n\t\t\t\tconst char *, const char *, bool comma = true);\n\tvoid\tallocate_subbus(void);\n\n\tBUSINFO *create_sio(void);\n\tBUSINFO *create_dio(void);\n\tvoid\tcountsio(void);\npublic:\n\tWBBUS(BUSINFO *bi);\n\t~WBBUS() {};\n\tvirtual\tint\taddress_width(void);\n\t//\n\tvirtual\tvoid\tassign_addresses(void);\n\tvirtual\tbool\tword_addressing(void) { return true; };\n\tvirtual\tbool\tget_base_address(MAPDHASH *phash, unsigned &base);\n\n\tvoid\t\twrite_addr_range(FILE *fp, const PERIPHP p,\n\t\t\t\tconst int dalines);\n\tvirtual\tvoid\twriteout_defn_v(FILE *fp, const char *pname,\n\t\t\t\tconst char *pfx, const int aw, const int dw,\n\t\t\t\tconst char *ewire, const char *btyp = \"\");\n\tvirtual\tvoid\twriteout_bus_slave_defns_v(FILE *fp);\n\tvirtual\tvoid\twriteout_bus_master_defns_v(FILE *fp);\n\n\tvirtual\tvoid\twriteout_bus_select_v(FILE *fp);\n\tvirtual\tvoid\twriteout_bus_logic_v(FILE *fp);\n\n\tvirtual\tvoid\twriteout_no_slave_v(FILE *fp, STRINGP prefix);\n\tvirtual\tvoid\twriteout_no_master_v(FILE *fp);\n\t//\n\t//\n\tvirtual\tSTRINGP\tiansi(BMASTERP);\n\tvirtual\tSTRINGP\toansi(BMASTERP);\n\tvirtual\tSTRINGP\tmaster_ansprefix(BMASTERP);\n\tvirtual\tSTRINGP\tmaster_portlist(BMASTERP);\n\tvirtual\tSTRINGP\tmaster_ansi_portlist(BMASTERP);\n\tvirtual\tSTRINGP\tslave_ansprefix(PERIPHP);\n\tvirtual\tSTRINGP\tslave_portlist(PERIPHP);\n\tvirtual\tSTRINGP\tslave_ansi_portlist(PERIPHP);\n\n\tvirtual\tvoid\tintegrity_check(void);\n};\n\nclass\tWBBUSCLASS : public BUSCLASS {\npublic:\n\tvirtual\tSTRINGP\tname(void);\t// i.e. WB\n\tvirtual\tSTRINGP\tlongname(void);\t// i.e. \"Wishbone\"\n\tvirtual\tbool\tmatchtype(STRINGP strp);\n\tvirtual\tbool\tmatchfail(MAPDHASH *);\n\t// virtual\tbool\tmatches(BUSINFO *bi);\n\tGENBUS\t*create(BUSINFO *bi);\n};\n\n#endif\n"
  },
  {
    "path": "sw/businfo.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/businfo.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tThe businfo structure is a generic object describing a bus\n//\t\t(in general) and all the properties associated with it.  It is\n//\tused by the specific bus logic drivers (in bus/*) to know how much\n//\taddress space, or data width is used by the bus, or what masters and\n//\tslaves are connected to the bus.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <string.h>\n#include <unistd.h>\n#include <ctype.h>\n\n#include \"parser.h\"\n#include \"mapdhash.h\"\n#include \"keys.h\"\n#include \"kveval.h\"\n#include \"legalnotice.h\"\n#include \"bldtestb.h\"\n#include \"bitlib.h\"\n#include \"plist.h\"\n#include \"bldregdefs.h\"\n#include \"ifdefs.h\"\n#include \"bldsim.h\"\n#include \"predicates.h\"\n#include \"businfo.h\"\n#include \"globals.h\"\n#include \"subbus.h\"\n#include \"msgs.h\"\n#include \"clockinfo.h\"\n\nBUSLIST\t*gbl_blist;\n\n#define\tPREFIX\n\n// Look up the number of bits in the address bus of the given hash\nint\tBUSINFO::address_width(void) {\n\tif (!m_addresses_assigned)\n\t\tassign_addresses();\n\treturn generator()->address_width();\n}\n\nbool\tBUSINFO::word_addressing(void) {\n\tassert(m_genbus);\n\treturn\tm_genbus->word_addressing();\n}\n\nint\tBUSINFO::data_width(void) {\n\tint\tvalue;\n\n\tif ((m_hash)&&(getvalue(m_hash, KY_WIDTH, value))) {\n\t\tm_data_width = value;\n\t} if (m_data_width > 0)\n\t\treturn m_data_width;\n\treturn\t32;\n}\n\nSTRINGP\tBUSINFO::name(void) {\n\tSTRINGP\tstr;\n\tstr = getstring(m_hash, KY_NAME);\n\tif (!m_name)\n\t\tm_name = str;\n\telse if (str->compare(*m_name) != 0) {\n\t\tgbl_msg.error(\"Bus name %s has changed to %s\\n\", m_name->c_str(), str->c_str());\n\t\tm_name = str;\n\t}\n\treturn\tstr;\n}\n\nSTRINGP\tBUSINFO::prefix(STRINGP p) {\n\tSTRINGP\thash_prefix;\n\n\thash_prefix = getstring(m_hash, KYPREFIX);\n\n\tif (!p)\n\t\treturn hash_prefix;\n\n\tif (NULL == hash_prefix && NULL != p) {\n\t\tsetstring(m_hash, KYPREFIX, p);\n\t\thash_prefix = p;\n\t} else if (p && hash_prefix->compare(*p) != 0)\n\t\tgbl_msg.error(\"Renaming bus %s with a second prefix\", name());\n\n\treturn hash_prefix;\n}\n\nSTRINGP\tBUSINFO::btype(void) {\n\tSTRINGP\tstr;\n\tstr = getstring(m_hash, KY_TYPE);\n\tif (!m_type)\n\t\tm_type = str;\n\telse if (str->compare(*m_type) != 0) {\n\t\tgbl_msg.error(\"Bus %s type has changed from %s to %s\\n\",\n\t\t\tname()->c_str(), m_type->c_str(), str->c_str());\n\t\tm_type = str;\n\t}\n\treturn\tstr;\n}\n\nSTRINGP\tBUSINFO::reset_wire(void) {\n\tSTRINGP\tstr;\n\tstr = getstring(m_hash, KY_RESET);\n\tif (NULL != str)\n\t\treturn str;\n\n\tif (m_clock)\n\t\tstr = getstring(m_clock->m_hash, KY_RESET);\n\treturn str;\n}\n\nbool\tBUSINFO::get_base_address(MAPDHASH *phash, unsigned &base) {\n\tif (!generator()) {\n\t\tgbl_msg.error(\"BUS[%s] has no type\\n\",\n\t\t\tm_name->c_str());\n\t\treturn false;\n\t} else\n\t\treturn generator()->get_base_address(phash, base);\n}\n\nvoid\tBUSINFO::assign_addresses(void) {\n\tif (!generator())\n\t\tgbl_msg.fatal(\"Bus %s has no generator type defined\\n\",\n\t\t\tm_name->c_str());\n\n\tgbl_msg.info(\"BI: Assigning addresses for bus %s\\n\", m_name->c_str());\n\tgenerator()->assign_addresses();\n\n\tif (m_mlist) for(unsigned k=0; k<m_mlist->size(); k++) {\n\t\t// Set the bus prefix for the master\n\t\tSTRINGP\t\tmname;\n\t\tMAPDHASH\t*hash = (*m_mlist)[k]->m_hash;\n\n\t\tmname = (*m_mlist)[k]->name();\n\t\tgbl_msg.info(\"BI: Assigning portlists for bus %s, \"\n\t\t\t\"master %s\\n\", m_name->c_str(),\n\t\t\t(mname) ? mname->c_str() : \" (No-name)\");\n\t\t(*m_mlist)[k]->bus_prefix();\n\t\tsetstring(hash, KYMASTER_PORTLIST,\n\t\t\tgenerator()->master_portlist((*m_mlist)[k]));\n\t\tsetstring(hash, KYMASTER_ANSIPORTLIST,\n\t\t\tgenerator()->master_ansi_portlist((*m_mlist)[k]));\n\t\tif (!getstring(hash, KYMASTER_IANSI))\n\t\t\tsetstring(hash, KYMASTER_IANSI, generator()->iansi((*m_mlist)[k]));\n\t\tif (!getstring(hash, KYMASTER_OANSI))\n\t\t\tsetstring(hash, KYMASTER_OANSI, generator()->oansi((*m_mlist)[k]));\n\t\tif (!getstring(hash, KYMASTER_ANSPREFIX))\n\t\t\tsetstring(hash, KYMASTER_ANSPREFIX, generator()->master_ansprefix((*m_mlist)[k]));\n\n\t\tREHASH;\n\t}\n\n\tm_addresses_assigned = true;\n}\n\nvoid BUSINFO::add(void) {\n\tif (!m_plist) {\n\t\tm_plist = new PLIST;\n\t\tm_plist->integrity_check();\n\t}\n}\n\nPERIPH *BUSINFO::add(PERIPHP p) {\n\tint\tpi;\n\tPLISTP\tplist;\n\n\tif (!m_plist)\n\t\tm_plist = new PLIST();\n\telse\n\t\tm_plist->integrity_check();\n\tplist = m_plist;\n\n\tpi = plist->add(p);\n\tm_addresses_assigned = false;\n\tplist->integrity_check();\n\tif (pi >= 0) {\n\t\tp = (*plist)[pi];\n\t\tp->p_slave_bus = this;\nassert(NULL != p->p_phash);\n\t\treturn p;\n\t} else {\n\t\tgbl_msg.fatal(\"Could not add %s\\n\",\n\t\t\tgetstring(p->p_phash, KYPREFIX)->c_str());\n\t\treturn NULL;\n\t}\n}\n\nPERIPH *BUSINFO::add(MAPDHASH *phash) {\n\tPERIPH\t*p;\n\tint\tpi;\n\tPLISTP\tplist;\n\n\tif (!m_plist)\n\t\tm_plist = new PLIST();\n\tplist = m_plist;\n\tassert(plist);\n\n\tpi = plist->add(phash);\n\tif (pi >= 0) {\n\t\tp = (*plist)[pi];\n\t\tp->p_slave_bus = this;\n\t\treturn p;\n\t} else {\n\t\tgbl_msg.error(\"Could not add %s\\n\", getstring(phash, KYPREFIX)->c_str());\n\t\treturn NULL;\n\t}\n}\n\nbool\tBUSINFO::need_translator(BUSINFO *m) {\n\t// If they are the same bus, then no translator is necessary\n\tif ((m==NULL)||(this == m))\n\t\treturn false;\n\tif (m_name->compare(*m->m_name)==0)\n\t\treturn false;\n\n\t// If they are of different clocks, then a translator is required\n\tif ((m_clock)&&(m->m_clock)&&(m_clock != m->m_clock))\n\t\treturn true;\n\n\t// If they are of different widths\n\tif ((m_data_width)&&(m->m_data_width)\n\t\t\t&&(m_data_width != m->m_data_width))\n\t\treturn true;\n\n\t// If they are of different bus types\n\tif ((m_type)&&(m->m_type)\n\t\t\t&&(m_type->compare(*m->m_type) != 0))\n\t\treturn true;\n\t//\n\t//\n\treturn false;\n}\n\nPERIPHP\tBUSINFO::operator[](unsigned k) {\n\tunsigned\tidx = k;\n\n\tif (idx < m_plist->size())\n\t\treturn (*m_plist)[idx];\n\n\treturn NULL;\n}\n\nunsigned\tBUSINFO::size(void) {\n\tunsigned sz = m_plist->size();\n\n\treturn sz;\n}\n\nvoid\tBUSINFO::init(MAPDHASH *bushash) {\n\tm_hash = bushash;\n\tm_name = getstring(m_hash, KY_NAME);\n\tif (!getvalue(m_hash, KY_WIDTH, m_data_width))\n\t\tm_data_width = 0;\n\telse {\n\t\tsetvalue(*m_hash, KY_NSELECT, (m_data_width+7)/8);\n\t}\n\tif (!getvalue(m_hash, KY_NULLSZ, m_nullsz))\n\t\tm_nullsz = 0;\n\tif (getstring(m_hash, KY_TYPE))\n\t\tgenerator();\n}\n\nvoid\tBUSINFO::init(STRINGP bname) {\n\tm_hash = new MAPDHASH();\n\tsetstring(m_hash, KY_NAME, bname);\n\tm_name = getstring(m_hash, KY_NAME);\n}\n\n// void\tBUSINFO::merge(STRINGP src, MAPDHASH *hash) {\n//\n//\tMerge description of bus from multiple disparate sources\n//\n//\tSet name, prefix, type, clock, nullsz, data width\n//\n// }\n\nvoid\tBUSINFO::merge(STRINGP component, MAPDHASH *bp) {\n\t// Component is the name of the component with this bus reference\n\t// bp is the pointer to the BUS reference from within this component\n\t//\n\tint\tvalue;\n\tMAPT\telm;\n\tSTRINGP\tstrp;\n\n\tfor(MAPDHASH::iterator kvpair=bp->begin(); kvpair != bp->end();\n\t\t\t\tkvpair++) {\n\t\tif (0 == KY_WIDTH.compare(kvpair->first)) {\n\t\t\tif (getvalue(*bp, KY_WIDTH, value)) {\n\t\t\t\tif (m_data_width <= 0) {\n\t\t\t\t\tm_data_width = value;\n\t\t\t\t\t//\n\t\t\t\t\telm.m_typ = MAPT_INT;\n\t\t\t\t\telm.u.m_v = value;\n\t\t\t\t\tm_hash->insert(KEYVALUE(KY_WIDTH, elm));\n\t\t\t\t\tgbl_msg.info(\"Setting bus width for %s bus to %d, in %s\\n\", m_name->c_str(), value, component->c_str());\n\n\t\t\t\t\t// Calculate the number of select lines\n\t\t\t\t\telm.m_typ = MAPT_INT;\n\t\t\t\t\telm.u.m_v = (value+7)/8;\n\t\t\t\t\tm_hash->insert(KEYVALUE(KY_NSELECT, elm));\n\t\t\t\t\tREHASH;\n\t\t\t\t\tkvpair = bp->begin();\n\t\t\t\t} else if (m_data_width != value) {\n\t\t\t\t\tgbl_msg.error(\"Conflicting bus width definitions for %s: %d != %d in %s\\n\", m_name->c_str(), m_data_width, value, component->c_str());\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue;\n\t\t} if (0== KY_NULLSZ.compare(kvpair->first)) {\n\t\t\tif ((getvalue(*bp, KY_NULLSZ, value))&&(m_nullsz != value)) {\n\t\t\t\tgbl_msg.info(\"BUSINFO::INIT(%s).NULLSZ \"\n\t\t\t\t\t\"FOUND: %d\\n\", component->c_str(), value);\n\t\t\t\tm_nullsz = (value > m_nullsz) ? value : m_nullsz;\n\t\t\t\t// m_addresses_assigned = false;\n\t\t\t\t//\n\t\t\t\telm.m_typ = MAPT_INT;\n\t\t\t\telm.u.m_v = value;\n\t\t\t\tm_hash->insert(KEYVALUE(KY_NULLSZ, elm));\n\n\t\t\t\tREHASH;\n\t\t\t\tkvpair = bp->begin();\n\t\t\t}\n\t\t\tcontinue;\n\t\t} if (0== KY_IDWIDTH.compare(kvpair->first)) {\n\t\t\tif (0 != getvalue(*bp, KY_IDWIDTH, value)) {\n\t\t\t\tMAPDHASH::iterator kvprev;\n\t\t\t\tgbl_msg.info(\"BUSINFO::INIT(%s).IDWIDTH \"\n\t\t\t\t\t\"FOUND: %d\\n\", component->c_str(), value);\n\t\t\t\tif (m_hash->end() == (kvprev =\n\t\t\t\t\t\tfindkey(*m_hash, KY_IDWIDTH))){\n\t\t\t\t\telm.m_typ = MAPT_INT;\n\t\t\t\t\telm.u.m_v = value;\n\t\t\t\t\tm_hash->insert(KEYVALUE(KY_IDWIDTH, elm));\n\n\t\t\t\t\tREHASH;\n\t\t\t\t\tkvpair = bp->begin();\n\t\t\t\t} else if (kvprev->second.m_typ != MAPT_INT){\n\t\t\t\t\tgbl_msg.info(\"BUSINFO::INIT(%s).IDWIDTH not an integer??\\n\", component->c_str());\n\t\t\t\t} else if (kvprev->second.u.m_v != value) {\n\t\t\t\t\tgbl_msg.error(\"BUSINFO::INIT(%s).IDWIDTH has conflicting values, %d and %d\\n\", component->c_str(), value, kvprev->second.u.m_v);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif ((MAPT_STRING == kvpair->second.m_typ)\n\t\t\t\t&&(NULL != kvpair->second.u.m_s)) {\n\t\t\tstrp = kvpair->second.u.m_s;\n\t\t\tgbl_msg.info(\"BUSINFO::MERGE(%s) @%s=%s\\n\",\n\t\t\t\tcomponent->c_str(), kvpair->first.c_str(),\n\t\t\t\tkvpair->second.u.m_s->c_str());\n\t\t\tif (0 == KY_TYPE.compare(kvpair->first)) {\n\t\t\t\tif (m_type == NULL) {\n\t\t\t\t\tm_type = strp;\n\t\t\t\t\telm.m_typ = MAPT_STRING;\n\t\t\t\t\telm.u.m_s = strp;\n\t\t\t\t\tif (NULL == m_hash) {\n\t\t\t\t\t\tgbl_msg.error(\"Undefined bus as a part of %s (no name given?)\\n\",\n\t\t\t\t\t\t\tcomponent->c_str());\n\t\t\t\t\t} else\n\t\t\t\t\t\tm_hash->insert(KEYVALUE(KY_TYPE, elm));\n\n\t\t\t\t\tREHASH;\n\t\t\t\t\tkvpair = bp->begin();\n\t\t\t\t} else if (m_type->compare(*strp) != 0) {\n\t\t\t\t\tgbl_msg.error(\"Conflicting bus types \"\n\t\t\t\t\t\t\"for %s\\n\",m_name->c_str());\n\t\t\t\t\tgbl_msg.info(\"First bus type: %s\\n\", m_type->c_str());\n\t\t\t\t\tgbl_msg.info(\"New   bus type: %s\\n\", strp->c_str());\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t} else if (0 == KY_RESET.compare(kvpair->first)) {\n\t\t\t\tSTRINGP\treset = getstring(m_hash, KY_RESET);\n\t\t\t\tif (reset == NULL) {\n\t\t\t\t\telm.m_typ = MAPT_STRING;\n\t\t\t\t\telm.u.m_s = strp;\n\t\t\t\t\tm_hash->insert(KEYVALUE(KY_RESET, elm));\n\n\t\t\t\t\tREHASH;\n\t\t\t\t\tkvpair = bp->begin();\n\t\t\t\t} else if (reset->compare(*strp) != 0) {\n\t\t\t\t\tgbl_msg.error(\"Conflicting bus resets \"\n\t\t\t\t\t\t\"for %s\\n\",m_name->c_str());\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t} else if ((0 == KY_CLOCK.compare(kvpair->first))\n\t\t\t\t\t&&(NULL == m_clock)) {\n\t\t\t\tgbl_msg.info(\"BUSINFO::INIT(%s).\"\n\t\t\t\t\t\"CLOCK(%s)\\n\", component->c_str(),\n\t\t\t\t\tstrp->c_str());\n\t\t\t\tassert(strp);\n\t\t\t\tm_clock = getclockinfo(strp);\n\t\t\t\tif (m_clock == NULL)\n\t\t\t\t\tm_clock = CLOCKINFO::new_clock(kvpair->second.u.m_s);\n\t\t\t\tgbl_msg.info(\"BUSINFO::INIT(%s).\"\n\t\t\t\t\t\"CLOCK(%s) FOUND, FREQ = %d\\n\",\n\t\t\t\t\tcomponent->c_str(), strp->c_str(),\n\t\t\t\t\tm_clock->frequency());\n\t\t\t\telm.m_typ = MAPT_MAP;\n\t\t\t\telm.u.m_m = m_clock->m_hash;\n\n\t\t\t\tif (NULL == m_hash) {\n\t\t\t\t\tgbl_msg.error(\"Undefined bus as a part of %s (no name given?)\\n\",\n\t\t\t\t\t\tcomponent->c_str());\n\t\t\t\t} else\n\t\t\t\t\tm_hash->insert(KEYVALUE(KY_CLOCK, elm));\n\t\t\t\tkvpair->second.m_typ = MAPT_MAP;\n\t\t\t\tkvpair->second.u.m_m = m_clock->m_hash;\n\t\t\t\tREHASH;\n\t\t\t\tkvpair = bp->begin();\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\t/*\n\t\t// We should really allow a clock *definition* here, rather\n\t\t// than just a reference\n\t\t//\n\t\telse if ((kvpair->second.m_typ == MAPT_MAP)\n\t\t\t\t&&(NULL != kvpair->second.u.m_m)) {\n\t\t\tif ((KY_CLOCK.compare(kvpair->first)==0)\n\t\t\t\t\t&&(NULL == m_clock))\n\t\t\t\t;\n\t\t}\n\t\t*/\n\n\t\t// Anything else, we copy into our defining hash\n\t\tif ((bp != m_hash)&&(m_hash->end()\n\t\t\t\t!= findkey(*m_hash, kvpair->first))) {\n\t\t\tm_hash->insert(*kvpair);\n\t\t\t// REHASH;\n\t\t}\n\t}\n}\n\nSTRINGP\tBUSINFO::slave_portlist(PERIPHP p) {\n\tif (!generator())\n\t\treturn NULL;\n\treturn generator()->slave_portlist(p);\n}\n\nSTRINGP\tBUSINFO::slave_iansi(PERIPHP p) {\n\tif (!generator())\n\t\treturn NULL;\n\treturn generator()->iansi(NULL);\n}\n\nSTRINGP\tBUSINFO::slave_oansi(PERIPHP p) {\n\tif (!generator())\n\t\treturn NULL;\n\treturn generator()->oansi(NULL);\n}\n\nSTRINGP\tBUSINFO::slave_ansprefix(PERIPHP p) {\n\tif (!generator())\n\t\treturn NULL;\n\treturn generator()->slave_ansprefix(p);\n}\n\nSTRINGP\tBUSINFO::slave_ansi_portlist(PERIPHP p) {\n\tif (!generator())\n\t\treturn NULL;\n\treturn generator()->slave_ansi_portlist(p);\n}\n\nSTRINGP\tBUSINFO::master_portlist(BMASTERP b) {\n\tif (!generator())\n\t\treturn NULL;\n\treturn generator()->master_portlist(b);\n}\n\nSTRINGP\tBUSINFO::master_ansi_portlist(BMASTERP b) {\n\tif (!generator())\n\t\treturn NULL;\n\treturn generator()->master_ansi_portlist(b);\n}\n\nvoid\tBUSINFO::integrity_check(void) {\n\tif (!m_name) {\n\t\tgbl_msg.error(\"Bus with no name! (No BUS.NAME tag)\\n\");\n\t\treturn;\n\t}\n\n\tif (m_data_width <= 0) {\n\t\tgbl_msg.error(\"BUS width not defined for %s\\n\",\n\t\t\tm_name->c_str());\n\t}\n\n\tif (m_clock == NULL) {\n\t\tgbl_msg.error(\"BUS %s has no defined clock\\n\",\n\t\t\tm_name->c_str());\n\t}\n}\n\nbool\tneed_translator(BUSINFO *s, BUSINFO *m) {\n\tif (!s)\n\t\treturn false;\n\treturn s->need_translator(m);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////////////////////////////\n//\n// Operations on sets of buses (i.e. vectors of BUSINFO)\n//\n////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////////////////////////////\nBUSINFO *BUSLIST::find_bus_of_peripheral(MAPDHASH *phash) {\n\tassert(NULL != phash);\n\tfor(iterator bp=begin(); bp!=end(); bp++) {\n\t\tif ((*bp)->ismember_of(phash))\n\t\t\treturn (*bp);\n\t} return NULL;\n}\n\nBUSINFO *find_bus_of_peripheral(MAPDHASH *phash) {\n\treturn gbl_blist->find_bus_of_peripheral(phash);\n}\n\nBUSINFO *BUSLIST::find_bus(MAPDHASH *hash) {\n\tif (!hash) {\n\t\tif ((*this)[0])\n\t\t\treturn ((*this)[0]);\n\t\treturn NULL;\n\t}\n\tfor(unsigned k=0; k<size(); k++) {\n\t\tif (((*this)[k]->m_hash)&&(hash == (*this)[k]->m_hash)) {\n\t\t\treturn (*this)[k];\n\t\t}\n\t} return NULL;\n}\n\nBUSINFO *find_bus(MAPDHASH *hash) {\n\treturn gbl_blist->find_bus(hash);\n}\n\nBUSINFO *BUSLIST::find_bus(STRINGP name) {\n\t// If no name is given, return the default bus\n\tif (NULL == name) {\n\t\tif ((*this)[0])\n\t\t\treturn ((*this)[0]);\n\t\treturn NULL;\n\t}\n\tfor(unsigned k=0; k<size(); k++) {\n\t\tif (((*this)[k]->name())\n\t\t\t&&((*this)[k]->name()->compare(*name)==0)) {\n\t\t\treturn (*this)[k];\n\t\t}\n\t} return NULL;\n}\n\nBUSINFO *find_bus(STRINGP name) {\n\treturn gbl_blist->find_bus(name);\n}\n\nunsigned\tBUSLIST::get_base_address(MAPDHASH *phash) {\n\tunsigned\tbase;\n\t// Assume everything has only one address, and that the first\n\t// address is the one we want\n\tfor(unsigned i=0; i<size(); i++)\n\t\tif ((*this)[i]->get_base_address(phash, base))\n\t\t\treturn base;\n\treturn 0;\n}\n\nvoid\tBUSLIST::addperipheral(MAPDHASH *phash) {\n\tSTRINGP\tpname;\n\tBUSINFO\t*bi;\n\n\t// Ignore everything that isn't a bus slave\n\tif (NULL == getmap(*phash, KYSLAVE))\n\t\treturn;\n\tif (NULL == (pname = getstring(*phash, KYPREFIX)))\n\t\tpname = new STRING(\"(Unnamed-P)\");\n\tgbl_msg.info(\"Adding peripheral %s to bus %s\\n\", pname->c_str(),\n\t\t(getstring(phash, KYSLAVE_BUS_NAME)\n\t\t? getstring(phash, KYSLAVE_BUS_NAME)->c_str() : \"(Unnamed)\"));\n\t// Insist on the existence of a default bus\n\tassert((*this)[0]);\n\n\tMAPDHASH::iterator\tkvpair, kvbus;\n\n\tkvpair = findkey(*phash, KYSLAVE_BUS);\n\tif (kvpair == phash->end()) {\n\t\tbi = (*this)[0];\n\t} else if (kvpair->second.m_typ == MAPT_STRING) {\n\t\t// If this peripheral is on a named bus, point us to it.\n\t\tbi = find_bus(kvpair->second.u.m_s);\n\t\t// Insist, though, that the named bus exist already\n\t\tassert(bi);\n\t} else if (kvpair->second.m_typ == MAPT_MAP) {\n\t\tbi = find_bus(kvpair->second.u.m_m);\n\t\tif (bi == NULL) {\n\t\t\tMAPDHASH\t*blmap = kvpair->second.u.m_m;\n\t\t\tfor(kvbus = blmap->begin(); kvbus != blmap->end();\n\t\t\t\t\tkvbus++) {\n\t\t\t\tif (kvbus->second.m_typ != MAPT_MAP)\n\t\t\t\t\tcontinue;\n\t\t\t\tbi = find_bus(kvbus->second.u.m_m);\n\t\t\t\tif (NULL == bi)\n\t\t\t\t\tcontinue;\n\t\t\t\tbi->add(phash);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tassert(bi);\n\t}\n\n\t// Now that we know what bus this peripheral attaches to, add it in\n\tassert(bi);\n\tbi->add(phash);\n\tassert(bi->m_plist);\n\n\tbi->m_plist->integrity_check();\n}\n\nvoid\tBUSLIST::addperipheral(MAPT &map) {\n\tif (map.m_typ == MAPT_MAP)\n\t\taddperipheral(map.u.m_m);\n}\n\nvoid\tBUSLIST::addmaster(MAPDHASH *phash) {\n\t// STRINGP\tmname;\n\tBUSINFO\t*bi;\n\n\t// Ignore everything that isn't a bus slave\n\tif (NULL == getmap(*phash, KYMASTER))\n\t\treturn;\n\n\t/*\n\tif (NULL == (mname = getstring(*phash, KYPREFIX)))\n\t\tmname = new STRING(\"(Unnamed-M)\");\n\t*/\n\n\t// Insist on the existence of a default bus\n\tassert((*this)[0]);\n\n\tMAPDHASH::iterator\tkvpair, kvbus;\n\n\tkvpair = findkey(*phash, KYMASTER_BUS);\n\tif (kvpair == phash->end()) {\n\t\t//\n\t\t// We have a MASTER tag with no MASTER.BUS tag\n\t\t//\n\t\t// Make this the default bus\n\t\t//\n\t\tbi = (*this)[0];\n\t} else if (kvpair->second.m_typ == MAPT_STRING) {\n\t\t//\n\t\t// MASTER.BUS= <name>\n\t\t//\n\t\t// If this peripheral is on a named bus, point us to it.\n\t\tbi = find_bus(kvpair->second.u.m_s);\n\t\t// Insist, though, that the named bus exist already\n\t\tassert(bi);\n\n\t\tgbl_msg.error(\"MASTER.BUS string shouldn't be here\");\n\t} else if (kvpair->second.m_typ == MAPT_MAP) {\n\t\tbi = find_bus(kvpair->second.u.m_m);\n\t\tif (bi == NULL) {\n\t\t\tMAPDHASH\t*blmap = kvpair->second.u.m_m;\n\t\t\tfor(kvbus = blmap->begin(); kvbus != blmap->end();\n\t\t\t\t\tkvbus++) {\n\t\t\t\tif (kvbus->second.m_typ != MAPT_MAP)\n\t\t\t\t\tcontinue;\n\t\t\t\tbi = find_bus(kvbus->second.u.m_m);\n\t\t\t\tif (NULL == bi)\n\t\t\t\t\tcontinue;\n\t\t\t\tbi->addmaster(phash);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tassert(bi);\n\t}\n\n\t// Now that we know what bus this peripheral attaches to, add it in\n\tassert(bi);\n\tbi->addmaster(phash);\n\tassert(bi->m_mlist);\n\t//\n\t// bi->m_mlist->integrity_check();\n}\n\n\nvoid\tBUSLIST::addmaster(MAPT &map) {\n\tif (map.m_typ == MAPT_MAP)\n\t\taddmaster(map.u.m_m);\n}\n\nvoid\tBUSLIST::adddefault(MAPDHASH &master, STRINGP defname) {\n\tBUSINFO\t*bi;\n\n\tif (size() == 0) {\n\t\t// If there are no elements (yet) in our BUSLIST, then create\n\t\t// a first one, and call it our default.\n\t\tpush_back(bi = new BUSINFO());\n\t\tbi->m_hash = new MAPDHASH();\n\t\tsetstring(*bi->m_hash, KY_NAME, defname);\n\t} else { // if (size() > 0)\n\t\t//\n\t\t// If there are already busses in our bus list, shuffle them\n\t\t// so that the bus named defname is the first.\n\t\t//\n\t\tif (NULL != (bi = find_bus(defname))) {\n\n\t\t\t// This bus already exists\n\t\t\tfor(unsigned k=0; k<size(); k++) {\n\t\t\t\tif (((*this)[k]->name())\n\t\t\t\t\t&&((*this)[k]->name()->compare(*defname)==0)) {\n\t\t\t\t\tif (k == 0)\n\t\t\t\t\t\treturn;\n\n\t\t\t\t\t// If it's not the zero bus,\n\t\t\t\t\t// move it to the zero position\n\t\t\t\t\tBUSINFO *bi = (*this)[0];\n\t\t\t\t\t(*this)[0] = (*this)[k];\n\t\t\t\t\t(*this)[k] = bi;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ((*this)[0]->name()) {\n\t\t\t// The bus doesn't exist, although others do\n\t\t\tif ((*this)[0]->name()->compare(*defname)!=0) {\n\t\t\t\t// Create a new BUSINFO struct for\n\t\t\t\t// this new one\n\t\t\t\tpush_back((*this)[0]);\n\t\t\t\t(*this)[0] = bi = new BUSINFO();\n\t\t\t\tbi->m_hash = new MAPDHASH();\n\t\t\t\tsetstring(*bi->m_hash, KY_NAME, defname);\n\t\t\t}\n\t\t\t// else this is already the default\n\t\t} else {\n\t\t\t// First spot exists, but has no name\n\t\t\tbi = (*this)[0];\n\t\t\tsetstring(*bi->m_hash, KY_NAME, defname);\n\t\t}\n\t}\n}\n\nBUSINFO *BUSLIST::newbus_aux(STRINGP component, MAPDHASH *bp) {\n\tif (NULL == bp)\n\t\treturn NULL;\n\n\tSTRINGP\tstr;\n\tBUSINFO\t*bi;\n\n\tstr = getstring(*bp, KY_NAME);\n\tif (str) {\n\t\tbi = find_bus(str);\n\t\tif (!bi) {\n\t\t\tMAPDHASH::iterator\tkvpair;\n\n\t\t\tbi = new BUSINFO();\n\t\t\tpush_back(bi);\n\t\t\tbi->init(bp);\n\t\t\tgbl_msg.userinfo(\"Bus: %s\\n\", str->c_str());\n\t\t} else {\n\t\t\t// We need to merge the BUS-MAP into the existing\n\t\t\t// one\n\t\t\tbi->merge(component, bp);\n\t\t\t// We don't need to initialize a new bus, so just\n\t\t\t// return\n\t\t}\n\t} else if (size() > 0) {\n\t\t// A default bus exists, add to that\n\t\tbi = (*this)[0];\n\t\tbi->merge(component, bp);\n\t} else {\n\t\tbi = new BUSINFO();\n\t\tpush_back(bi);\n\t\tbi->init(bp);\n\t}\n\n\treturn bi;\n}\n\nBUSINFO *BUSLIST::newbus_aux(STRINGP component, STRINGP bn) {\n\tif (NULL == bn)\n\t\treturn NULL;\n\n\tBUSINFO\t*bi;\n\n\tbi = find_bus(bn);\n\tif (!bi) {\n\t\tMAPDHASH::iterator\tkvpair;\n\n\t\tbi = new BUSINFO();\n\t\tpush_back(bi);\n\t\tbi->init(bn);\n\t\tgbl_msg.userinfo(\"BUS: %s (from %s)\\n\", bn->c_str(),\n\t\t\t(component) ?  component->c_str() : \"(Unnamed component)\");\n\t}\n\n\treturn bi;\n}\n\nvoid\tBUSLIST::addbus(STRINGP cname, STRINGP bname) {\n\t(void)newbus_aux(cname, bname);\n}\n\nvoid\tBUSLIST::addbus(STRINGP cname, MAPDHASH *bhash) {\n\tSTRINGP\t\tbname;\n\tBUSINFO\t\t*bi;\n\n\tbname = getstring(bhash, KY_NAME);\n\tif (bname == NULL)\n\t\t// Bus is un-named--won't happen here\n\t\treturn;\n\n\tbi = find_bus(bname);\n\tif (!bi)\n\t\tbi = newbus_aux(cname, bhash);\n\t\t// This includes the merge\n\telse\n\t\tbi->merge(cname, bhash);\n}\nvoid\tBUSLIST::addbus(STRINGP cname, MAPT &map) {\n\tif (map.m_typ == MAPT_MAP)\n\t\taddbus(cname, map.u.m_m);\n}\n\n//\n// assign_addresses\n//\n// Assign addresses to all of our peripherals, given a first address to start\n// from.  The first address helps to insure that the NULL address creates a\n// proper error (as it should).\n//\nvoid assign_addresses(void) {\nfprintf(stderr, \"MASTER--> ASSIGN ADDRESSES\\n\");\n\tfor(unsigned i=0; i<gbl_blist->size(); i++)\n\t\t(*gbl_blist)[i]->assign_addresses();\n}\n\nvoid\tBUSINFO::writeout_bus_defns_v(FILE *fp) {\n\tif (!generator())\n\t\tgbl_msg.error(\"No bus type defined for bus %s\\n\", name()->c_str());\n\tgenerator()->writeout_bus_defns_v(fp);\n}\n\nvoid\twriteout_bus_defns_v(FILE *fp) {\n\tfprintf(fp, \"\\t////////////////////////////////////////////////////////////////////////\\n\"\n\t\t\"\\t//\\n\"\n\t\t\"\\t// Declare bus signals\\n\"\n\t\t\"\\t// {{{\\n\"\n\t\t\"\\t////////////////////////////////////////////////////////////////////////\\n\\n\");\n\tBUSLIST\t*bl = gbl_blist;\n\tfor(BUSLIST::iterator bp=bl->begin(); bp != bl->end(); bp++) {\n\t\tfprintf(fp, \"\\t// Bus %s\\n\\t// {{{\\n\", (*bp)->name()->c_str());\n\t\t(*bp)->writeout_bus_defns_v(fp);\n\t\tfprintf(fp, \"\\t// }}}\\n\");\n\t}\n\tfprintf(fp, \"\\t// }}}\\n\");\n}\n\nvoid\tBUSINFO::writeout_no_slave_v(FILE *fp, STRINGP prefix) {\n\tif (!generator())\n\t\tgbl_msg.error(\"No slaves assigned to bus %s\\n\", name()->c_str());\n\telse\n\t\tgenerator()->writeout_no_slave_v(fp, prefix);\n}\n\nvoid\tBUSINFO::writeout_no_master_v(FILE *fp) {\n\tif (!generator())\n\t\tgbl_msg.error(\"No slaves assigned to bus %s\\n\",\n\t\t\t(name()) ? name()->c_str() : \"(Unnamed-bus)\");\n\telse\n\t\tgenerator()->writeout_no_master_v(fp);\n}\n\nbool\tBUSINFO::ismember_of(MAPDHASH *phash) {\n\tif (m_plist == NULL)\n\t\treturn false;\n\tfor(unsigned i=0; i<m_plist->size(); i++)\n\t\tif ((*m_plist)[i]->p_phash == phash)\n\t\t\treturn true;\n\n\treturn false;\n}\n\nvoid\tBUSINFO::writeout_bus_logic_v(FILE *fp) {\n\tif (!generator())\n\t\tgbl_msg.error(\"No slaves assigned to bus %s\\n\", name()->c_str());\n\telse\n\t\tgenerator()->writeout_bus_logic_v(fp);\n}\n\nvoid\twriteout_bus_logic_v(FILE *fp) {\n\tfor(unsigned i=0; i<gbl_blist->size(); i++) {\n\t\tfprintf(fp, \"\\t//\\n\\t// BUS-LOGIC for %s\\n\\t// {{{\\n\",\n\t\t\t(*gbl_blist)[i]->name()->c_str());\n\t\t(*gbl_blist)[i]->writeout_bus_logic_v(fp);\n\t\tfprintf(fp, \"\\t// End of bus logic for %s\\n\"\n\t\t\t\"\\t// }}}\\n\", (*gbl_blist)[i]->name()->c_str());\n\t}\n}\n\nvoid\tassign_bus_slave(MAPDHASH &master, MAPDHASH *bus_slave) {\n\tMAPDHASH::iterator sbus;\n\tBUSINFO\t*bi;\n\tSTRINGP\tpname, strp;\n\tMAPDHASH\t*shash;\n\n\tpname = getstring(*bus_slave, KYPREFIX);\n\tif (pname == NULL)\n\t\tpname = new STRING(\"(Null)\");\n\n\tshash = getmap(*bus_slave, KYSLAVE);\n\tif (NULL == shash)\n\t\treturn;\n\n\tsbus = findkey(*shash, KYBUS);\n\tif (sbus == shash->end()) {\n\t\t//\n\t\t// No SLAVE.BUS tag\n\t\t//\n\t} else if (sbus->second.m_typ == MAPT_STRING) {\n\t\t//\n\t\t// SLAVE.BUS = bus_name\n\t\t//\n\t\tBUSINFO\t*bi;\n\t\tchar\t*cstr, *tok, *nxt;\n\t\tconst char\t*DELIMITERS=\", \\t\\r\\n\";\n\n\t\tstrp = sbus->second.u.m_s;\n\t\tcstr = strdup(strp->c_str());\n\n\t\t// Allow only one bus name\n\t\ttok = strtok(cstr, DELIMITERS);\n\t\tnxt = strtok(NULL, DELIMITERS);\n\t\tif ((tok)&&(!nxt)) {\n\t\t\tbi = gbl_blist->find_bus(strp);\n\t\t\tif (NULL == bi) {\n\t\t\t\t// Buses should've been found and enumerated\n\t\t\t\t// already\n\t\t\t\tgbl_msg.error(\"BUS %s not found in %s\\n\",\n\t\t\t\t\ttok, pname->c_str());\n\t\t\t} else {\n\t\t\t\t//\n\t\t\t\t// Replace the bus name with the bus map\n\t\t\t\tsbus->second.m_typ = MAPT_MAP;\n\t\t\t\tsbus->second.u.m_m = bi->m_hash;\n\t\t\t}\n\t\t} else\n\t\t\tgbl_msg.error(\"TAG %s does not specify a bus name\\n\",\n\t\t\t\tstrp->c_str());\n\t\tfree(cstr);\n\t} else if (sbus->second.m_typ == MAPT_MAP) {\n\t\t//\n\t\t// SLAVE.BUS.NAME = bus_name\n\t\t//\n\t\tif (NULL == (strp = getstring(*sbus->second.u.m_m, KY_NAME))) {\n\t\t\tgbl_msg.error(\"%s SLAVE.BUS \"\n\t\t\t\t\"exists, is a map, but has no name\\n\",\n\t\t\t\tpname->c_str());\n\t\t} else if (NULL == (bi = find_bus(strp))) {\n\t\t\tgbl_msg.error(\"%s SLAVE.BUS.NAME \"\n\t\t\t\t\"exists, is a map, but no there\\'s no bus named %s\\n\",\n\t\t\t\tpname->c_str(), strp->c_str());\n\t\t} else if ((bi->m_hash != sbus->second.u.m_m)\n\t\t\t\t\t&&(strp->compare(*bi->name())==0)) {\n\t\t\tbi->merge(pname, sbus->second.u.m_m);\n\t\t\tsbus->second.u.m_m = bi->m_hash;\n\t\t}\n\t} else {\n\t\tgbl_msg.error(\"%s SLAVE.BUS exists, but isn't a string!\\n\",\n\t\t\tpname->c_str());\n\t}\n}\n\nvoid\tassign_bus_master(MAPDHASH &master, MAPDHASH *bus_master) {\n\tMAPDHASH::iterator mbus;\n\tBUSINFO\t\t*bi;\n\tSTRINGP\t\tpname, strp;\n\tMAPDHASH\t*mhash;\n\n\tpname = getstring(*bus_master, KYPREFIX);\n\tif (pname == NULL)\n\t\tpname = new STRING(\"(Null)\");\n\n\tmhash = getmap(*bus_master, KYMASTER);\n\tif (NULL == mhash)\n\t\treturn;\n\n\tmbus = findkey(*mhash, KYBUS);\n\tif (mbus == mhash->end()) {\n\t\t//\n\t\t// No MASTER.BUS tag\n\t\t//\n\t} else if (mbus->second.m_typ == MAPT_STRING) {\n\t\t//\n\t\t// MASTER.BUS = bus_name\n\t\t//\n\t\tchar\t*cstr, *tok, *nxt;\n\t\tconst char\t*DELIMITERS=\", \\t\\r\\n\";\n\n\t\tstrp = mbus->second.u.m_s;\n\t\tcstr = strdup(strp->c_str());\n\n\t\t// Allow only one bus name\n\t\ttok = strtok(cstr, DELIMITERS);\n\t\tnxt = (tok) ? strtok(NULL, DELIMITERS) : NULL;\n\t\tif ((tok)&&(!nxt)) {\n\t\t\tSTRING\ttokstr = tok;\n\t\t\tbi = gbl_blist->find_bus(&tokstr);\n\t\t\tif (NULL == bi) {\n\t\t\t\tgbl_msg.error(\"BUS %s not found in %s\\n\",\n\t\t\t\t\ttok, pname->c_str());\n\t\t\t} else {\n\t\t\t\t//\n\t\t\t\t// Replace the bus name with the bus hash\n\t\t\t\tmbus->second.m_typ = MAPT_MAP;\n\t\t\t\tmbus->second.u.m_m = bi->m_hash;\n\t\t\t}\n\t\t\treeval(master);\n\t\t} free(cstr);\n\t} else if (mbus->second.m_typ == MAPT_MAP) {\n\t\t//\n\t\t// MASTER.BUS.NAME = bus_name\n\t\tif (NULL == (strp = getstring(*mbus->second.u.m_m, KY_NAME))) {\n\t\t\tgbl_msg.error(\"%s MASTER.BUS \"\n\t\t\t\t\"exists, is a map, but has no name\\n\",\n\t\t\t\tpname->c_str());\n\t\t} else if (NULL == (bi = find_bus(strp))) {\n\t\t\tgbl_msg.error(\"%s MASTER.BUS.NAME \"\n\t\t\t\t\"exists, is a map, but there\\'s no bus named %s\\n\",\n\t\t\t\tpname->c_str(), strp->c_str());\n\t\t} else if ((bi->m_hash != mbus->second.u.m_m)\n\t\t\t\t\t&&(strp->compare(*bi->name())==0)) {\n\t\t\tbi->merge(pname, mbus->second.u.m_m);\n\t\t\tmbus->second.u.m_m = bi->m_hash;\n\t\t}\n\t} else {\n\t\tgbl_msg.error(\"%s MASTER.BUS exists, but isn't a string!\\n\",\n\t\t\tpname->c_str());\n\t}\n}\n\nGENBUS *BUSINFO::generator(void) {\n\tbool\tfound= false;\n\n\tif (NULL == m_genbus) {\n\t\tfor(unsigned tst=0; tst<num_bus_classes; tst++) {\n\t\t\tif (busclass_list[tst]->matches(this)) {\n\t\t\t\tfound = true;\n\t\t\t\tm_genbus = busclass_list[tst]->create(this);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t} if (!found) {\n\t\t\tgbl_msg.fatal(\"No bus logic generator found for bus %s \"\n\t\t\t\t\"of type %s\\n\", name()->c_str(),\n\t\t\t\tgetstring(m_hash, KY_TYPE)\n\t\t\t\t\t? getstring(m_hash, KY_TYPE)->c_str()\n\t\t\t\t\t: \"(None)\");\n\t\t}\n\t}\n\n\treturn m_genbus;\n}\n\nvoid\tBUSLIST::assign_bus_types(void) {\n\tif (num_bus_classes == 0)\n\t\tgbl_msg.warning(\"No bus classes defined!\\n\");\n\tfor(unsigned k = 0; k < size(); k++) {\n\t\tbool\tfound= false;\n\t\tfor(unsigned tst=0; tst<num_bus_classes; tst++) {\n// printf(\"Looking for a bus generator for %s\\n\", (*this)[k]->m_name->c_str());\n\t\t\tif (busclass_list[tst]->matches((*this)[k])) {\n\t\t\t\tfound = true;\n\t\t\t\t(*this)[k]->generator(); // = busclass_list[tst]->create((*this)[k]);\n\t\t\t\tbreak;\n\t\t\t}\n// printf(\"No match to class, %s %s\\n\", (*this)[k]->m_name->c_str(), busclass_list[tst]->name()->c_str());\n\t\t} if (!found) {\n\t\t\tgbl_msg.error(\"No bus logic generator found for bus %s\\n\", (*this)[k]->name()->c_str());\n\t\t}\n\t}\n}\n\nvoid\tBUSLIST::checkforbusdefns(STRINGP prefix, MAPDHASH *map, const STRING &key) {\n\tMAPDHASH::iterator\tbusp;\n\tSTRINGP\t\t\tbname;\n\tBUSINFO\t\t\t*bi;\n\n\tif (map->end() != (busp = findkey(*map, key))) {\n\t\tif (busp->second.m_typ == MAPT_MAP) {\n\t\t\taddbus(prefix, busp->second.u.m_m);\n\t\t\tbname = getstring(busp->second.u.m_m, KY_NAME);\n\t\t\tif (bname == NULL) {\n\t\t\t\tgbl_msg.error(\"Bus tag in %s without a bus name\\n\",\n\t\t\t\t\t(prefix) ? prefix->c_str() : \"(No name)\");\n\t\t\t\treturn;\n\t\t\t} bi = find_bus(bname);\n\t\t\tif (bi == NULL) {\n\t\t\t\tgbl_msg.error(\"Just created bus %s, and can\\'t find it now\\n\",\n\t\t\t\t\tbname->c_str());\n\t\t\t}\n\t\t\tbusp->second.u.m_m = bi->m_hash;\n\t\t} else if (busp->second.m_typ == MAPT_STRING) {\n\t\t\taddbus(prefix, busp->second.u.m_s);\n\t\t\tbusp->second.m_typ = MAPT_MAP;\n\t\t\tbusp->second.u.m_m = find_bus(busp->second.u.m_s)->m_hash;\n\t\t\tassert(busp->second.u.m_m);\n\t\t}\n\t}\n}\n\nbool\tgbl_ready_for_address_assignment = false;\nvoid\tbuild_bus_list(MAPDHASH &master) {\n\tMAPDHASH::iterator\tkvpair, kvaccess, kvsearch;\n\tBUSLIST\t*bl = new BUSLIST;\n\tSTRINGP\tstr;\n\n\tgbl_blist = bl;\n\n\tgbl_msg.info(\"------------ BUILD-BUS-LIST------------\\n\");\n\n\n\tif (NULL != (str = getstring(master, KYDEFAULT_BUS))) {\n\t\tbl->adddefault(master, str);\n\t}\n\n\t//\n\tif (refbus(master)) {\n\t\tSTRING\tcname = \"toplevel\";\n\t\tMAPDHASH\t*mp;\n\n\t\tgbl_msg.info(\"Adding a refbus (master)\\n\");\n\t\tif (NULL != (mp = getmap(*kvpair->second.u.m_m, KYBUS)))\n\t\t\tbl->addbus(&cname, mp);\n\t}\n\t//\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tSTRINGP\t\t\tprefix;\n\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tprefix = getstring(kvpair->second.u.m_m, KYPREFIX);\n\t\t//\n\t\t// First check for any of the three possible bus maps\n\t\t//\n\t\tbl->checkforbusdefns(prefix, kvpair->second.u.m_m, KYBUS);\n\t\tbl->checkforbusdefns(prefix, kvpair->second.u.m_m, KYSLAVE_BUS);\n\t\tbl->checkforbusdefns(prefix, kvpair->second.u.m_m, KYMASTER_BUS);\n\t}\n\n\t// Make certain every bus has an appropriate logic generator\n\tfor(unsigned k=0; k<bl->size(); k++)\n\t\t(*bl)[k]->generator();\n\n\t// Let's now go back through our components, and create a SLAVE.BUS\n\t// and (possibly) a MASTER.BUS tags for each component.\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tif (isbusmaster(kvpair->second)) {\n\t\t\tassign_bus_master(master, kvpair->second.u.m_m);\n\t\t} if (isperipheral(kvpair->second)) {\n\t\t\tassign_bus_slave(master, kvpair->second.u.m_m);\n\t\t}\n\t}\n\n\treeval(master);\n\n\t// Set any unset clocks to the default\n\tfor(BUSLIST::iterator bp=bl->begin(); bp != bl->end(); bp++) {\n\t\tif (NULL == (*bp)->m_clock) {\n\t\t\tMAPDHASH\t*map;\n\t\t\tif (NULL != (str = getstring((*bp)->m_hash, KYCLOCK))) {\n\t\t\t\t(*bp)->m_clock = getclockinfo(str);\n\t\t\t\tMAPDHASH::iterator kvclock;\n\t\t\t\tkvclock = findkey(*(*bp)->m_hash, KYCLOCK);\n\t\t\t\tassert((*bp)->m_hash->end() != kvclock);\n\t\t\t\tkvclock->second.m_typ = MAPT_MAP;\n\t\t\t\tkvclock->second.u.m_m = (*bp)->m_clock->m_hash;\n\t\t\t} else if (NULL != (map = getmap((*bp)->m_hash, KYCLOCK))) {\n\t\t\t\t(*bp)->m_clock = getclockinfo(getstring(map, KY_NAME));\n\t\t\t\tMAPDHASH::iterator kvclock;\n\t\t\t\tkvclock = findkey(*(*bp)->m_hash, KYCLOCK);\n\t\t\t\tassert((*bp)->m_hash->end() != kvclock);\n\t\t\t\tkvclock->second.m_typ = MAPT_MAP;\n\t\t\t\tkvclock->second.u.m_m = (*bp)->m_clock->m_hash;\n\t\t\t} else {\n\t\t\t\tgbl_msg.fatal(\"Bus %s has no defined clock\\n\",\n\t\t\t\t\t(*bp)->name()->c_str());\n\t\t\t\t(*bp)->m_clock = getclockinfo(NULL);\n\t\t\t\tassert((*bp)->m_hash);\n\t\t\t\tsetstring((*bp)->m_hash, KYCLOCK, (*bp)->m_clock->m_name);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor(BUSLIST::iterator bp=bl->begin(); bp != bl->end(); bp++)\n\t\t(*bp)->integrity_check();\n\n\t//\n\t//\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (isperipheral(kvpair->second))\n\t\t\tbl->addperipheral(kvpair->second);\n\t\tif (isbusmaster(kvpair->second))\n\t\t\tbl->addmaster(kvpair->second);\n\t}\n\treeval(master);\n\n\tbl->assign_bus_types();\n\n\tgbl_ready_for_address_assignment = true;\n\tfor(unsigned i=0; i< bl->size(); i++) {\n\t\t(*bl)[i]->assign_addresses();\n\t\treeval(master);\n\t}\n\n\treeval(master);\n}\n\n// #define\tDUMP_BUS_TREE\n#ifdef\tDUMP_BUS_TREE\nvoid\tBUSINFO::dump_bus_tree(int tab=0) {\n\n\tgbl_msg.info(\"%*sDUMP BUS-TREE: %s\\n\",\n\t\ttab, \"\", b_name->c_str());\n\n\tfor(m_plist::iterator pp=m_plist->begin(); pp != m_plist->end(); pp++) {\n\t\tgbl_msg.info(\"%*s%s\\n\", tab+1, \"\", (*pp)->p_name->c_str());\n\t\tif (issubbus((*pp)->p_phash))\n\t\t\t(*pp)->p_master_bus->dump_bus_tree(tab+1);\n\t}\n}\n\nvoid\tdump_global_buslist(void) {\n\tfind_bus(0)->dump_bus_tree(0);\n}\n#endif\n"
  },
  {
    "path": "sw/businfo.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/businfo.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\t\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tBUSINFO_H\n#define\tBUSINFO_H\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n\nclass\tBUSINFO;\nclass\tGENBUS;\n\n#include \"parser.h\"\n#include \"mapdhash.h\"\n#include \"plist.h\"\n#include \"mlist.h\"\n#include \"clockinfo.h\"\n#include \"keys.h\"\n#include \"bitlib.h\"\n\n#include \"genbus.h\"\n\nclass\tBUSINFO {\n\tGENBUS\t*m_genbus;\t// Bus logic generator\n\tint\tm_nullsz;\n\tSTRINGP\tm_name;\npublic:\n\n\t// List of peripherals on the bus\n\tPLISTP    m_plist;\n\t// List of bus masters\n\tMLISTP\t\tm_mlist;\n\t//\n\tSTRINGP   m_type;\n\tCLOCKINFO *m_clock; // , *m_bhash;\n\tMAPDHASH\t*m_hash;\n\tint\tm_data_width, m_address_width;\n\tbool\tm_addresses_assigned;\n\n\tBUSINFO(void) { // MAPDHASH *hash)\n\t\t// m_bhash  = hash;\n\t\tm_plist  = NULL;\n\t\tm_mlist  = NULL;\n\t\tm_name   = NULL;\n\t\tm_type   = NULL;\n\t\tm_clock  = NULL;\n\t\tm_hash   = NULL;\n\t\tm_genbus = NULL;\n\t\tm_nullsz = 0;\n\t\tm_data_width = 0;\n\t\tm_addresses_assigned = false;\n\t\tm_address_width = 0;\n\t}\n\n\tBUSINFO(STRINGP name) {\n\t\tm_plist  = NULL;\n\t\tm_mlist  = NULL;\n\t\tm_name   = name;\n\t\tm_type   = NULL;\n\t\tm_clock  = NULL;\n\t\tm_hash   = new MAPDHASH();\n\t\tm_genbus = NULL;\n\t\tm_nullsz = 0;\n\t\tm_data_width = 0;\n\t\tm_addresses_assigned = false;\n\t\tm_address_width = 0;\n\n\t\tsetstring(m_hash, KY_NAME, name);\n\t}\n\n\tbool\tneed_translator(BUSINFO *b);\n\n\tbool\tget_base_address(MAPDHASH *phash, unsigned &base);\n\tint\tword_address_width(void) {\n\t\t\tif (word_addressing())\n\t\t\t\treturn address_width();\n\t\t\telse\n\t\t\t\treturn address_width() - nextlg(data_width()/8);\n\t}\n\n\tint\tbyte_address_width(void) {\n\t\tif (word_addressing())\n\t\t\treturn address_width() + nextlg(data_width()/8);\n\t\telse\n\t\t\treturn address_width();\n\t}\n\n\tbool\tword_addressing(void);\n\tvoid\tassign_addresses(void);\n\tint\taddress_width(void);\n\tint\tdata_width(void);\n\tvoid\tadd(void);\n\tPERIPH *add(PERIPHP p);\n\tPERIPH *add(MAPDHASH *phash);\n\tvoid\taddmaster(MAPDHASH *hash) {\n\t\tif (!m_mlist)\n\t\t\tm_mlist = new MLIST();\n\t\tBMASTERP bp = new BMASTER(hash);\n\t\tm_mlist->push_back(bp);\n\t}\n\n\tvoid\twriteout_bus_slave_defns_v(FILE *fp);\n\tvoid\twriteout_bus_master_defns_v(FILE *fp);\n\tvoid\twriteout_bus_defns_v(FILE *fp);\n\tvoid\twriteout_bus_logic_v(FILE *fp);\n\n\tvoid\twriteout_no_slave_v(FILE *fp, STRINGP prefix);\n\tvoid\twriteout_no_master_v(FILE *fp);\n\n\tPERIPHP operator[](unsigned i);\n\tunsigned size(void);\n\tvoid\tinit(MAPDHASH *phash);\n\tvoid\tinit(STRINGP bname);\n\tvoid\tmerge(STRINGP component, MAPDHASH *hash);\n\tvoid\tintegrity_check(void);\n\tbool\tismember_of(MAPDHASH *phash);\n\tSTRINGP\tname(void);\n\tSTRINGP\tprefix(STRINGP p = NULL);\n\tSTRINGP\tbtype(void);\n\tSTRINGP\treset_wire(void);\n\tSTRINGP\tslave_iansi(PERIPHP);\n\tSTRINGP\tslave_oansi(PERIPHP);\n\tSTRINGP\tslave_ansprefix(PERIPHP);\n\tSTRINGP\tslave_portlist(PERIPHP);\n\tSTRINGP\tslave_ansi_portlist(PERIPHP);\n\tSTRINGP\tmaster_portlist(BMASTERP);\n\tSTRINGP\tmaster_ansi_portlist(BMASTERP);\n\tGENBUS\t*generator(void);\t// Bus logic generator\n};\n\nclass\tBUSLIST : public std::vector<BUSINFO *>\t{\npublic:\n\tBUSINFO *find_bus(STRINGP name);\n\tBUSINFO *find_bus(MAPDHASH *hash);\n\tunsigned\tget_base_address(MAPDHASH *phash);\n\tvoid\taddperipheral(MAPDHASH *phash);\n\tvoid\taddperipheral(MAPT &map);\n\tvoid\taddmaster(MAPDHASH *phash);\n\tvoid\taddmaster(MAPT &map);\n\n\tvoid\tadddefault(MAPDHASH &master, STRINGP defname);\n\n\tBUSINFO *newbus_aux(STRINGP cname, MAPDHASH *bp);\n\tBUSINFO *newbus_aux(STRINGP cname, STRINGP bn);\n\tvoid\taddbus(STRINGP cname, STRINGP busname);\n\tvoid\taddbus(STRINGP cname, MAPDHASH *phash);\n\tvoid\taddbus(STRINGP cname, MAPT &map);\n\t// void\tcountsio(MAPDHASH *phash);\n\t// void\tcountsio(MAPT &map);\n\tBUSINFO *find_bus_of_peripheral(MAPDHASH *phash);\n\tvoid\tassign_bus_types(void);\n\tvoid\tcheckforbusdefns(STRINGP, MAPDHASH *, const STRING &);\n};\n\nextern\tvoid\tbuild_bus_list(MAPDHASH &master);\nextern\tBUSINFO *find_bus_of_peripheral(MAPDHASH *phash);\nextern\tBUSINFO *find_bus(MAPDHASH *hash);\nextern\tBUSINFO *find_bus(STRINGP name);\nextern\tbool\tneed_translator(BUSINFO *a, BUSINFO *b);\nextern\tvoid\twriteout_bus_defns_v(FILE *fp);\nextern\tvoid\twriteout_bus_select_v(FILE *fp);\nextern\tvoid\twriteout_bus_logic_v(FILE *fp);\n\n#endif\t// BUSINFO_H\n"
  },
  {
    "path": "sw/clockinfo.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/clockinfo.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tCaptures the information associated with a clock in a fashion\n//\t\tthat can cross the entire design.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdio.h>\n#include <stdlib.h>\n#include <vector>\n#include \"parser.h\"\n#include \"mapdhash.h\"\n#include \"keys.h\"\n#include \"bldtestb.h\"\n#include \"legalnotice.h\"\n#include \"clockinfo.h\"\n#include \"globals.h\"\n#include \"msgs.h\"\n\nconst\tunsigned long\tCLOCKINFO::UNKNOWN_PS = 2ul;\nconst\tunsigned long\tCLOCKINFO::PICOSECONDS_PER_SECOND = 1000000000000ul;\n\nCLKLIST\tcklist;\n\nCLOCKINFO::CLOCKINFO(void) {\n\tm_hash  = new MAPDHASH();\n\tm_name  = NULL;\n\tm_reset = NULL;\n\tm_wire  = NULL;\n\tm_top   = NULL;\n\tm_simclass = NULL;\n\tm_interval_ps = UNKNOWN_PS;\n}\n\nCLOCKINFO *CLOCKINFO::new_clock(STRINGP name) {\n\tCLOCKINFO *ci;\n\tif (NULL != (ci = getclockinfo(name)))\n\t\treturn ci;\n\n\tunsigned\tid = cklist.size();\n\tcklist.push_back(CLOCKINFO());\n\tci = &cklist[id];\n\tci->setname(new STRING(*name));\n\n\treturn\tci;\n}\n\nunsigned long CLOCKINFO::setfrequency(unsigned long frequency_hz) {\n\n\tif (frequency_hz != 0l) {\n\t\tunsigned long ps;\n\n\t\tsetvalue(*m_hash, KY_FREQUENCY, (int)frequency_hz);\n\t\tps = PICOSECONDS_PER_SECOND / (unsigned long)frequency_hz;\n\t\tm_interval_ps = ps;\n\t\treturn m_interval_ps;\n\t} else if (m_interval_ps != UNKNOWN_PS)\n\t\treturn m_interval_ps;\n\treturn 0l;\n}\n\nunsigned\tCLOCKINFO::frequency(void) {\n\tdouble\tv = 1e12 / m_interval_ps;\n\treturn (unsigned)v;\n}\n\nvoid\tCLOCKINFO::setname(STRINGP name) {\n\tSTRINGP\tstrp;\n\n\tstrp = getstring(*m_hash, KY_NAME);\n\tif (NULL == strp) {\n\t\tsetstring(*m_hash, KY_NAME, name);\n\t\tm_name = name;\n\t} else if (strp->compare(*name) != 0) {\n\t\tfprintf(stderr, \"ERR: Clock with multiple names: %s and %s\\n\",\n\t\t\tstrp->c_str(), name->c_str());\n\t\tm_name = strp;\n\t} else if (!m_name)\n\t\tm_name = name;\n}\n\nSTRINGP\tCLOCKINFO::reset(void) {\n\tSTRINGP\tstrp;\n\n\tstrp = getstring(*m_hash, KY_RESET);\n\treturn strp;\n}\n\nvoid\tCLOCKINFO::setwire(STRINGP wire) {\n\tSTRINGP\tstrp;\n\n\tstrp = getstring(*m_hash, KY_WIRE);\n\tif (NULL == strp) {\n\t\tsetstring(*m_hash, KY_WIRE, wire);\n\t\tm_wire = wire;\n\t} else if (strp->compare(*wire) != 0) {\n\t\tfprintf(stderr, \"ERR: Clock with multiple wire ID\\'s: %s and %s\\n\",\n\t\t\tstrp->c_str(), wire->c_str());\n\t\tm_wire = strp;\n\t} else if (!m_wire) {\n\t\t// Case #3: This is a new WIRE tag\n\t\tMAPT\tsubfm;\n\n\t\tsubfm.m_typ = MAPT_STRING;\n\t\tsubfm.u.m_s = wire;\n\t\tm_hash->insert(KEYVALUE(KY_WIRE, subfm));\n\t\tm_wire = wire;\n\t}\n}\n\nvoid\tCLOCKINFO::settop(STRINGP top) {\n\tSTRINGP\tstrp;\n\n\tstrp = getstring(*m_hash, KY_TOP);\n\tif (NULL == strp) {\n\t\t// Case #1: it's not (yet) in our hash\n\t\tsetstring(*m_hash, KY_TOP, top);\n\t\tm_top = top;\n\t} else if (strp->compare(*top) != 0) {\n\t\t// Case #2: it's in the has, but conflicts\n\t\tfprintf(stderr, \"ERR: Clock with multiple top-level wire ID\\'s: %s and %s\\n\",\n\t\t\tstrp->c_str(), top->c_str());\n\t\tm_top = strp;\n\t} else if (!m_top) {\n\t\t// Case #3: This is a new TOP tag\n\t\tMAPT\tsubfm;\n\n\t\tsubfm.m_typ = MAPT_STRING;\n\t\tsubfm.u.m_s = top;\n\t\tm_hash->insert(KEYVALUE(KY_TOP, subfm));\n\t\tm_top = top;\n\t}\n}\n\nvoid\tCLOCKINFO::setclass(STRINGP simclass) {\n\tSTRINGP\tstrp;\n\n\tstrp = getstring(*m_hash, KY_CLASS);\n\tif (NULL == strp) {\n\t\tsetstring(*m_hash, KY_CLASS, simclass);\n\t\tm_simclass = simclass;\n\t} else if (strp->compare(*simclass) != 0) {\n\t\tfprintf(stderr, \"ERR: Clock with multiple simulation classes: %s and %s\\n\",\n\t\t\tstrp->c_str(), simclass->c_str());\n\t\tm_simclass = strp;\n\t} else if (!m_simclass) {\n\t\t// Case #3: This is a new CLASS tag\n\t\tm_simclass = simclass;\n\t\tMAPT\tsubfm;\n\n\t\tsubfm.m_typ = MAPT_STRING;\n\t\tsubfm.u.m_s = simclass;\n\t\tm_hash->insert(KEYVALUE(KY_CLASS, subfm));\n\t\tm_simclass = simclass;\n\t}\n}\n\nvoid\tCLOCKINFO::setreset(STRINGP ckreset) {\n\tSTRINGP\tstrp;\n\n\tstrp = getstring(*m_hash, KY_RESET);\n\tif (NULL == strp) {\n\t\tsetstring(*m_hash, KY_RESET, ckreset);\n\t\tm_reset = ckreset;\n\t} else if (strp->compare(*ckreset) != 0) {\n\t\tfprintf(stderr, \"ERR: Clock with multiple reset wires: %s and %s\\n\",\n\t\t\tstrp->c_str(), ckreset->c_str());\n\t\tm_reset = strp;\n\t} else if (!m_reset) {\n\t\t// Case #3: This is a new RESET tag\n\t\tm_reset = ckreset;\n\t\tMAPT\tsubfm;\n\n\t\tsubfm.m_typ = MAPT_STRING;\n\t\tsubfm.u.m_s = ckreset;\n\t\tm_hash->insert(KEYVALUE(KY_RESET, subfm));\n\t\tm_reset = ckreset;\n\t}\n}\n\nvoid\tadd_to_clklist(MAPDHASH *ckmap) {\n\tconst\tchar\tDELIMITERS[] = \" \\t\\n,\";\n\tint\tifreq;\n\n\tSTRINGP\tsname, swire, sfreq, simclass, stop, sreset;\n\tchar\t*dname, *dwire, *dfreq, *dsimclass, *dtop, *dreset;\n\tchar\t*pname, *pwire, *pfreq, *psimclass, *ptop, *preset;\n\tchar\t*tname, *twire, *tfreq, *tsimclass, *ttop, *treset;\n\n\tsname    = getstring(*ckmap, KY_NAME);\n\tswire    = getstring(*ckmap, KY_WIRE);\n\tsimclass = getstring(*ckmap, KY_CLASS);\n\tstop     = getstring(*ckmap, KY_TOP);\n\tsreset   = getstring(*ckmap, KY_RESET);\n\n\t// strtok requires a writable string\n\tif (sname) dname = strdup(sname->c_str());\n\telse\t  dname = NULL;\n\tif (swire) dwire = strdup(swire->c_str());\n\telse\t  dwire = NULL;\n\tif (simclass) dsimclass = strdup(simclass->c_str());\n\telse\t  dsimclass = NULL;\n\tif (stop) dtop = strdup(stop->c_str());\n\telse\t  dtop = NULL;\n\tif (sreset) dreset = strdup(sreset->c_str());\n\telse\t  dreset = NULL;\n\n\t{\n\t\tMAPDHASH::iterator\tkvfreq;\n\n\t\tsfreq = NULL;\n\t\tdfreq = NULL;\n\t\tifreq = 0;\n\n\t\tkvfreq = findkey(*ckmap, KY_FREQUENCY);\n\t\tif (kvfreq != ckmap->end()) switch(kvfreq->second.m_typ) {\n\t\tcase MAPT_STRING:\n\t\t\tsfreq = kvfreq->second.u.m_s;\n\t\t\tdfreq = strdup(sfreq->c_str());\n\t\t\tbreak;\n\t\tcase MAPT_INT: case MAPT_AST: case MAPT_MAP:\n\t\tdefault:\n\t\t\tif (!getvalue(*ckmap, KY_FREQUENCY, ifreq)) {\n\t\t\t\tgbl_msg.error(\"Could not evaluate the \"\n\t\t\t\t\t\"frequency of clock %s\\n\",\n\t\t\t\t\t(sname)?(sname->c_str())\n\t\t\t\t\t\t: \"(Unnamed-clock)\");\n\t\t\t} break;\n\t\t}\n\t}\n\n\tpname = (dname) ? strtok_r(dname, DELIMITERS, &tname) : NULL;\n\tpwire = (dwire) ? strtok_r(dwire, DELIMITERS, &twire) : NULL;\n\tpfreq = (dfreq) ? strtok_r(dfreq, DELIMITERS, &tfreq) : NULL;\n\tptop  = (dtop ) ? strtok_r(dtop , DELIMITERS, &ttop) : NULL;\n\tpsimclass = (dsimclass) ? strtok_r(dsimclass, DELIMITERS, &tsimclass) : NULL;\n\tpreset = (dreset) ? strtok_r(dreset, DELIMITERS, &treset) : NULL;\n\n\tif (!pname)\n\t\tfprintf(stderr, \"ERR: CLOCK has no name!\\n\");\n\t// if ((!pfreq)&&(ifreq == 0))\n\t\t// fprintf(stderr, \"ERR: CLOCK has no frequency\\n\");\n\n\twhile(pname) {\n\t\tunsigned\tid = cklist.size();\n\t\tunsigned long\tclocks_per_second;\n\t\tSTRINGP\t\twname;\n\t\tbool\t\talready_defined = false;\n\n\t\tgbl_msg.info(\"Examining clock: %s %s %s %s\\n\",\n\t\t\t\tpname, (pwire)?pwire:\"(Unspec)\",\n\t\t\t\t(pfreq)?pfreq:\"(Unspec)\",\n\t\t\t\t(ptop)?ptop:\"(Unspec)\");\n\n\t\tfor(unsigned i=0; i<id; i++) {\n\t\t\tif (cklist[i].m_name->compare(pname)==0) {\n\t\t\t\t//\n\t\t\t\t// Update an existing clocks information\n\t\t\t\t//\n\t\t\t\talready_defined = true;\n\t\t\t\tgbl_msg.info(\"Clock %s is already defined: %s %ld\\n\",\n\t\t\t\t\t\tcklist[i].m_name->c_str(),\n\t\t\t\t\t\t(cklist[i].m_wire)\n\t\t\t\t\t\t  ? cklist[i].m_wire->c_str()\n\t\t\t\t\t\t  : \"(Unspec)\",\n\t\t\t\t\t\tcklist[i].m_interval_ps);\n\n\t\t\t\t//\n\t\t\t\t// Clock's wire name, such as i_clk\n\t\t\t\t//\n\t\t\t\tif ((pwire)&&(cklist[i].m_wire == NULL)) {\n\t\t\t\t\tcklist[i].m_wire = new STRING(pwire);\n\t\t\t\t\tgbl_msg.info(\"Clock %s\\'s wire set to %s\\n\", pname, pwire);\n\t\t\t\t} else if ((pwire)&&(cklist[i].m_wire->compare(pwire) != 0)) {\n\t\t\t\t\tgbl_msg.error(\"Clock %s has a conflicting wire definition: %s and %s\\n\", pname, pwire, cklist[i].m_wire->c_str());\n\t\t\t\t}\n\n\t\t\t\t//\n\t\t\t\t// Name of the top level incoming port, if\n\t\t\t\t// present\n\t\t\t\t//\n\t\t\t\tif ((ptop)&&(cklist[i].m_top == NULL)) {\n\t\t\t\t\tcklist[i].settop(new STRING(ptop));\n\t\t\t\t\tgbl_msg.info(\"Clock\\'s %s top-level wire set to %s\\n\", pname, ptop);\n\t\t\t\t} else if ((ptop)&&(cklist[i].m_top->compare(ptop) != 0)) {\n\t\t\t\t\tgbl_msg.error(\"Clock %s has a conflicting toplevel wire definition: %s and %s\\n\", pname, ptop, cklist[i].m_top->c_str());\n\t\t\t\t}\n\n\n\t\t\t\t//\n\t\t\t\t// Name of the simulation class, if present\n\t\t\t\t//\n\t\t\t\tif ((psimclass)&&(cklist[i].m_simclass == NULL)) {\n\t\t\t\t\tcklist[i].setclass(new STRING(psimclass));\n\t\t\t\t\tgbl_msg.info(\"Clock %s\\'s simulation class set to %s\\n\", pname, psimclass);\n\t\t\t\t} else if ((psimclass)&&(cklist[i].m_simclass->compare(psimclass) != 0)) {\n\t\t\t\t\tgbl_msg.error(\"Clock %s has a conflicting simulation class definition: %s and %s\\n\", pname, psimclass, cklist[i].m_simclass->c_str());\n\t\t\t\t}\n\n\t\t\t\t//\n\t\t\t\t// Name of the associated reset wire, if any\n\t\t\t\t//\n\t\t\t\tif (preset) {\n\t\t\t\t\tcklist[i].setreset(new STRING(preset));\n\t\t\t\t\tgbl_msg.info(\"Clock %s\\'s associated reset wire set to %s\\n\", pname, preset);\n\t\t\t\t}\n\n\n\t\t\t\t//\n\t\t\t\t// Set the clocks frequency\n\t\t\t\t//\n\t\t\t\tif ((pfreq)&&(cklist[i].interval_ps()==CLOCKINFO::UNKNOWN_PS)) {\n\t\t\t\t\tclocks_per_second = strtoul(pfreq, NULL, 0);\n\t\t\t\t\tgbl_msg.info(\"Setting %s clock frequency to %ld\\n\", pname, clocks_per_second);\n\t\t\t\t\tcklist[i].setfrequency(\n\t\t\t\t\t\t\tclocks_per_second);\n\t\t\t\t} else if ((ifreq)&&(cklist[i].interval_ps() == CLOCKINFO::UNKNOWN_PS)) {\n\t\t\t\t\tgbl_msg.info(\"Setting %s clock frequency to %u\\n\", pname, ifreq);\n\t\t\t\t\tcklist[i].setfrequency(\n\t\t\t\t\t\t\t(unsigned long)\n\t\t\t\t\t\t\t((unsigned)ifreq));\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} if (!already_defined) {\n\t\t\tCLOCKINFO\t*cki;\n\n\t\t\tcklist.push_back(CLOCKINFO());\n\t\t\tcki = &cklist[id];\n\t\t\tcki->setname(new STRING(pname));\n\t\t\tif (pwire)\n\t\t\t\twname = new STRING(pwire);\n\t\t\telse\n\t\t\t\twname = new STRING(STRING(\"i_\")+STRING(pname));\n\t\t\tcki->setwire(wname);\n\t\t\tif (ptop)\n\t\t\t\tcki->settop(new STRING(ptop));\n\t\t\tif (psimclass)\n\t\t\t\tcki->setclass(new STRING(psimclass));\n\t\t\tif (preset) {\nfprintf(stderr, \"preset != NULL\\n\");\n\t\t\t\tcki->setreset(new STRING(preset));\n}\n\t\t\tclocks_per_second = (unsigned)ifreq;\n\t\t\tif (pfreq) {\n\t\t\t\tclocks_per_second = strtoul(pfreq, NULL, 0);\n\t\t\t\tcki->setfrequency(clocks_per_second);\n\t\t\t} else if (ifreq != 0) {\n\t\t\t\t// clocks_per_second = (unsigned)ifreq;\n\t\t\t\tcki->setfrequency(clocks_per_second);\n\t\t\t}\n\n\t\t\tSTRING\tinfostr = STRING(\"Clock: \") + STRING(pname) + STRING(\", is \") + (*wname);\n\n\t\t\tif (clocks_per_second != 0) {\n\t\t\t\tif ((clocks_per_second % 1000000) == 0) {\n\t\t\t\t\tinfostr += STRING(\" at \") + std::to_string(clocks_per_second/1000000);\n\t\t\t\t\tinfostr += \" MHz\";\n\t\t\t\t} else if ((clocks_per_second % 1000) == 0) {\n\t\t\t\t\tinfostr += STRING(\" at \") + std::to_string(clocks_per_second / 1000);\n\t\t\t\t\tinfostr += \" kHz\";\n\t\t\t\t} else {\n\t\t\t\t\tinfostr += STRING(\" at \") + std::to_string(clocks_per_second);\n\t\t\t\t\tinfostr += \" Hz\";\n\t\t\t\t}\n\t\t\t} if (NULL != cki->reset())\n\t\t\t\tinfostr += \", w/ associated reset \" + (*cki->reset());\n\t\t\tinfostr += \"\\n\";\n\t\t\tgbl_msg.userinfo(infostr.c_str());\n\t\t}\n\n\t\tif (pname) pname = strtok_r(NULL, DELIMITERS, &tname);\n\t\tif (pwire) pwire = strtok_r(NULL, DELIMITERS, &twire);\n\t\tif (pfreq) pfreq = strtok_r(NULL, DELIMITERS, &tfreq);\n\t\tif (ptop)  ptop  = strtok_r(NULL, DELIMITERS, &ttop);\n\t\tif (psimclass) psimclass = strtok_r(NULL, DELIMITERS, &tsimclass);\n\t\tif (preset) preset = strtok_r(NULL, DELIMITERS, &treset);\n\t\tifreq = 0;\n\t}\n\n\tfree(dname);\n\tfree(dwire);\n\tfree(dfreq);\n\tfree(dtop);\n\tfree(dsimclass);\n}\n\nCLOCKINFO\t*getclockinfo(STRING &clock_name) {\n\tCLKLIST::iterator\tckp;\n\n\tfor(ckp = cklist.begin(); ckp != cklist.end(); ckp++) {\n\t\tif (ckp->m_name->compare(clock_name)==0) {\n\t\t\tCLOCKINFO\t*ckresult;\n\t\t\tckresult = &(*ckp);\n\t\t\treturn ckresult;\n\t\t}\n\t} return NULL;\n}\n\nCLOCKINFO\t*getclockinfo(STRINGP clock_name) {\n\tif (!clock_name) {\n\t\t// Get the default clock\n\t\tassert(0);\n\t\tgbl_msg.fatal(\"No clock name given (might have assumed a default clock of clk)\\n\");\n\t\tSTRING\tstr(\"clk\");\n\t\treturn getclockinfo(str);\n\t}\n\treturn getclockinfo(*clock_name);\n}\n\nvoid\texpand_clock(MAPDHASH &info) {\n\tMAPDHASH::iterator\tkyclock;\n\tMAPDHASH\t*ckmap;\n\tCLOCKINFO\t*cki;\n\tSTRINGP\t\tsname;\n\n\tkyclock = findkey(info, KYCLOCK);\n\tif (info.end() == kyclock)\n\t\treturn;\n\tif (kyclock->second.m_typ != MAPT_MAP)\n\t\treturn;\n\tckmap = kyclock->second.u.m_m;\n\tsname = getstring(ckmap, KY_NAME);\n\n\tif (!sname) {\n\t\tSTRINGP ckwire;\n\t\tMAPDHASH::iterator\tkyprefix;\n\t\tkyprefix = findkey(info, KYPREFIX);\n\t\tif ((info.end() == kyprefix)\n\t\t\t\t||(kyprefix->second.m_typ != MAPT_STRING)) {\n\t\t\tgbl_msg.error(\"ERR: Clock in %s has been given no name\",\n\t\t\t\tkyprefix->second.u.m_s->c_str());\n\t\t\treturn;\n\t\t}\n\t\tckwire = getstring(ckmap, KY_WIRE);\n\t\tif (ckwire) {\n\t\t\tgbl_msg.error(\"ERR: Clock with no name, using wire named %s\\n\", ckwire->c_str());\n\t\t\treturn;\n\t\t}\n\t} assert(sname);\n\n\t// This will fail if multiple clocks are defined on the same line\n\tcki = getclockinfo(sname);\n\n\tif (cki) {\n\t\tif (cki->m_hash != kyclock->second.u.m_m)\n\t\t\tkyclock->second.u.m_m = cki->m_hash;\n\t}\n}\n\nvoid\texpand_clock(MAPT &elm) {\n\tif(elm.m_typ == MAPT_MAP)\n\t\texpand_clock(*elm.u.m_m);\n}\n\nvoid\tfind_clocks(MAPDHASH &master) {\n\tMAPDHASH\t*ckkey;\n\tMAPDHASH::iterator\tkypair;\n\n\tgbl_msg.info(\"------------ FIND-CLOCKS!! ------------\\n\");\n\n\t// If we already have at least one clock, then we must've been called\n\t// before.  Do nothing more.\n\tif (cklist.size() > 0)\n\t\treturn;\n\n\tif (NULL != (ckkey = getmap(master, KYCLOCK))) {\n\t\tadd_to_clklist(ckkey);\n\t}\n\n\tfor(kypair = master.begin(); kypair != master.end(); kypair++) {\n\t\tMAPDHASH\t*p;\n\n\t\tif (kypair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\n\t\tp = kypair->second.u.m_m;\n\t\tif (NULL != (ckkey = getmap(*p, KYCLOCK)))\n\t\t\tadd_to_clklist(ckkey);\n\t}\n\n\tCLOCKINFO\t*cki;\n\tSTRINGP\t\tsclk;\n\n\tsclk = new STRING(\"clk\");\n\tif (NULL == (cki = getclockinfo(new STRING(\"clk\")))) {\n\t\tcklist.push_back(CLOCKINFO());\n\t\t// Default clock, if not given, is 100MHz\n\t\tcklist[0].set(sclk, new STRING(\"i_clk\"), 100000000ul);\n\t} else\n\t\tdelete sclk;\n\n\texpand_clock(master);\n\tfor(kypair = master.begin(); kypair != master.end(); kypair++)\n\t\texpand_clock(kypair->second);\n\n\tfprintf(stderr, \"All clocks enumerated\\n\");\n}\n"
  },
  {
    "path": "sw/clockinfo.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/clockinfo.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tCLOCKINFO_H\n#define\tCLOCKINFO_H\n\n#include \"parser.h\"\n#include \"mapdhash.h\"\n#include \"keys.h\"\n\n\nclass\tCLOCKINFO {\nprivate:\n\tSTRINGP\t\tm_reset;\npublic:\n\tMAPDHASH\t*m_hash;\n\tunsigned long\tm_interval_ps;\n\tSTRINGP\t\tm_name, m_wire, m_top, m_simclass;\n\tstatic const unsigned long\tUNKNOWN_PS,\n\t\t\tPICOSECONDS_PER_SECOND;\n\n\tCLOCKINFO(void);\n\tstatic CLOCKINFO *new_clock(STRINGP name);\n\n\tunsigned long\tinterval_ps(void) {\n\t\treturn m_interval_ps;\n\t}\n\n\tunsigned long\tsetfrequency(const char *sfreq_hz) {\n\t\treturn setfrequency(strtoul(sfreq_hz, NULL, 0));\n\t}\n\n\tunsigned long\tsetfrequency(unsigned long frequency_hz);\n\tvoid\tsetname(STRINGP name);\n\tvoid\tsetwire(STRINGP wire);\n\tvoid\tsettop(STRINGP top);\n\tvoid\tsetclass(STRINGP simclass);\n\tvoid\tsetreset(STRINGP ckreset);\n\n\tvoid set(STRINGP name, STRINGP wire, unsigned long frequency_hz) {\n\t\tsetname(name);\n\t\tsetwire(wire);\n\t\tsetfrequency(frequency_hz);\n\t}\n\n\tvoid set(STRINGP name, STRINGP wire, char *sfreq) {\n\t\tsetname(name);\n\t\tsetwire(wire);\n\t\tsetfrequency(sfreq);\n\t}\n\n\tunsigned frequency(void);\n\tSTRINGP\treset(void);\n};\ntypedef\tstd::vector<CLOCKINFO>\tCLKLIST;\n\n\n// A list of all of the clocks found within this design\nextern\tCLKLIST\tcklist;\n\n// Search through the master hash looking for all of the clocks within it.\nextern\tCLOCKINFO\t*getclockinfo(STRING &clock_name);\nextern\tCLOCKINFO\t*getclockinfo(STRINGP clock_name);\n\n// Search through the master hash looking for all of the clocks within it.\nextern\tvoid\tfind_clocks(MAPDHASH &master);\n\n#endif\t// CLOCKINFO_H\n\n"
  },
  {
    "path": "sw/expr.l",
    "content": "/*******************************************************************************\n**\n** Filename: \texpr.l\n** {{{\n** Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n**\n** Purpose:\tThe lexical analyzer for any variable evaluations.  This\n**\t\tconverts data description input into tokens, to feed the parser.\n**\tIn general, the data description input is a single line, although it may\n**\tbe split across multiple if the computation to be accomplished is\n**\tcomplex enough.\n**\n**\n** Creator:\tDan Gisselquist, Ph.D.\n**\t\tGisselquist Technology, LLC\n**\n********************************************************************************\n** }}}\n** Copyright (C) 2017-2024, Gisselquist Technology, LLC\n** {{{\n** This program is free software (firmware): you can redistribute it and/or\n** modify it under the terms of the GNU General Public License as published\n** by the Free Software Foundation, either version 3 of the License, or (at\n** your option) any later version.\n**\n** This program is distributed in the hope that it will be useful, but WITHOUT\n** ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n** FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n** for more details.\n**\n** You should have received a copy of the GNU General Public License along\n** with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n** target there if the PDF file isn't present.)  If not, see\n** <http://www.gnu.org/licenses/> for a copy.\n** }}}\n** License:\tGPL, v3, as defined and found on www.gnu.org,\n** {{{\n**\t\thttp://www.gnu.org/licenses/gpl.html\n**\n********************************************************************************\n** }}}\n**/\n\n%{\n#include <stdio.h>\n#include \"parser.h\"\n#include \"expr.tab.h\"\n\nextern \"C\" int yylex();\nextern \"C\" int\tyywrap() { return 1;}\n%}\n\n%%\n[@]?[$]?[/.^+]?[_A-Za-z][._a-zA-Z0-9]*  {\n\t\tif (yytext[0] == '@') {\n\t\t\tif (yytext[1]=='$')\n\t\t\t\tyylval.u_id = strdup(yytext+2);\n\t\t\telse\n\t\t\t\tyylval.u_id = strdup(yytext+1);\n\t\t} else\n\t\t\tyylval.u_id  = strdup(yytext);\n\t\treturn IDENTIFIER;\n\t}\n@[$]?\\([/.^+]?[_A-Za-z][._a-zA-Z0-9]*\\)  {\n\t\tif (yytext[1]=='$')\n\t\t\tyylval.u_id = strdup(yytext+3);\n\t\telse\n\t\t\tyylval.u_id = strdup(yytext+2);\n\t\t// Remove the trailing parenthesis\n\t\tyylval.u_id[strlen(yylval.u_id)-1]='\\0';\n\t\treturn IDENTIFIER;\n\t}\n0[xX][0-9A-Fa-f]+   { yylval.u_ival = strtoul(yytext,NULL,16);return INT;}\n0[0-7]+\t\t{ yylval.u_ival = strtoul(yytext,NULL, 8);return INT;}\n[1-9][0-9]*\t  \t{ yylval.u_ival = strtoul(yytext,NULL,10);return INT;}\n\"0\"\t\t{ yylval.u_ival = 0;return INT;}\n\"+\"\t\t{ return PLUS; }\n\"-\"\t\t{ return MINUS; }\n\"*\"\t\t{ return TIMES; }\n\"/\"\t\t{ return DIVIDE; }\n\"<<\"\t\t{ return UPSHIFT; }\n\">>\"\t\t{ return DOWNSHIFT; }\n\"!=\"\t\t{ return LOGICAL_NEQ; }\n\"<=\"\t\t{ return LOGICAL_LTE; }\n\">=\"\t\t{ return LOGICAL_GTE; }\n\"<\"\t\t{ return LOGICAL_LT; }\n\">\"\t\t{ return LOGICAL_GT; }\n\"&&\"\t\t{ return BOOLEANAND; }\n\"||\"\t\t{ return BOOLEANOR; }\n\"==\"\t\t{ return BOOLEANEQ; }\n\"!\"\t\t{ return BOOLEANNOT; }\n\"|\"\t\t{ return BITWISEOR; }\n\"&\"\t\t{ return BITWISEAND; }\n\"^\"\t\t{ return BITWISEXOR; }\n\"~\"\t\t{ return BITWISENOT; }\n\"%\"\t\t{ return MODULO; }\n\":\"\t\t{ return COLON; }\n\"?\"\t\t{ return QUESTION; }\n[ \\t]+\t\t{ }\n[(]\t\t{ return '('; }\n[)]\t\t{ return ')'; }\n\n%%\n"
  },
  {
    "path": "sw/expr.ypp",
    "content": "/*******************************************************************************\n**\n** Filename: \texpr.ypp\n** {{{\n** Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n**\n** Purpose:\t\n**\n** Creator:\tDan Gisselquist, Ph.D.\n**\t\tGisselquist Technology, LLC\n**\n********************************************************************************\n** }}}\n** Copyright (C) 2017-2021, Gisselquist Technology, LLC\n** {{{\n** This program is free software (firmware): you can redistribute it and/or\n** modify it under the terms of the GNU General Public License as published\n** by the Free Software Foundation, either version 3 of the License, or (at\n** your option) any later version.\n**\n** This program is distributed in the hope that it will be useful, but WITHOUT\n** ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n** FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n** for more details.\n**\n** You should have received a copy of the GNU General Public License along\n** with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n** target there if the PDF file isn't present.)  If not, see\n** <http://www.gnu.org/licenses/> for a copy.\n** }}}\n** License:\tGPL, v3, as defined and found on www.gnu.org,\n** {{{\n**\t\thttp://www.gnu.org/licenses/gpl.html\n**\n**\n********************************************************************************\n** }}}\n*/\n\n%{\n #include <stdio.h>\n #include <stdlib.h>\n #include <string.h>\n #include \"parser.h\"\n #include \"ast.h\"\n\n#define\tDEFAULT_OUTPUT_FNAME\t\"z.out\"\n#define YYDEBUG 1\n\n  extern \"C\" int yylex(void);\n  extern \"C\" int yyparse(void);\n  // extern \"C\" FILE *yyin;\n  void yyerror(const char *);\n\n  static AST *toplevel_ast;\n%}\n\n%token PLUS MINUS TIMES DIVIDE MODULO\n%token UPSHIFT DOWNSHIFT\n%token BITWISEOR BITWISEAND BITWISEXOR BITWISENOT\n%token BOOLEANOR BOOLEANAND BOOLEANEQ BOOLEANNOT\n%token LOGICAL_NEQ LOGICAL_LT LOGICAL_LTE\n%token LOGICAL_GT LOGICAL_GTE\n%token COLON QUESTION\n%token IDENTIFIER INT\n\n%union {\n\tlong\t\t\tu_ival;\n\tchar\t\t\t*u_id;\n\tAST\t\t\t*u_ast;\n}\n\n%type\t<u_ival>\tINT\n%type\t<u_id>\t\tIDENTIFIER\n%type\t<u_ast>\t\texpr value\n\n%left QUESTION COLON\n%left BOOLEANOR\n%left BOOLEANAND\n%left BOOLEANEQ\n%left BOOLEANNOT\n%left UPSHIFT DOWNSHIFT\n%left LOGICAL_LT LOGICAL_GT LOGICAL_LTE LOGICAL_GTE\n%left LOGICAL_EQ LOGICAL_NEQ\n%left BITWISEOR BITWISEXOR\n%left BITWISEAND\n%left BITWISENOT\n%left MODULO\n%left PLUS MINUS\n%left TIMES DIVIDE\n\n%% /* The grammar follows */\n\ninput:\n  %empty\n| expr { toplevel_ast = $1; }\n;\n\nexpr:\n\tvalue\t\t\t{ $$ = $1; }\n|\tMINUS value %prec TIMES\t { $$ = new AST_BRANCH('-',new AST_NUMBER(0), $2); }\n|\texpr PLUS expr\t\t{ $$ = new AST_BRANCH('+',$1,$3); }\n|\texpr MINUS expr\t\t{ $$ = new AST_BRANCH('-',$1,$3); }\n|\texpr TIMES expr\t\t{ $$ = new AST_BRANCH('*',$1,$3); }\n|\texpr DIVIDE expr\t{ $$ = new AST_BRANCH('/',$1,$3); }\n|\texpr MODULO expr\t{ $$ = new AST_BRANCH('%',$1,$3); }\n|\texpr BITWISEOR expr\t{ $$ = new AST_BRANCH('|',$1,$3); }\n|\texpr BITWISEAND expr\t{ $$ = new AST_BRANCH('&',$1,$3); }\n|\texpr BITWISEXOR expr\t{ $$ = new AST_BRANCH('^',$1,$3); }\n|\texpr BITWISENOT expr\t{ $$ = new AST_BRANCH('~',$1,$3); }\n|\texpr UPSHIFT expr\t{ $$ = new AST_BRANCH('u',$1,$3); }\n|\texpr DOWNSHIFT expr\t{ $$ = new AST_BRANCH('d',$1,$3); }\n|\texpr BOOLEANOR expr\t{ $$ = new AST_BRANCH('o',$1,$3); }\n|\texpr BOOLEANAND expr\t{ $$ = new AST_BRANCH('a',$1,$3); }\n|\texpr LOGICAL_EQ expr\t{ $$ = new AST_BRANCH('e',$1,$3); }\n|\texpr LOGICAL_NEQ expr\t{ $$ = new AST_BRANCH('N',$1,$3); }\n|\texpr LOGICAL_LT expr\t{ $$ = new AST_BRANCH('L',$1,$3); }\n|\texpr LOGICAL_GT expr\t{ $$ = new AST_BRANCH('G',$1,$3); }\n|\texpr LOGICAL_LTE expr\t{ $$ = new AST_BRANCH('<',$1,$3); }\n|\texpr LOGICAL_GTE expr\t{ $$ = new AST_BRANCH('>',$1,$3); }\n|\texpr QUESTION expr COLON expr { $$ = new AST_TRIOP($1,$3,$5); }\n|\t'(' expr ')'\t\t{ $$ = $2; }\n;\n\t/* |\tBITWISENOT expr\t{ $$ = new AST_SINGLEOP('~',$2); } */\n\t/* |\tBOOLEANNOT expr\t{ $$ = new AST_SINGLEOP('!',$2); } */\n\nvalue:\n\tINT\t{ $$ = new AST_NUMBER($1); }\n| IDENTIFIER\t{ $$ = new AST_IDENTIFIER($1); }\n;\n%%\n\n#include <unistd.h>\n#include <sys/types.h>\n#include <sys/wait.h>\n#include <sys/stat.h>\n#include <sys/fcntl.h>\n#include <assert.h>\n#include <string>\n//\n#include \"lex.yy.h\"\n\nstatic\tchar\t*topstr;\n\nvoid\tyyerror(const char *str) {\n\tfflush(stdout);\n\tfprintf(stderr, \"EXPR ERR: %s\\n\", str);\n\tfprintf(stderr, \"ERR: While processing \\\"%s\\\"\\n\", topstr);\n}\n\nAST\t*parse_ast(const STRING &str) {\n\tsize_t\tln = str.size() + 4;\n\tchar\t*buf = new char[ln];\n\ttopstr\t= buf;\n\n\tmemset(buf, 0, ln);\n\tstrcpy(buf, str.c_str());\n\tyy_scan_string(buf);\n\tyyparse();\n\treturn\ttoplevel_ast;\n}\n"
  },
  {
    "path": "sw/gather.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/gather.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tTo gather all peripherals together, using a given bus to do so\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <string.h>\n#include <unistd.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <limits.h>\n#include <ctype.h>\n\n#include \"parser.h\"\n#include \"keys.h\"\n#include \"kveval.h\"\n#include \"legalnotice.h\"\n#include \"plist.h\"\n#include \"bldregdefs.h\"\n#include \"businfo.h\"\n#include \"subbus.h\"\n#include \"globals.h\"\n#include \"msgs.h\"\n#include \"predicates.h\"\n\ntypedef\tstd::vector<PERIPHP>\tAPLIST;\n\nvoid\tgather_peripherals(APLIST *alist, BUSINFO *bus, PLIST *plist, unsigned base) {\n\tif (NULL == plist) {\n\t\tgbl_msg.warning(\"Sub-bus %s has no peripherals\\n\", bus->name()->c_str());\n\t\treturn;\n\t}\n\n\tfor(unsigned k=0; k<plist->size(); k++) {\n\t\tMAPDHASH\t*ph = (*plist)[k]->p_phash;\n\t\tunsigned\taddr;\n\n\t\t// unsigned base = 0;\n\t\tif (!bus->get_base_address(ph, addr))\n\t\t\taddr = 0;\n\t\talist->push_back((*plist)[k]);\n\t\tif (addr+base != 0) {\n\t\t\tsetvalue(*ph, KYREGBASE, addr+base);\n\t\t\treeval(gbl_hash);\n\t\t}\n\t\t(*plist)[k]->p_regbase = addr+base;\n\t\tif (isarbiter(*ph)) {\n\t\t\tBUSINFO\t*subbus;\n\n\t\t\tsubbus = (*plist)[k]->p_master_bus;\n\t\t\tassert(subbus);\n\n\t\t\tgather_peripherals(alist, subbus, subbus->m_plist, addr+base);\n\t\t}\n\t}\n}\n\nAPLIST\t*gather_peripherals(BUSINFO *bus) {\n\tAPLIST\t*alist = new APLIST;\n\n\tgather_peripherals(alist, bus, bus->m_plist, 0);\n\n\treturn alist;\n}\n\nAPLIST *full_gather(void) {\n\tSTRINGP\tstrp;\n\tBUSINFO\t*bi;\n\tAPLIST\t*alist;\n\n        strp = getstring(*gbl_hash, KYREGISTER_BUS_NAME);\n        if (NULL == strp) {\n\t\tgbl_msg.warning(\"No REGISTER.BUS defined, assuming a register bus of \\\"wbu\\\".\\n\");\n                strp = new STRING(\"wbu\");\n        } bi = find_bus(strp);\n        if (NULL == bi) {\n\t\tgbl_msg.warning(\"Register bus %s not found, switching to default\\n\",\n                strp->c_str());\n                bi = find_bus((STRINGP)NULL);\n        }\n        if(!bi) {\n\t\tgbl_msg.error(\"No bus found for register definitions\\n\");\n                return NULL;\n        }\n\n        // Get the list of peripherals\n        alist = gather_peripherals(bi);\n\tsort(alist->begin(), alist->end(), compare_regaddr);\n        return alist;\n}\n"
  },
  {
    "path": "sw/gather.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/gather.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tTo gather all peripherals together, using a given bus to do so\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tGATHER_H\n#define\tGATHER_H\n\n#include <vector>\n\n#include \"plist.h\"\n#include \"businfo.h\"\n\ntypedef\tstd::vector<PERIPHP>\tAPLIST;\n\nextern \tvoid\tgather_peripherals(APLIST *alist, BUSINFO *bus, PLIST *plist, unsigned base=0);\n\nextern \tAPLIST\t*gather_peripherals(BUSINFO *bus);\n\nextern\tAPLIST\t*full_gather(void);\n\n#endif\n"
  },
  {
    "path": "sw/genbus.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/genbus.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tDefines a generic bus class, from which other buses may derive.\n//\t\tMore importantly, describes a way that different potential\n//\tbus classes/implementations may be searched for an appropriate one.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include \"genbus.h\"\n#include \"bitlib.h\"\n#include \"msgs.h\"\n#include \"bus/wb.h\"\n#include \"bus/axil.h\"\n#include \"bus/axi.h\"\n#include \"keys.h\"\n#include \"mapdhash.h\"\n\nWBBUSCLASS\twbclass;\nAXILBUSCLASS\taxilclass;\nAXIBUSCLASS\taxiclass;\n\nBUSCLASS\t*busclass_list[NUM_BUS_CLASSES] = {\n\t\t&wbclass, &axilclass, &axiclass };\nunsigned\tnum_bus_classes = NUM_BUS_CLASSES;\n\n/*\nvoid\tGENBUS::integrity_check(void) {\n\tif (!m_info) {\n\t\tgbl_msg.error(\"Bus logic generator with no bus info structure\\n\");\n\t\treturn;\n\t}\n\n\tif (!m_info->m_plist)\n\t\tgbl_msg.error(\"Bus logic generator with no peripherals attached\\n\");\n\n\tif (!m_info->m_name)\n\t\tgbl_msg.error(\"Bus has no name!\\n\");\n\n\tif (!m_info->m_clock)\n\t\tgbl_msg.error(\"Bus has no assigned clock!\\n\");\n}\n*/\n\nbool\tGENBUS::bus_option(const STRING &ky) {\n\tMAPDHASH\t*option;\n\n\toption = getmap(m_info->m_hash, ky);\n\treturn\t(option != NULL);\n}\n\nvoid\tGENBUS::xbar_option(FILE *fp, const STRING &key, const char *pat, const char *def) {\n\tconst char *loc = strchr(pat, '%');\n\tSTRINGP\t\tstr;\n\tint\t\tval, prech;\n\n\tassert(loc != NULL);\n\tprech = loc-pat;\n\n\tif (!bus_option(key)) {\n\t\tif (NULL != def)\n\t\t\tfprintf(fp, \"%.*s%s%s\", prech, pat, def, loc+1);\n\t\treturn;\n\t}\n\n\tif (getvalue(*m_info->m_hash, key, val)) {\n\t\tfprintf(fp, \"%.*s%d%s\", prech, pat, val, loc+1);\n\t\treturn;\n\t}\n\n\tif (NULL != (str = getstring(*m_info->m_hash, key))) {\n\t\tfprintf(fp, \"%.*s%s%s\", prech, pat, str->c_str(), loc+1);\n\t\treturn;\n\t}\n\n\tif (NULL != def) {\n\t\tfprintf(fp, \"%.*s%s%s\", prech, pat, def, loc+1);\n\t\treturn;\n\t}\n}\n\nSTRINGP\tGENBUS::name(void) {\n\tif (m_info)\n\t\treturn m_info->name();\n\treturn NULL;\n}\n\nunsigned GENBUS::max_name_width(PLIST *pl) {\n\tunsigned\tslave_name_width = 0;\n\n\tfor(unsigned k=0; k<pl->size(); k++) {\n\t\tPERIPHP\tp = (*pl)[k];\n\t\tunsigned\tsz;\n\n\t\tsz = p->name()->size();\n\t\tif (slave_name_width < sz)\n\t\t\tslave_name_width = sz;\n\t}\n\n\treturn slave_name_width;\n}\n\n\nvoid\tGENBUS::slave_addr(FILE *fp, PLIST *pl, const int addr_lsbs) {\n\t// int\t\tlgdw = nextlg(m_info->data_width())-3;\n\tunsigned\tslave_name_width = max_name_width(pl);\n\n\tfprintf(fp,\n\t\t\"\\t\\t.SLAVE_ADDR({\\n\");\n\tfprintf(fp,\n\t\t\"\\t\\t\\t// Address width    = %d\\n\"\n\t\t\"\\t\\t\\t// Address LSBs     = %d\\n\",\n\t\taddress_width(), addr_lsbs);\n\tfor(unsigned k=pl->size()-1; k>0; k=k-1) {\n\t\tPERIPHP\tp = (*pl)[k];\n\n\t\tfprintf(fp, \"\\t\\t\\t{ %d\\'h%0*lx },\",\n\t\t\taddress_width(),\n\t\t\t(address_width()+3)/4,\n\t\t\t((*pl)[k]->p_base)>>addr_lsbs);\n\t\tfprintf(fp, \" // %*s: 0x%0*lx\\n\", slave_name_width,\n\t\t\tp->name()->c_str(),\n\t\t\t(address_width()+addr_lsbs+3)/4, p->p_base);\n\n\t} fprintf(fp, \"\\t\\t\\t{ %d\\'h%0*lx }  // %*s: 0x%0*lx\\n\",\n\t\t\taddress_width(),\n\t\t\t(address_width()+3)/4,\n\t\t\t((*pl)[0]->p_base)>>addr_lsbs,\n\t\t\tslave_name_width,\n\t\t\t(*pl)[0]->name()->c_str(),\n\t\t\t(address_width()+addr_lsbs+3)/4,\n\t\t\t(*pl)[0]->p_base);\n\tfprintf(fp, \"\\t\\t})\");\n}\n\nvoid\tGENBUS::slave_mask(FILE *fp, PLIST *pl, const int addr_lsbs) {\n\tint\t\tlgdw = 0;\n\tunsigned\tslave_name_width = max_name_width(pl);\n\n\tif (word_addressing())\n\t\tlgdw = nextlg(m_info->data_width())-3;\n\n\tfprintf(fp, \"\\t\\t.SLAVE_MASK({\\n\");\n\tfprintf(fp,\n\t\t\"\\t\\t\\t// Address width    = %d\\n\"\n\t\t\"\\t\\t\\t// Address LSBs     = %d\\n\",\n\t\taddress_width(), addr_lsbs);\n\tfor(unsigned k=pl->size()-1; k>0; k=k-1) {\n\t\tPERIPHP\tp = (*pl)[k];\n\n\t\tfprintf(fp, \"\\t\\t\\t{ %d\\'h%0*lx }, // %*s\\n\",\n\t\t\taddress_width(),\n\t\t\t(address_width()+3)/4,\n\t\t\tp->p_mask << (addr_lsbs-lgdw),\n\t\t\tslave_name_width, p->name()->c_str());\n\t} fprintf(fp, \"\\t\\t\\t{ %d\\'h%0*lx }  // %*s\\n\",\n\t\t\taddress_width(),\n\t\t\t(address_width()+3)/4,\n\t\t\t((*pl)[0]->p_mask << (lgdw - addr_lsbs)),\n\t\t\tslave_name_width, (*pl)[0]->name()->c_str());\n\tfprintf(fp, \"\\t\\t})\");\n}\n\nbool\tBUSCLASS::matches(BUSINFO *bi) {\n\tMAPDHASH *bhash = bi->m_hash;\n\tSTRINGP\tbtype;\n\n\t// Check any slaves of this bus to see if we can\n\t// handle them\n\tbtype = getstring(bhash, KY_TYPE);\n\treturn matchtype(btype);\n}\n"
  },
  {
    "path": "sw/genbus.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/genbus.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tDefines a generic bus interface which, if implemented, should\n//\t\tallow support for any bus type desired.\n//\n// Translators:\n//\tTo facilitate bus translation, every bus type is defined uniquely by\n//\tthe buses data width, type, and clock.  Data types will (eventually)\n//\tinclude: AXI, AXI-lite (or AXIL), WB, and WBC (or WB-classic).\n//\n//\tTo avoid unnecessary translation, address width properties will\n//\tpropagate up, ID width will propagate down.  All AXI slaves are required\n//\tto support an arbitrary number of AXI ID's.\n//\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tGENBUS_H\n#define\tGENBUS_H\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n\n#include \"parser.h\"\n#include \"mapdhash.h\"\n#include \"plist.h\"\n#include \"clockinfo.h\"\n#include \"businfo.h\"\n\nclass\tGENBUS {\npublic:\n\tBUSINFO\t*m_info;\t// Generic bus information\n\t// MLISTP\tm_mlist;\t// List of bus masters\n\t// PLISTP\tm_plist;\t// List of peripheral/slaves\n\n\t// GENBUS(BUSINFO *bi);\n\t// ~GENBUS() {};\n\n\tvirtual\tint\taddress_width(void) = 0;\n\tvirtual\tbool\tword_addressing(void) = 0;\n\t//\n\tvirtual\tvoid\tassign_addresses(void) = 0;\n\tvirtual\tbool\tget_base_address(MAPDHASH *phash, unsigned &base) = 0;\n\t// virtual\tunsigned size(void) { return (m_info && m_info->m_plist) ? m_info->m_plist->size() : 0; };\n\n\t// virtual\tvoid\twriteout_slave_defn_v(FILE *fp, const char *name, const char *errwire = NULL, const char *btyp=\"\") = 0;\n\tvirtual\tvoid\twriteout_bus_slave_defns_v(FILE *fp) = 0;\n\tvirtual\tvoid\twriteout_bus_master_defns_v(FILE *fp) = 0;\n\tvirtual\tvoid\twriteout_bus_defns_v(FILE *fp) {\n\t\twriteout_bus_master_defns_v(fp);\n\t\twriteout_bus_slave_defns_v(fp);\n\t}\n\n\tvirtual\tvoid\twriteout_bus_logic_v(FILE *fp) = 0;\n\n\tvirtual\tvoid\twriteout_no_slave_v(FILE *fp, STRINGP prefix) = 0;\n\tvirtual\tvoid\twriteout_no_master_v(FILE *fp) = 0;\n\n\n\tvirtual\tSTRINGP\tiansi(BMASTERP m) { return NULL; }\n\tvirtual\tSTRINGP\toansi(BMASTERP m) { return NULL; }\n\tvirtual\tSTRINGP\tmaster_ansprefix(BMASTERP m) { return NULL; }\n\tvirtual\tSTRINGP\tmaster_portlist(BMASTERP m) { return NULL; }\n\tvirtual\tSTRINGP\tmaster_ansi_portlist(BMASTERP m) { return NULL; }\n\tvirtual\tSTRINGP\tslave_ansprefix(PERIPHP p) { return NULL; }\n\tvirtual\tSTRINGP\tslave_portlist(PERIPHP p) { return NULL; }\n\tvirtual\tSTRINGP\tslave_ansi_portlist(PERIPHP p) { return NULL; }\n\t\tSTRINGP\tname(void);\n\tunsigned max_name_width(PLIST *pl);\n\tvoid\tslave_addr(FILE *fp, PLIST *pl, const int addr_lsbs = 0);\n\tvoid\tslave_mask(FILE *fp, PLIST *pl, const int addr_lsbs = 0);\n\tvirtual\tvoid\tintegrity_check(void) {};\n\tbool\tbus_option(const STRING &str);\n\tvoid\txbar_option(FILE *fp, const STRING&,\n\t\t\tconst char *,const char *d=NULL);\n};\n\nclass\tBUSCLASS {\npublic:\n\tvirtual\tSTRINGP\tname(void) = 0;\t// i.e. WB\n\tvirtual\tSTRINGP\tlongname(void) = 0;\t// i.e. \"Wishbone\"\n\tvirtual\tbool\tmatchtype(STRINGP) = 0;\n\tvirtual\tbool\tmatchfail(MAPDHASH *bhash) { return false; };\n\tvirtual\tbool\tmatches(BUSINFO *bi);\n\tvirtual\tGENBUS\t*create(BUSINFO *bi) = 0;\n};\n\n#define\tNUM_BUS_CLASSES\t3\nextern\tunsigned\tnum_bus_classes;\nextern\tBUSCLASS\t*busclass_list[NUM_BUS_CLASSES];\n#endif\t// GENBUS_H\n"
  },
  {
    "path": "sw/globals.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/globals.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\t\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include \"globals.h\"\n\nMAPDHASH\t*gbl_hash = NULL;\nconst bool\tDELAY_ACK = true;\n\n\n"
  },
  {
    "path": "sw/globals.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/globals.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\t\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tGLOBALS_H\n#define\tGLOBALS_H\n\n#include <stdio.h>\n#include \"mapdhash.h\"\n\n\nextern\tMAPDHASH\t*gbl_hash;\n\n#endif // GLOBALS_H\n"
  },
  {
    "path": "sw/ifdefs.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/ifdefs.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tComponents we have can contain an ACCESS keyword that can then\n//\t\tbe used by logic to determine if the component exists or not.\n//\n//\tThese ACCESS lines may also depend upon the ACCESS lines of other\n//\tcomponents.\n//\n//\tmain.v\t\tGets all of our work.  The ACCESS lines are used at\n//\t\t\tthe top of this component to turn things on (or off)\n//\n//\ttoplevel.v\tDoesn't get touched.  If you include your component\n//\t\t\tin the autofpga list, it will define external ports\n//\t\t\tfor it, independent of the ACCESS lines.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <string.h>\n#include <unistd.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <limits.h>\n#include <ctype.h>\n\n#include \"parser.h\"\n#include \"keys.h\"\n#include \"kveval.h\"\n#include \"legalnotice.h\"\n\nextern\tbool\tisperipheral(MAPT &pmap);\nextern\tbool\tisperipheral(MAPDHASH &phash);\n\nvoid\tbuild_access_ifdefs_v(MAPDHASH &master, FILE *fp) {\n\tconst\tchar\tDELIMITERS[] = \", \\t\\n\";\n\tMAPDHASH::iterator\tkvpair;\n\tSTRING\t\talready_defined;\n\tMAPDHASH\tdephash;\n\n\tfprintf(fp,\n\"//\\n\"\n\"//\\n\"\n\"// Here is a list of defines which may be used, post auto-design\\n\"\n\"// (not post-build), to turn particular peripherals (and bus masters)\\n\"\n\"// on and off.  In particular, to turn off support for a particular\\n\"\n\"// design component, just comment out its respective `define below.\\n\"\n\"//\\n\"\n\"// These lines are taken from the respective @ACCESS tags for each of our\\n\"\n\"// components.  If a component doesn\\'t have an @ACCESS tag, it will not\\n\"\n\"// be listed here.\\n\"\n\"//\\n\");\n\tfprintf(fp, \"// First, the independent access fields for any bus masters\\n\");\n\t// {{{\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tif (isperipheral(kvpair->second))\n\t\t\tcontinue;\n\t\tSTRINGP\tdep, accessp;\n\t\tdep = getstring(*kvpair->second.u.m_m, KYDEPENDS);\n\t\taccessp = getstring(*kvpair->second.u.m_m, KYACCESS);\n\t\tif (NULL == accessp)\n\t\t\tcontinue;\n\t\tif (NULL != dep) {\n\t\t\tdephash.insert(*kvpair);\n\t\t} else {\n\t\t\tchar *dup = strdup(accessp->c_str());\n\t\t\tchar *tok = strtok(dup, DELIMITERS);\n\n\t\t\twhile(tok != NULL) {\n\t\t\t\tif (tok[0] == '!')\n\t\t\t\t\ttok++;\n\t\t\t\tfprintf(fp, \"`define\\t%s\\n\", tok);\n\t\t\t\talready_defined = already_defined\n\t\t\t\t\t\t\t+ \" \" + STRING(tok);\n\t\t\t\ttok = strtok(NULL, DELIMITERS);\n\t\t\t} free(dup);\n\t\t}\n\t}\n\t// }}}\n\n\tfprintf(fp, \"// And then for the independent peripherals\\n\");\n\t// {{{\n\tfor(kvpair=master.begin(); kvpair != master.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tif (!isperipheral(kvpair->second))\n\t\t\tcontinue;\n\t\tSTRINGP\tdep, accessp;\n\t\tdep = getstring(kvpair->second, KYDEPENDS);\n\t\taccessp = getstring(kvpair->second, KYACCESS);\n\t\tif (NULL == accessp)\n\t\t\tcontinue;\n\t\telse if (NULL != dep) {\n\t\t\tdephash.insert(*kvpair);\n\t\t} else {\n\t\t\tchar *dup = strdup(accessp->c_str());\n\t\t\tchar *tok = strtok(dup, DELIMITERS);\n\n\t\t\twhile(tok != NULL) {\n\t\t\t\tif (tok[0] == '!')\n\t\t\t\t\ttok++;\n\t\t\t\tfprintf(fp, \"`define\\t%s\\n\", tok);\n\t\t\t\talready_defined = already_defined\n\t\t\t\t\t\t\t+ \" \" + STRING(tok);\n\t\t\t\ttok = strtok(NULL, DELIMITERS);\n\t\t\t} free(dup);\n\t\t}\n\t}\n\t// }}}\n\n\tif (dephash.begin() != dephash.end()) {\n\t\tfprintf(fp, \"//\\n//\\n// The list of those things that have @DEPENDS tags\\n//\\n//\\n\");\n\t\tfprintf(fp,\n\"//\\n\"\n\"// Dependencies\\n\"\n\"// Any core with both an @ACCESS and a @DEPENDS tag will show up here.\\n\"\n\"// The @DEPENDS tag will turn into a series of ifdef\\'s, with the @ACCESS\\n\"\n\"// being defined only if all of the ifdef\\'s are true\"\n\"//\\n\");\n\t\t// {{{\n\n\t\tbool\tdone;\n\t\tdo {\n\t\t\tdone = true;\n\t\t\tSTRING\tdepstr, endstr;\n\n\t\t\tfor(kvpair=dephash.begin(); kvpair != dephash.end(); kvpair++) {\n\t\t\t\t// {{{\n\t\t\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\t\t\tcontinue;\n\t\t\t\tSTRINGP\tdep, accessp;\n\t\t\t\tdep = getstring(kvpair->second, KYDEPENDS);\n\t\t\t\taccessp = getstring(kvpair->second, KYACCESS);\n\n\n\t\t\t\tbool\tdepsmet = true;\n\t\t\t\tchar\t*deplist, *dependency;\n\t\t\t\tdeplist = strdup(dep->c_str());\n\n\t\t\t\tdepstr = \"\";\n\t\t\t\tendstr = \"\";\n\t\t\t\tfprintf(fp, \"// Deplist for @$(PREFIX)=%s\\n\", kvpair->first.c_str());\n\t\t\t\tdependency = strtok(deplist, DELIMITERS);\n\t\t\t\twhile(dependency) {\n\t\t\t\t\tchar\t*rawdep, *baredep;\n\n\t\t\t\t\trawdep = dependency;\n\t\t\t\t\tbaredep = rawdep;\n\t\t\t\t\tif (rawdep[0] == '!')\n\t\t\t\t\t\tbaredep = rawdep+1;\n\t\t\t\t\tSTRING\tmstr = STRING(\" \")+STRING(baredep)\n\t\t\t\t\t\t+STRING(\" \");\n\t\t\t\t\tif (NULL == strstr(already_defined.c_str(),\n\t\t\t\t\t\t\tbaredep)) {\n\t\t\t\t\t\t// fprintf(fp, \"// -- Dependency not met: %s\\n\", baredep);\n\t\t\t\t\t\tdepsmet = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (rawdep[0] == '!') {\n\t\t\t\t\t\tdepstr += STRING(\"`ifndef\\t\")\n\t\t\t\t\t\t\t+ STRING(baredep)\n\t\t\t\t\t\t\t+ STRING(\"\\n\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdepstr += STRING(\"`ifdef\\t\")\n\t\t\t\t\t\t\t+ STRING(rawdep)\n\t\t\t\t\t\t\t+ STRING(\"\\n\");\n\t\t\t\t\t}\n\t\t\t\t\tendstr = STRING(\"`endif\\t// \")\n\t\t\t\t\t\t+ STRING(rawdep)\n\t\t\t\t\t\t+ STRING(\"\\n\")\n\t\t\t\t\t\t+ endstr;\n\t\t\t\t\tdependency = strtok(NULL, DELIMITERS);\n\t\t\t\t}\n\n\n\t\t\t\tif (depsmet) {\n\t\t\t\t\tchar *dup = strdup(accessp->c_str());\n\t\t\t\t\tchar *tok = strtok(dup, DELIMITERS);\n\n\t\t\t\t\tfprintf(fp, \"%s\", depstr.c_str());\n\t\t\t\t\twhile(tok != NULL) {\n\t\t\t\t\t\tif (tok[0] == '!')\n\t\t\t\t\t\t\ttok++;\n\t\t\t\t\t\tif (NULL == strstr(already_defined.c_str(), tok)) {\n\t\t\t\t\t\t\tfprintf(fp, \"`define\\t%s\\n\", tok);\n\t\t\t\t\t\t\talready_defined = already_defined\n\t\t\t\t\t\t\t\t+ \" \" + STRING(tok);\n\n\t\t\t\t\t\t\t// We changed something, so ...\n\t\t\t\t\t\t\tdone = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttok = strtok(NULL, DELIMITERS);\n\t\t\t\t\t} free(dup);\n\n\t\t\t\t\tfprintf(fp, \"%s\", endstr.c_str());\n\n\t\t\t\t\tdephash.erase(kvpair);\n\t\t\t\t\tkvpair = dephash.begin();\n\t\t\t\t\tif (kvpair == dephash.end())\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// }}}\n\t\t\t}\n\n\t\t\tif (dephash.begin() == dephash.end())\n\t\t\t\tdone = true;\n\t\t} while(!done);\n\t\t// }}}\n\t}\n\n\tif (dephash.begin() != dephash.end()) {\n\t\tfprintf(fp,\n\"//\\n\"\n\"// The following macros have unmet dependencies.  They are listed\\n\"\n\"// here for reference, but their dependencies cannot be met.\\n\");\n\t\t// {{{\n\n\t\tfor(kvpair=dephash.begin(); kvpair != dephash.end(); kvpair++) {\n\t\t\tconst char\tDELIMITERS[] = \", \\t\\n\";\n\t\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\t\tcontinue;\n\t\t\tSTRINGP\tdep, accessp;\n\t\t\tdep = getstring(kvpair->second, KYDEPENDS);\n\t\t\taccessp = getstring(kvpair->second, KYACCESS);\n\n\n\t\t\tchar\t*deplist, *dependency;\n\t\t\tdeplist = strdup(dep->c_str());\n\n\t\t\tSTRING\tdepstr, endstr;\n\n\t\t\tdepstr = \"\";\n\t\t\tendstr = \"\";\n\n\t\t\tfprintf(fp,\n\t\t\t\t\"// Unmet Dependency list for @$(PREFIX)=%s\\n\",\n\t\t\t\tkvpair->first.c_str());\n\n\t\t\tdependency = strtok(deplist, DELIMITERS);\n\t\t\twhile(dependency) {\n\t\t\t\tconst char *baredep = dependency;\n\t\t\t\tbool\t\tdefined = false;\n\n\t\t\t\tif (baredep[0] == '!')\n\t\t\t\t\tbaredep++;\n\n\t\t\t\tif (NULL != strstr(already_defined.c_str(), baredep))\n\t\t\t\t\tdefined = true;\n\n\t\t\t\tif (dependency[0] == '!') {\n\t\t\t\t\tdepstr += STRING(\"`ifndef\\t\")\n\t\t\t\t\t\t+STRING(baredep);\n\t\t\t\t\tif (!defined)\n\t\t\t\t\t\tdepstr += \" // This value is unknown\";\n\t\t\t\t\tdepstr += STRING(\"\\n\");\n\t\t\t\t} else {\n\t\t\t\t\tdepstr += STRING(\"`ifdef\\t\")\n\t\t\t\t\t\t+STRING(baredep);\n\t\t\t\t\tif (!defined)\n\t\t\t\t\t\tdepstr += \" // This value is unknown\";\n\t\t\t\t\tdepstr += STRING(\"\\n\");\n\t\t\t\t}\n\t\t\t\tendstr += STRING(\"`endif\\n\");\n\t\t\t\tdependency = strtok(NULL, DELIMITERS);\n\t\t\t}\n\n\t\t\tfprintf(fp, \"%s\", depstr.c_str());\n\n\t\t\t{\n\t\t\t\tchar *dup = strdup(accessp->c_str());\n\t\t\t\tchar *tok = strtok(dup, DELIMITERS);\n\n\t\t\t\twhile(tok != NULL) {\n\t\t\t\t\tif (tok[0] == '!')\n\t\t\t\t\t\ttok++;\n\t\t\t\t\tfprintf(fp, \"`define\\t%s\\n\", tok);\n\t\t\t\t\ttok = strtok(NULL, DELIMITERS);\n\t\t\t\t} free(dup);\n\t\t\t}\n\n\t\t\tfprintf(fp, \"%s\\n\", endstr.c_str());\n\t\t}\n\t\t// }}}\n\t}\n\n\tfprintf(fp, \"//\\n// End of dependency list\\n//\\n//\\n\");\n}\n"
  },
  {
    "path": "sw/ifdefs.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/ifdefs.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tComponents we have can contain an ACCESS keyword that can then\n//\t\tbe used by logic to determine if the component exists or not.\n//\n//\tThese ACCESS lines may also depend upon the ACCESS lines of other\n//\tcomponents.\n//\n//\tmain.v\t\tGets all of our work.  The ACCESS lines are used at\n//\t\t\tthe top of this component to turn things on (or off)\n//\n//\ttoplevel.v\tDoesn't get touched.  If you include your component\n//\t\t\tin the autofpga list, it will define external ports\n//\t\t\tfor it, independent of the ACCESS lines.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tIFDEFS_H\n#define\tIFDEFS_H\n#include <stdio.h>\n#include \"mapdhash.h\"\n\nextern\tvoid\tbuild_access_ifdefs_v(MAPDHASH &master, FILE *fp);\n#endif\n"
  },
  {
    "path": "sw/keys.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/keys.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tDefines the strings AutoFPGA understands.  These strings are\n// \t\ttypically key names, as described by the ICD.  The actual string\n// \tnames are (nearly) equal to their C++ name.  However, by defining them\n// \there, I get some robustness to ICD changes, and some compiler help to\n// \tmake sure I only use named strings.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include \"keys.h\"\n\nconst\tSTRING\tKYLEGAL=\t\"LEGAL\";\nconst\tSTRING\tKYCOPYRIGHT=\t\"COPYRIGHT\";\t// Another name for LEGAL\nconst\tSTRING\tKYCMDLINE=\t\"CMDLINE\";\nconst\tSTRING\tKYSUBD=\t\t\"SUBD\";\nconst\tSTRING\tKYPATH=\t\t\"PATH\";\n// const\tSTRING\tKYBUS_ADDRESS_WIDTH=\"BUS_ADDRESS_WIDTH\";\nconst\tSTRING\tKYRESET_ADDRESS\t=\"RESET_ADDRESS\";\n// For subclassing\nconst\tSTRING\tKYPLUSDOT\t=\"+\";\nconst\tSTRING\tKYINCLUDE\t=\"INCLUDE\";\nconst\tSTRING\tKYINCLUDEFILE\t=\"INCLUDEFILE\";\n// Other global keys\nconst\tSTRING\tKYREGDEFS_CPP_INCLUDE\t=\"REGDEFS.CPP.INCLUDE\";\nconst\tSTRING\tKYREGDEFS_CPP_INSERT\t=\"REGDEFS.CPP.INSERT\";\nconst\tSTRING\tKYKEYS_TRIMLIST\t=\"KEYS.TRIMLIST\";\nconst\tSTRING\tKYKEYS_INTLIST\t=\"KEYS.INTLIST\";\nconst\tSTRING\tKYPROJECT\t=\"PROJECT\";\n//\nconst\tSTRING\tKYSIO=\t\t\"sio\";\nconst\tSTRING\tKYDIO=\t\t\"dio\";\nconst\tSTRING\tKYSIO_SEL=\t\"sio_sel\";\nconst\tSTRING\tKYDIO_SEL=\t\"dio_sel\";\n//\nconst\tSTRING\tKYPREFIX=\t\"PREFIX\";\nconst\tSTRING\tKYACCESS=\t\"ACCESS\";\nconst\tSTRING\tKYDEPENDS=\t\"DEPENDS\";\nconst\tSTRING\tKYERROR_WIRE=\t\"ERROR.WIRE\";\nconst\tSTRING\tKYSLAVE=\t\t\"SLAVE\",\n\t\tKYSLAVE_TYPE=\t\t\"SLAVE.TYPE\",\n\t\tKYSLAVE_BUS=\t\t\"SLAVE.BUS\",\n\t\tKYSLAVE_BUS_NAME=\t\"SLAVE.BUS.NAME\",\n\t\tKYSLAVE_ORDER=\t\t\"SLAVE.ORDER\",\n\t\tKYSLAVE_AWID=\t\t\"SLAVE.AWID\",\n\t\tKYSLAVE_OPTIONS=\t\"SLAVE.OPTIONS\",\n\t\tKYSLAVE_PREFIX=\t\t\"SLAVE.PREFIX\",\n\t\tKYSLAVE_PORTLIST=\t\"SLAVE.PORTLIST\",\n\t\tKYSLAVE_ANSIPORTLIST=\t\"SLAVE.ANSIPORTLIST\",\n\t\tKYSLAVE_IANSI=\t\t\"SLAVE.IANSI\",\n\t\tKYSLAVE_OANSI=\t\t\"SLAVE.OANSI\",\n\t\tKYSLAVE_ANSPREFIX=\t\"SLAVE.ANSPREFIX\";\nconst\tSTRING\tKYMASTER=\t\"MASTER\",\n\t\tKYMASTER_TYPE=\t\"MASTER.TYPE\",\n\t\tKYMASTER_BUS=\t\"MASTER.BUS\",\n\t\tKYMASTER_BUS_NAME=\t\"MASTER.BUS.NAME\",\n\t\tKYMASTER_PREFIX=\t\"MASTER.PREFIX\",\n\t\tKYMASTER_AWID=\t\t\"MASTER.AWID\",\n\t\tKYMASTER_OPTIONS=\t\"MASTER.OPTIONS\",\n\t\tKYMASTER_PORTLIST=      \"MASTER.PORTLIST\",\n\t\tKYMASTER_ANSIPORTLIST=  \"MASTER.ANSIPORTLIST\",\n\t\tKYMASTER_IDWIDTH=       \"MASTER.IDWIDTH\",\n\t\tKYMASTER_IANSI=         \"MASTER.IANSI\",\n\t\tKYMASTER_OANSI=         \"MASTER.OANSI\",\n\t\tKYMASTER_ANSPREFIX=     \"MASTER.ANSPREFIX\";\n// Types of bus masters\n// KYBUS, and ...\nconst\tSTRING\tKYSUBBUS=\t\"SUBBUS\",\n\t\tKYARBITER=\t\"ARBITER\",\n\t\tKYXCLOCK=\t\"XCLOCK\",\n\t\tKYHOST=\t\t\"HOST\",\n\t\tKYCPU=\t\t\"CPU\";\n//\nconst\tSTRING\tKYBASE=\t\t\"BASE\";\nconst\tSTRING\tKYREGBASE=\t\"REGBASE\";\nconst\tSTRING\tKYNADDR=\t\"NADDR\";\nconst\tSTRING\tKYMASK=\t\t\"MASK\";\n//\nconst\tSTRING\tKYEXPR=\t\t\"EXPR\";\nconst\tSTRING\tKYVAL=\t\t\"VAL\";\nconst\tSTRING\tKYFORMAT=\t\"FORMAT\";\nconst\tSTRING\tKYSTR=\t\t\"STR\";\n//\nconst\tSTRING\tKYSCOPE=\t\"SCOPE\";\nconst\tSTRING\tKYMEMORY=\t\"MEMORY\";\nconst\tSTRING\tKYSINGLE=\t\"SINGLE\";\nconst\tSTRING\tKYDOUBLE=\t\"DOUBLE\";\nconst\tSTRING\tKYOTHER=\t\"OTHER\";\n// Numbers of things\nconst\tSTRING\tKYNP=\t\t\"NP\";\nconst\tSTRING\tKYNPIC=\t\t\"NPIC\";\nconst\tSTRING\tKYNPSINGLE=\t\"NPSINGLE\";\nconst\tSTRING\tKYNPDOUBLE=\t\"NPDOUBLE\";\nconst\tSTRING\tKYNPMEMORY=\t\"NPMEMORY\";\nconst\tSTRING\tKYNSCOPES=\t\"NSCOPES\";\n// Regs definitions\nconst\tSTRING\tKYREGS_N=\t\"REGS.N\";\nconst\tSTRING\tKYREGS_NOTE=\t\"REGS.NOTE\";\nconst\tSTRING\tKYREGDEFS_H_INCLUDE=\"REGDEFS.H.INCLUDE\";\nconst\tSTRING\tKYREGDEFS_H_DEFNS=\"REGDEFS.H.DEFNS\";\nconst\tSTRING\tKYREGDEFS_H_INSERT=\"REGDEFS.H.INSERT\";\n// Board defintions for C/C++\nconst\tSTRING\tKYBDEF_INCLUDE=\t\"BDEF.INCLUDE\";\nconst\tSTRING\tKYBDEF_DEFN=\t\"BDEF.DEFN\";\nconst\tSTRING\tKYBDEF_IOTYPE=\t\"BDEF.IOTYPE\";\nconst\tSTRING\tKYBDEF_OSDEF=\t\"BDEF.OSDEF\";\nconst\tSTRING\tKYBDEF_OSVAL=\t\"BDEF.OSVAL\";\nconst\tSTRING\tKYBDEF_INSERT=\t\"BDEF.INSERT\";\n// Top definitions\nconst\tSTRING\tKYTOP_PORTLIST=\t\"TOP.PORTLIST\";\nconst\tSTRING\tKYTOP_IODECL=\t\"TOP.IODECL\";\nconst\tSTRING\tKYTOP_PARAM=\t\"TOP.PARAM\";\nconst\tSTRING\tKYTOP_DEFNS=\t\"TOP.DEFNS\";\nconst\tSTRING\tKYTOP_MAIN=\t\"TOP.MAIN\";\nconst\tSTRING\tKYTOP_INSERT=\t\"TOP.INSERT\";\n// Main definitions\nconst\tSTRING\tKYMAIN_INCLUDE= \"MAIN.INCLUDE\";\nconst\tSTRING\tKYMAIN_PORTLIST=\"MAIN.PORTLIST\";\nconst\tSTRING\tKYMAIN_IODECL=\t\"MAIN.IODECL\";\nconst\tSTRING\tKYMAIN_PARAM=\t\"MAIN.PARAM\";\nconst\tSTRING\tKYMAIN_DEFNS=\t\"MAIN.DEFNS\";\nconst\tSTRING\tKYMAIN_INSERT=\t\"MAIN.INSERT\";\nconst\tSTRING\tKYMAIN_ALT=\t\"MAIN.ALT\";\n// LD definitions\nconst\tSTRING\tKYLD_FILE=\t\"LD.FILE\";\nconst\tSTRING\tKYLD_SCRIPT=\t\"LD.SCRIPT\";\nconst\tSTRING\tKYLD_ENTRY=\t\"LD.ENTRY\";\nconst\tSTRING\tKYLD_NAME=\t\"LD.NAME\";\nconst\tSTRING\tKYLD_PERM=\t\"LD.PERM\";\nconst\tSTRING\tKYLD_DEFNS=\t\"LD.DEFNS\";\nconst\tSTRING\tKYSCRIPT=\t\"SCRIPT\";\nconst\tSTRING\tKYFLASH=\t\"flash\";\n// XDC/UCF definitions\nconst\tSTRING\tKYXDC_FILE=\t\"XDC.FILE\";\nconst\tSTRING\tKYXDC_INSERT=\t\"XDC.INSERT\";\nconst\tSTRING\tKYPCF_FILE=\t\"PCF.FILE\";\nconst\tSTRING\tKYPCF_INSERT=\t\"PCF.INSERT\";\nconst\tSTRING\tKYLPF_FILE=\t\"LPF.FILE\";\nconst\tSTRING\tKYLPF_INSERT=\t\"LPF.INSERT\";\nconst\tSTRING\tKYUCF_FILE=\t\"UCF.FILE\";\nconst\tSTRING\tKYUCF_INSERT=\t\"UCF.INSERT\";\n// INT definitions\nconst\tSTRING\tKY_INT=\t\t\"INT\";\nconst\tSTRING\tKYINTLIST=\t\"INTLIST\";\nconst\tSTRING\tKY_WIRE=\t\"WIRE\";\nconst\tSTRING\tKY_DOTWIRE=\t\".WIRE\";\nconst\tSTRING\tKY_ID=\t\t\"ID\";\n// Arbitrary output data files\nconst\tSTRING\tKYOUT_FILE=\t\"OUT.FILE\";\nconst\tSTRING\tKYOUT_DATA=\t\"OUT.DATA\";\n// RTL/Makefile definitions\nconst\tSTRING\tKYRTL_MAKE_GROUP= \"RTL.MAKE.GROUP\";\nconst\tSTRING\tKYRTL_MAKE_SUBD=  \"RTL.MAKE.SUBD\";\nconst\tSTRING\tKYVFLIST=\t  \"VFLIST\";\nconst\tSTRING\tKYRTL_MAKE_VDIRS= \"RTL.MAKE.VDIRS\";\nconst\tSTRING\tKYRTL_MAKE_FILES= \"RTL.MAKE.FILES\";\nconst\tSTRING\tKYAUTOVDIRS=\t  \"AUTOVDIRS\";\n// PIC definitions\nconst\tSTRING\tKYPIC=\t\t\"PIC\";\nconst\tSTRING\tKYPIC_BUS=\t\"PIC.BUS\";\nconst\tSTRING\tKYPIC_MAX=\t\"PIC.MAX\";\n// Cache information\nconst\tSTRING\tKYCACHABLE_FILE=\"CACHABLE.FILE\";\n// SIM definitions\nconst\tSTRING\tKYSIM_INCLUDE=\t\"SIM.INCLUDE\";\nconst\tSTRING\tKYSIM_DEFINES=\t\"SIM.DEFINES\";\nconst\tSTRING\tKYSIM_DEFNS=\t\"SIM.DEFNS\";\nconst\tSTRING\tKYSIM_PREINITIAL=\"SIM.PREINITIAL\";\nconst\tSTRING\tKYSIM_INIT=\t\"SIM.INIT\";\nconst\tSTRING\tKYSIM_CLOCK=\t\"SIM.CLOCK\";\nconst\tSTRING\tKYSIM_TICK=\t\"SIM.TICK\";\nconst\tSTRING\tKYSIM_SETRESET=\t\"SIM.SETRESET\";\nconst\tSTRING\tKYSIM_CLRRESET=\t\"SIM.CLRRESET\";\nconst\tSTRING\tKYSIM_DBGCONDITION=\t\"SIM.DBGCONDITION\";\nconst\tSTRING\tKYSIM_DEBUG=\t\"SIM.DEBUG\";\nconst\tSTRING\tKYSIM_LOAD=\t\"SIM.LOAD\";\nconst\tSTRING\tKYSIM_METHODS=\t\"SIM.METHODS\";\n// SIM/Makefile definitions\n// const\tSTRING\tKYSIM_MAKE_GROUP= \"SIM.MAKE.GROUP\";\n// const\tSTRING\tKYSIM_MAKE_FILES= \"SIM.MAKE.FILES\";\n// const\tSTRING\tKYSIM_MAKE_SUBD=  \"SIM.MAKE.SUBD\";\n// const\tSTRING\tKYSIM_MAKE_VDIRS= \"SIM.MAKE.VDIRS\";\n//\nconst\tSTRING\tKYTHIS=\"THIS\";\nconst\tSTRING\tKYTHISDOT=\"THIS.\";\n// CLOCKS\nconst\tSTRING\tKYCLOCK=\"CLOCK\";\nconst\tSTRING\tKYCLOCK_NAME=\"CLOCK.NAME\";\nconst\tSTRING\tKYCLOCK_TOP=\"CLOCK.TOP\";\nconst\tSTRING\tKY_NAME=\"NAME\";\nconst\tSTRING\tKY_TOP=\"TOP\";\nconst\tSTRING\tKY_FREQUENCY=\"FREQUENCY\";\nconst\tSTRING\tKY_CLASS=\"CLASS\";\n// BUS definitions\nconst\tSTRING\tKYBUS = \"BUS\",\n\t\tKYBUS_NAME = \"BUS.NAME\",\n\t\tKYBUS_PREFIX = \"BUS.PREFIX\",\n\t\tKYBUS_TYPE   = \"BUS.TYPE\",\n\t\tKYBUS_AWID   = \"BUS.AWID\",\n\t\tKYBUS_IDWIDTH= \"BUS.IDWIDTH\",\n\t\tKYBUS_CLOCK  = \"BUS.CLOCK\",\n\t\tKYBUS_NULLSZ = \"BUS.NULLSZ\",\n\t\tKY_TYPE      = \"TYPE\",\n\t\tKY_WIDTH     = \"WIDTH\",\n\t\tKY_IDWIDTH   = \"IDWIDTH\",\n\t\tKY_AWID      = \"AWID\",\n\t\tKY_CLOCK     = \"CLOCK\",\n\t\tKY_RESET     = \"RESET\",\n\t\tKY_NULLSZ    = \"NULLSZ\",\n\t\tKY_NSELECT   = \"NSELECT\",\n\t\tKYDEFAULT_BUS= \"DEFAULT.BUS\",\n\t\tKYREGISTER_BUS= \"REGISTER.BUS\",\n\t\tKYREGISTER_BUS_NAME= \"REGISTER.BUS.NAME\";\n\nconst\tSTRING\tKY_OPT_LOWPOWER   = \"OPT_LOWPOWER\",\n\t\tKY_OPT_LINGER     = \"OPT_LINGER\",\n\t\tKY_OPT_LGMAXBURST = \"OPT_LGMAXBURST\",\n\t\tKY_OPT_TIMEOUT    = \"OPT_TIMEOUT\",\n\t\tKY_OPT_STARVATION_TIMEOUT = \"OPT_STARVATION_TIMEOUT\",\n\t\tKY_OPT_DBLBUFFER  = \"OPT_DBLBUFFER\";\n//\n//\n\n"
  },
  {
    "path": "sw/keys.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/keys.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tDefines the names of the strings AutoFPGA understands.  These\n//\t\tare the key names understood by AutoFPGA and described by the\n//\tICD.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tICD_H\n#define\tICD_H\n\n#include <string>\n#include \"mapdhash.h\"\n\n//\nextern const\tSTRING\tKYLEGAL;\nextern const\tSTRING\tKYCOPYRIGHT;\nextern const\tSTRING\tKYCMDLINE;\nextern const\tSTRING\tKYSUBD;\t// Output subdirectory\nextern const\tSTRING\tKYPATH;\nextern const\tSTRING\tKYSUBD;\n// extern const\tSTRING\tKYBUS_ADDRESS_WIDTH;\nextern const\tSTRING\tKYSKIPADDR;\nextern const\tSTRING\tKYRESET_ADDRESS;\n// For subclassing\nextern const\tSTRING\tKYPLUSDOT;\nextern const\tSTRING\tKYINCLUDEFILE;\n// Other global keys\nextern const\tSTRING\tKYREGDEFS_CPP_INCLUDE;\nextern const\tSTRING\tKYREGDEFS_CPP_INSERT;\nextern const\tSTRING\tKYKEYS_TRIMLIST;\nextern const\tSTRING\tKYKEYS_INTLIST;\nextern const\tSTRING\tKYPROJECT;\n//\nextern const\tSTRING\tKYSIO;\nextern const\tSTRING\tKYDIO;\nextern const\tSTRING\tKYSIO_SEL;\nextern const\tSTRING\tKYDIO_SEL;\n//\nextern const\tSTRING\tKYPREFIX;\nextern const\tSTRING\tKYACCESS;\nextern const\tSTRING\tKYDEPENDS;\nextern const\tSTRING\tKYERROR_WIRE;\nextern const\tSTRING\tKYSLAVE,\n\t\t\tKYSLAVE_TYPE,\n\t\t\tKYSLAVE_BUS,\n\t\t\tKYSLAVE_BUS_NAME,\n\t\t\tKYSLAVE_ORDER,\n\t\t\tKYSLAVE_AWID,\n\t\t\tKYSLAVE_OPTIONS,\n\t\t\tKYSLAVE_PREFIX,\n\t\t\tKYSLAVE_PORTLIST,\n\t\t\tKYSLAVE_ANSIPORTLIST,\n\t\t\tKYSLAVE_IANSI,\n\t\t\tKYSLAVE_OANSI,\n\t\t\tKYSLAVE_ANSPREFIX;\nextern const\tSTRING\tKYMASTER,\n\t\t\tKYMASTER_TYPE,\n\t\t\tKYMASTER_BUS,\n\t\t\tKYMASTER_BUS_NAME,\n\t\t\tKYMASTER_PREFIX,\n\t\t\tKYMASTER_AWID,\n\t\t\tKYMASTER_OPTIONS,\n\t\t\tKYMASTER_PORTLIST,\n\t\t\tKYMASTER_ANSIPORTLIST,\n\t\t\tKYMASTER_IDWIDTH,\n\t\t\tKYMASTER_IANSI,\n\t\t\tKYMASTER_OANSI,\n\t\t\tKYMASTER_ANSPREFIX;\n// Types of bus masters.\n// KYBUS, (HOST), (VIDEO), (XCLOCK), and ...\nextern\tconst\tSTRING\tKYSUBBUS,\n\t\t\tKYARBITER,\n\t\t\tKYXCLOCK,\n\t\t\tKYHOST,\n\t\t\tKYCPU;\n//\nextern const\tSTRING\tKYBASE;\nextern const\tSTRING\tKYREGBASE;\nextern const\tSTRING\tKYMASK;\nextern const\tSTRING\tKYNADDR;\n//\nextern const\tSTRING\tKYEXPR;\nextern const\tSTRING\tKYVAL;\nextern const\tSTRING\tKYFORMAT;\nextern const\tSTRING\tKYSTR;\n//\nextern const\tSTRING\tKYSCOPE;\nextern const\tSTRING\tKYMEMORY;\nextern const\tSTRING\tKYSINGLE;\nextern const\tSTRING\tKYDOUBLE;\nextern const\tSTRING\tKYOTHER;\n//\nextern const\tSTRING\tKYNP;\nextern const\tSTRING\tKYNPIC;\nextern const\tSTRING\tKYNPSINGLE;\nextern const\tSTRING\tKYNPDOUBLE;\nextern const\tSTRING\tKYNPMEMORY;\nextern const\tSTRING\tKYNSCOPES;\n// Regs definition(s)\nextern const\tSTRING\tKYREGS_N;\nextern const\tSTRING\tKYREGS_NOTE;\nextern const\tSTRING\tKYREGDEFS_H_INCLUDE;\nextern const\tSTRING\tKYREGDEFS_H_DEFNS;\nextern const\tSTRING\tKYREGDEFS_H_INSERT;\n// Board definitions for C/C++\nextern const\tSTRING\tKYBDEF_INCLUDE;\nextern const\tSTRING\tKYBDEF_DEFN;\nextern const\tSTRING\tKYBDEF_IOTYPE;\nextern const\tSTRING\tKYBDEF_OSDEF;\nextern const\tSTRING\tKYBDEF_OSVAL;\nextern const\tSTRING\tKYBDEF_INSERT;\n// Top definitions\nextern const\tSTRING\tKYTOP_PORTLIST;\nextern const\tSTRING\tKYTOP_IODECL;\nextern const\tSTRING\tKYTOP_PARAM;\nextern const\tSTRING\tKYTOP_DEFNS;\nextern const\tSTRING\tKYTOP_MAIN;\nextern const\tSTRING\tKYTOP_INSERT;\n// Main definitions\nextern const\tSTRING\tKYMAIN_INCLUDE;\nextern const\tSTRING\tKYMAIN_PORTLIST;\nextern const\tSTRING\tKYMAIN_IODECL;\nextern const\tSTRING\tKYMAIN_PARAM;\nextern const\tSTRING\tKYMAIN_DEFNS;\nextern const\tSTRING\tKYMAIN_INSERT;\nextern const\tSTRING\tKYMAIN_ALT;\n// Definitions for the .ld file(s)\nextern const\tSTRING\tKYLD_FILE;\nextern const\tSTRING\tKYLD_SCRIPT;\nextern const\tSTRING\tKYLD_ENTRY;\nextern const\tSTRING\tKYLD_NAME;\nextern const\tSTRING\tKYLD_PERM;\nextern const\tSTRING\tKYLD_DEFNS;\nextern const\tSTRING\tKYFLASH;\nextern const\tSTRING\tKYSCRIPT;\n// XDC/UCF definitions\nextern\tconst\tSTRING\tKYXDC_FILE;\nextern\tconst\tSTRING\tKYXDC_INSERT;\nextern\tconst\tSTRING\tKYPCF_FILE;\nextern\tconst\tSTRING\tKYPCF_INSERT;\nextern\tconst\tSTRING\tKYLPF_FILE;\nextern\tconst\tSTRING\tKYLPF_INSERT;\nextern\tconst\tSTRING\tKYUCF_FILE;\nextern\tconst\tSTRING\tKYUCF_INSERT;\n// Arbitrary output data files\nextern\tconst\tSTRING\tKYOUT_FILE;\nextern\tconst\tSTRING\tKYOUT_DATA;\n// rtl/Makefile include file\nextern\tconst\tSTRING\tKYRTL_MAKE_GROUP;\nextern\tconst\tSTRING\tKYRTL_MAKE_SUBD;\nextern\tconst\tSTRING\tKYRTL_MAKE_VDIRS;\nextern\tconst\tSTRING\tKYRTL_MAKE_FILES;\nextern\tconst\tSTRING\tKYVFLIST;\nextern\tconst\tSTRING\tKYAUTOVDIRS;\n// PIC definitions\nextern\tconst\tSTRING\tKYPIC, KYPIC_BUS, KYPIC_MAX;\n// Cache information\nextern\tconst\tSTRING\tKYCACHABLE_FILE;\n// Interrupt definitions\nextern\tconst\tSTRING\tKY_INT, KYINTLIST, KY_WIRE, KY_DOTWIRE, KY_ID;\n// SIM definitions\nextern\tconst\tSTRING\tKYSIM_INCLUDE, KYSIM_DEFINES, KYSIM_DEFNS,\n\t\t\tKYSIM_PREINITIAL, KYSIM_INIT, KYSIM_TICK,\n\t\t\tKYSIM_SETRESET, KYSIM_CLRRESET,\n\t\t\tKYSIM_DBGCONDITION, KYSIM_DEBUG,\n\t\t\tKYSIM_LOAD, KYSIM_METHODS, KYSIM_CLOCK;\n// CLOCK definitions\nextern\tconst\tSTRING\tKYCLOCK,\n\t\t\tKYCLOCK_NAME,\n\t\t\tKYCLOCK_TOP,\n\t\t\tKY_NAME,\n\t\t\tKY_TOP,\n\t\t\tKY_CLASS,\n\t\t\tKY_FREQUENCY;\n// BUS definitions\nextern\tconst\tSTRING\tKYBUS,\n\t\t\tKYBUS_NAME,\n\t\t\tKYBUS_PREFIX,\n\t\t\tKYBUS_TYPE,\n\t\t\tKYBUS_WIDTH,\n\t\t\tKYBUS_IDWIDTH,\n\t\t\tKYBUS_AWID,\n\t\t\tKYBUS_CLOCK,\n\t\t\tKYBUS_NULLSZ,\n\t\t\tKY_TYPE,\n\t\t\tKY_WIDTH,\n\t\t\tKY_IDWIDTH,\n\t\t\tKY_AWID,\n\t\t\tKY_CLOCK,\n\t\t\tKY_RESET,\n\t\t\tKY_NULLSZ,\n\t\t\tKY_NSELECT,\n\t\t\tKYDEFAULT_BUS,\n\t\t\tKYREGISTER_BUS,\n\t\t\tKYREGISTER_BUS_NAME;\n// Bus options\nextern\tconst\tSTRING\tKY_OPT_LOWPOWER,\n\t\t\tKY_OPT_LINGER,\n\t\t\tKY_OPT_LGMAXBURST,\n\t\t\tKY_OPT_TIMEOUT,\n\t\t\tKY_OPT_STARVATION_TIMEOUT,\n\t\t\tKY_OPT_DBLBUFFER;\n//\nextern const\tSTRING\tKYSTHIS;\nextern const\tSTRING\tKYTHISDOT;\n\n#endif\n"
  },
  {
    "path": "sw/kveval.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/kveval.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\t\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <vector>\n#include \"mapdhash.h\"\n#include \"kveval.h\"\n#include \"keys.h\"\n#include \"ast.h\"\n#include \"msgs.h\"\n\n\ntypedef\tstd::vector<MAPDHASH *>\tMAPSTACK;\n\nbool\tget_named_kvpair(MAPSTACK &stack, MAPDHASH &here, STRING &key,\n\t\tMAPDHASH::iterator &pair) {\n\tMAPDHASH::iterator\tkvpair, kvsub;\n\n\tif ((key[0]=='.')||(strncmp(key.c_str(), KYTHISDOT.c_str(), KYTHISDOT.size())==0)) {\n\t\tSTRING\tsubkey = (key[0]=='.')?key.substr(1)\n\t\t\t: key.substr(KYTHISDOT.size(),\n\t\t\t\t\tkey.size()-KYTHISDOT.size());\n\t\tpair = findkey(here, subkey);\n\t\treturn (pair != here.end());\n\t} else if (key[0] == '+') {\n\t\tSTRING\tsubkey = key.substr(2);\n\t\tMAPDHASH::iterator\tkvnxt;\n\n\t\tkvpair = findkey(here, KYPLUSDOT);\n\t\tif (kvpair == here.end())\n\t\t\t// +. not found\n\t\t\treturn false;\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\t// It was found, but wasn't a MAP\n\t\t\treturn false;\n\t\tkvsub = kvpair->second.u.m_m->begin();\n\t\tkvnxt = kvsub; kvnxt++;\n\t\tassert(kvnxt == kvpair->second.u.m_m->end());\n\t\tassert(kvsub->second.m_typ == MAPT_MAP);\n\n\t\tpair = findkey(*kvsub->second.u.m_m, subkey);\n/*\nif (pair != kvpair->second.u.m_m->end())\n\tfprintf(stderr, \"  Found a key for %s\\n\", subkey.c_str());\nelse\n\tfprintf(stderr, \"  %s not found\\n\", subkey.c_str());\n*/\n\t\treturn (pair != kvpair->second.u.m_m->end());\n\t} else if (key[0] == '/') {\n\t\tSTRING\tsubkey = key.substr(1);\n\t\tpair = findkey(*stack[0], subkey);\n\t\treturn (pair != stack[0]->end());\n\t// Ok, go first, look for things in the following order:\n\t//\t1. here\n\t//\t2. superclass (in a loop)\n\t//\t3. parent (in a loop)\n\t//\t....\n\t//\t4. top\n\t} else if (here.end() != (pair = findkey(here, key))) {\n\t\treturn true;\n\t}\n\n\t{\n\t\tint\tposn = (int)stack.size()-1;\n\t\tfor(; posn>= 0; posn--) {\n\t\t\tpair =findkey(*stack[posn], key);\n\t\t\tif (pair != stack[posn]->end())\n\t\t\t\tbreak;\n\t\t} if (posn >= 0)\n\t\t\treturn true;\n\t} return false;\n}\n\nbool\tget_named_value(MAPSTACK &stack, MAPDHASH &here, STRING &key,\n\t\tint &value) {\n\tMAPDHASH::iterator\tkvpair;\n\n\tif (get_named_kvpair(stack, here, key, kvpair)) {\n\t\tif (kvpair->second.m_typ == MAPT_INT) {\n\t\t\tvalue = kvpair->second.u.m_v;\n\t\t\treturn true;\n\t\t} else if (kvpair->second.m_typ == MAPT_MAP) {\n\t\t\tif (getvalue(*kvpair->second.u.m_m, value))\n\t\t\t\treturn true;\n\t\t}\n\t} return false;\n}\n\nSTRINGP\tget_named_string(MAPSTACK &stack, MAPDHASH &here, STRING &key) {\n\tMAPDHASH::iterator\tkvpair;\n\n\tif (get_named_kvpair(stack, here, key, kvpair)) {\n\t\tif (kvpair->second.m_typ == MAPT_MAP)\n\t\t\treturn getstring(*kvpair->second.u.m_m);\n\t\tif (kvpair->second.m_typ != MAPT_STRING)\n\t\t\treturn NULL;\n\t\tif (NULL != strstr(kvpair->second.u.m_s->c_str(), \"@$\"))\n\t\t\t// Don't return a named value if it hasn't (yet)\n\t\t\t// been filled in within its current context\n\t\t\treturn NULL;\n\t\treturn kvpair->second.u.m_s;\n\t} return NULL;\n}\n\nvoid\texpr_eval(MAPSTACK &stack, MAPDHASH &here, MAPDHASH &sub, MAPT &expr) {\n\tAST\t*ast;\n\tif (expr.m_typ == MAPT_STRING) {\n\t\tast = parse_ast(*expr.u.m_s);\n\t\tast->define(stack, here);\n\t\tif (ast->isdefined()) {\n\t\t\texpr.m_typ = MAPT_INT;\n\t\t\texpr.u.m_v = ast->eval();\n\t\t\tdelete\tast;\n\t\t} else {\n\t\t\texpr.m_typ = MAPT_AST;\n\t\t\texpr.u.m_a = ast;\n\t\t}\n\t} else if (expr.m_typ == MAPT_AST) {\n\t\tast = expr.u.m_a;\n\t\tast->define(stack, here);\n\t\tif (ast->isdefined()) {\n\t\t\tint\tv = (int)ast->eval();\n\t\t\texpr.m_typ = MAPT_INT;\n\t\t\texpr.u.m_v = v;\n\t\t\tdelete\tast;\n\t\t}\n\t}\n}\n\nbool\tfind_any_unevaluated_sub(MAPSTACK &stack, MAPDHASH *here,\n\t\tMAPDHASH &sub) {\n\tbool\tchanged = false;\n\tMAPDHASH::iterator\tpfx = sub.end(), subi;\n\tMAPDHASH\t*component;\n\n\tpfx = sub.find(KYPREFIX);\n\tif (pfx != sub.end())\n\t\tcomponent = &sub;\n\telse\n\t\tcomponent = here;\n\n\tfor(subi=sub.begin(); subi != sub.end(); subi++) {\n\t\tif (subi->second.m_typ == MAPT_MAP) {\n\t\t\tif (KYPLUSDOT.compare(subi->first) != 0) {\n\t\t\t\t// Don't recurse below any +. keys\n\t\t\t\tstack.push_back(subi->second.u.m_m);\n\t\t\t\tchanged = find_any_unevaluated_sub(stack,\n\t\t\t\t\tcomponent, *subi->second.u.m_m)\n\t\t\t\t\t|| (changed);\n\t\t\t\tstack.pop_back();\n\t\t\t}\n\t\t} else if (subi->first == KYEXPR) {\n\t\t\tif (subi->second.m_typ == MAPT_STRING) {\n\t\t\t\texpr_eval(stack, *component, sub, subi->second);\n\t\t\t\tif (subi->second.m_typ != MAPT_STRING)\n\t\t\t\t\tchanged = true;\n\t\t\t} else if (subi->second.m_typ == MAPT_AST) {\n\t\t\t\tAST\t*ast = subi->second.u.m_a;\n\t\t\t\tast->define(stack, *component);\n\t\t\t\tif (ast->isdefined()) {\n\t\t\t\t\tsubi->second.m_typ = MAPT_INT;\n\t\t\t\t\tsubi->second.u.m_v = ast->eval();\n\t\t\t\t\tdelete ast;\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (subi->second.m_typ == MAPT_AST) {\n\t\t\tAST\t*ast = subi->second.u.m_a;\n\t\t\tast->define(stack, *component);\n\t\t\tif (ast->isdefined()) {\n\t\t\t\tint\tval = ast->eval();\n\t\t\t\tsubi->second.m_typ = MAPT_INT;\n\t\t\t\tsubi->second.u.m_v = val;\n\t\t\t\tdelete ast;\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}\n\t} return changed;\n}\n\nvoid\tfind_any_unevaluated(MAPDHASH &info) {\n\tMAPDHASH::iterator\ttopi;\n\tbool\tchanged = false;\n\tMAPSTACK\tstack;\n\tstack.push_back(&info);\n\n\tdo {\n\t\tfor(topi=info.begin(); topi != info.end(); topi++) {\n\t\t\tif (topi->second.m_typ != MAPT_MAP)\n\t\t\t\tcontinue;\n\t\t\tchanged = find_any_unevaluated_sub(stack, &info,\n\t\t\t\t\t*topi->second.u.m_m);\n\t\t}\n\t} while(changed);\n}\n\nbool\tsubresults_into(MAPSTACK stack, MAPDHASH *here, STRINGP &sval) {\n\tbool\tchanged = false, everchanged = false;;\n\n\tif (STRING::npos == (sval->find(\"@$\"))) {\n\t\treturn everchanged;\n\t}\n\n\tdo {\n\t\tunsigned long\tsloc = -1;\n\n\t\tchanged = false;\n\t\tsloc = 0;\n\t\twhile(STRING::npos != (sloc = sval->find(\"@$\", sloc))) {\n\t\t\tint\tkylen = 0, value, endpos, kystart, fstart, fend;\n\t\t\tconst char *ptr = sval->c_str() + sloc + 2,\n\t\t\t\t*fmt = NULL;\n\n\t\t\tkystart = sloc+2;\n\t\t\tif (*ptr == '[') {\n\t\t\t\tfstart = kystart+1; fend = fstart;\n\t\t\t\tptr++; fmt = ptr;\n\t\t\t\tfor(; (*ptr)&&(*ptr != ']'); ptr++)\n\t\t\t\t\tfend++;\n\t\t\t\tassert(*ptr == ']');\n\t\t\t\tassert((*sval)[fend] == ']');\n\t\t\t\tptr++;\n\t\t\t\tkystart = fend+1;\n\t\t\t\tfend -= fstart;\n\t\t\t}\n\t\t\tif (*ptr == '(') {\n\t\t\t\tkystart++;\n\t\t\t\tptr++;\n\t\t\t\tif ((ptr[kylen] == '+')\n\t\t\t\t\t||(ptr[kylen] == '!')\n\t\t\t\t\t||(ptr[kylen] == '/'))\n\t\t\t\t\tkylen++;\n\t\t\t\tfor(; (ptr[kylen]); kylen++) {\n\t\t\t\t\tif((!isalpha(ptr[kylen]))\n\t\t\t\t\t\t&&(!isdigit(ptr[kylen]))\n\t\t\t\t\t\t&&(ptr[kylen] != '_')\n\t\t\t\t\t\t&&(ptr[kylen] != '.'))\n\t\t\t\t\tbreak;\n\t\t\t\t} endpos = kylen+1+kystart-sloc;\n\t\t\t\tif (ptr[kylen] != ')') {\n\t\t\t\t\tgbl_msg.error(\"%s <<--\\n\", sval->c_str());\n\t\t\t\t\tgbl_msg.error(\"Closing parentheses for %*s not found\\n\", kylen, ptr);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ((ptr[kylen] == '+')\n\t\t\t\t\t||(ptr[kylen] == '!')\n\t\t\t\t\t||(ptr[kylen] == '/'))\n\t\t\t\t\tkylen++;\n\t\t\t\tfor(; ptr[kylen]; kylen++) {\n\t\t\t\t\tif((!isalpha(ptr[kylen]))\n\t\t\t\t\t\t&&(!isdigit(ptr[kylen]))\n\t\t\t\t\t\t&&(ptr[kylen] != '_')\n\t\t\t\t\t\t&&(ptr[kylen] != '.'))\n\t\t\t\t\tbreak;\n\t\t\t\t} endpos = kylen+kystart-sloc;\n\t\t\t}\n\n\t\t\tif (kylen > 0) {\n\t\t\t\tSTRING key = sval->substr(kystart, kylen),\n\t\t\t\t\t*vstr;\n\t\t\t\tif ((fmt)&&(get_named_value(stack, *here,\n\t\t\t\t\t\tkey, value))) {\n\t\t\t\t\tchar\t*tbuf, *fcpy;\n\t\t\t\t\tfcpy = strdup(fmt); fcpy[fend]='\\0';\n\t\t\t\t\tSTRING\ttmp;\n\t\t\t\t\ttbuf = new char[fend+64];\n\t\t\t\t\tsprintf(tbuf, fcpy, value);\n\t\t\t\t\ttmp = tbuf;\n\t\t\t\t\tsval->replace(sloc, endpos, tmp);\n\t\t\t\t\tdelete[] fcpy;\n\t\t\t\t\tdelete[] tbuf;\n\t\t\t\t} else if (NULL != (vstr = get_named_string(\n\t\t\t\t\t\t\tstack, *here, key))) {\n\t\t\t\t\tsval->replace(sloc, endpos, *vstr);\n\t\t\t\t\tchanged = true;\n\t\t\t\t} else if(get_named_value(stack,*here,key,value)) {\n\t\t\t\t\tchar\tbuffer[64];\n\t\t\t\t\tSTRING\ttmp;\n\t\t\t\t\tsprintf(buffer, \"%d\", value);\n\t\t\t\t\ttmp = buffer;\n\t\t\t\t\tsval->replace(sloc, endpos, tmp);\n\t\t\t\t\tchanged = true;\n\t\t\t\t} else sloc++;\n\t\t\t} else sloc++;\n\t\t} everchanged = everchanged || changed;\n\t} while (changed);\n\n\treturn everchanged;\n}\n\nSTRINGP\tgenstr(STRING fmt, int val) {\n\tchar\t*buf = new char[fmt.size()+64];\n\tSTRINGP\tr;\n\n\tif (fmt.size() > 0) {\n\t\tsprintf(buf, fmt.c_str(), val);\n\t} else {\n\t\tsprintf(buf, \"%d\", val);\n\t}\n\n\tr = new STRING(buf);\n\tdelete[] buf;\n\treturn r;\n}\n\n// Return if anything changes\nbool\tresolve_ast_expressions(MAPDHASH &exmap) {\n\tMAPDHASH::iterator\tkvexpr, kvval, kvfmt, kvstr;\n\tMAPT\telm;\n\tSTRINGP\tstrp;\n\tAST\t*ast;\n\n\tkvexpr = exmap.find(KYEXPR);\n\tkvval  = exmap.find(KYVAL);\n\tkvfmt  = exmap.find(KYFORMAT);\n\tkvstr  = exmap.find(KYSTR);\n\n\tif (kvstr != exmap.end())\n\t\treturn false;\n\tif (kvexpr == exmap.end())\n\t\treturn false;\n\n\tif ((kvval != exmap.end())&&(kvval->second.m_typ == MAPT_INT)) {\n\t\tif((kvfmt != exmap.end())&&(kvfmt->second.m_typ == MAPT_STRING))\n\t\t\tstrp = genstr(*kvfmt->second.u.m_s,kvval->second.u.m_v);\n\t\telse\n\t\t\tstrp = genstr(STRING(\"\"),kvval->second.u.m_v);\n\t\tMAPT\telm;\n\t\telm.m_typ = MAPT_STRING;\n\t\telm.u.m_s = strp;\n\t\texmap.insert(KEYVALUE(KYSTR, elm));\n\n\t\treturn true;\n\t}\n\n\tif ((kvexpr != exmap.end())&&(kvexpr->second.m_typ == MAPT_STRING)) {\n\t\tAST *ast = parse_ast(*kvexpr->second.u.m_s);\n\t\tkvexpr->second.m_typ = MAPT_AST;\n\t\tkvexpr->second.u.m_a = ast;\n\t}\n\n\tif ((kvexpr != exmap.end())\n\t\t\t&&((kvexpr->second.m_typ == MAPT_AST)\n\t\t\t ||(kvexpr->second.m_typ == MAPT_INT))) {\n\t\tif (kvexpr->second.m_typ == MAPT_AST) {\n\t\t\tast = kvexpr->second.u.m_a;\n\t\t\tif (!ast->isdefined()) {\n\t\t\t\treturn false;\n\t\t\t} kvexpr->second.m_typ = MAPT_INT;\n\t\t\tkvexpr->second.u.m_v = ast->eval();\n\t\t\tdelete ast;\n\t\t}\n\n\t\telm.m_typ = MAPT_INT;\n\t\telm.u.m_v = kvexpr->second.u.m_v;\n\t\texmap.insert(KEYVALUE(KYVAL, elm));\n\n\t\tresolve_ast_expressions(exmap);\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nbool\tsubstitute_any_results_sub(MAPSTACK &stack, MAPDHASH *here,\n\t\tMAPDHASH &sub) {\n\tMAPDHASH::iterator\tpfx = sub.end(), subi, kvelm, kvstr, kvfmt;\n\tMAPDHASH\t*component;\n\tbool\t\tv = false;\n\n\tpfx = sub.find(KYPREFIX);\n\tif (pfx != sub.end())\n\t\tcomponent = &sub;\n\telse\n\t\tcomponent = here;\n\n\tfor(subi=sub.begin(); subi != sub.end(); subi++) {\n\t\tif (subi->second.m_typ == MAPT_MAP) {\n\t\t\tif ((KYPLUSDOT.compare(subi->first)!=0)\n\t\t\t\t&&(subi->first.size()>0)) {\n\t\t\tstack.push_back(subi->second.u.m_m);\n\t\t\tsubstitute_any_results_sub(stack, component,\n\t\t\t\t*subi->second.u.m_m);\n\t\t\tstack.pop_back();\n\t\t\tkvelm = subi->second.u.m_m->find(KYEXPR);\n\t\t\tkvstr  = subi->second.u.m_m->find(KYSTR);\n\t\t\tkvfmt  = subi->second.u.m_m->find(KYFORMAT);\n\t\t\tif ((kvstr == subi->second.u.m_m->end())\n\t\t\t\t&&(kvelm != subi->second.u.m_m->end())) {\n\t\t\t\tv = resolve_ast_expressions(*subi->second.u.m_m) || v;\n\t\t\t}\n\t\t\t}\n\t\t} else if (subi->second.m_typ == MAPT_STRING) {\n\t\t\tv = subresults_into(stack, here, subi->second.u.m_s) ||v;\n\t\t}\n\t} return v;\n}\n\nbool\tsubstitute_any_results(MAPDHASH &info) {\n\tMAPSTACK\tstack;\n\tstack.push_back(&info);\n\treturn substitute_any_results_sub(stack, &info, info);\n}\n\nvoid\treeval(MAPDHASH &info) {\n\tdo {\n\t\t// First, find expressions that need evalution\n\t\tfind_any_unevaluated(info);\n\t\t// Then, substitute their results back in as necessary\n\t} while(substitute_any_results(info));\n}\n\nvoid\treeval(MAPDHASH *info) {\n\tassert(info);\n\treeval(*info);\n}\n"
  },
  {
    "path": "sw/kveval.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/kveval.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tTo define the interface whereby values within the key-value hash\n//\t\tcan be both computed, and substituted/replaced as necessary.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tKVEVAL_H\n#define\tKVEVAL_H\n\n#include <vector>\n#include \"mapdhash.h\"\n#include \"globals.h\"\n\n#define\tREHASH\tdo { gbl_msg.info(\"REEVAL %s:%d\\n\", __FILE__, __LINE__); reeval(gbl_hash); gbl_msg.dump(*gbl_hash); } while(0)\ntypedef\tstd::vector<MAPDHASH *>\tMAPSTACK;\n\nbool\tget_named_kvpair(MAPSTACK &stack, MAPDHASH &here, STRING &key,\n\t\tMAPDHASH::iterator &pair);\nbool\tget_named_value(MAPSTACK &stack, MAPDHASH &here, STRING &key,\n\t\tint &value);\nSTRINGP\tget_named_string(MAPSTACK &stack, MAPDHASH &here, STRING &key);\n\nextern\tbool\tresolve_ast_expressions(MAPDHASH &info);\nextern\tvoid\treeval(MAPDHASH &info);\nextern\tvoid\treeval(MAPDHASH *info);\n\n#endif\n"
  },
  {
    "path": "sw/legalnotice.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/legalnotice.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tDefines a routine that can be used to copy a legal notice\n//\t\tinto a stream.  Modifications are made to the comments along\n//\tthe way, as appropriate for the type of stream.  Specific modifications\n//\tinclude:\n//\n//\tPlaces the name of the file at the top of the file, assuming a\n//\tFilename: key (as above) is found within the file.\n//\n//\tAdds the project name from the KYPROJECT key to the Project: line\n//\t(as above) the project name with the KYPROJECT\n//\n//\tPlaces a notice in the file that it was automatically generated.  This\n//\tnotice includes the autofpga command line.\n//\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <string.h>\n#include <unistd.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <limits.h>\n#include <ctype.h>\n\n#include \"mapdhash.h\"\n#include \"parser.h\"\n#include \"keys.h\"\n#include \"kveval.h\"\n#include \"msgs.h\"\n\nextern\tFILE *open_in(MAPDHASH &info, const STRING &fname);\n\n//\n// Place a legal notice at the top of every file.  The legal notice is given\n// to us as a filename, which we must then open and parse.\n//\n// We also do several substitutions here, given by the strings below.  This\n// allows us to mark all of our produced files with their names within them,\n// as well as marking the project that they are associated with.\n//\nvoid\tlegal_notice(MAPDHASH &info, FILE *fp, STRING &fname,\n\t\t\tconst char *cline = NULL,\n\t\t\tconst char *comment = \"//\") {\n\tchar\tline[512];\n\tFILE\t*lglfp;\n\tSTRING\tstr;\n\n\tSTRINGP\tlegal_fname = getstring(info, str = KYLEGAL);\n\tif (!legal_fname) {\n\t\tfprintf(stderr, \"WARNING: NO COPYRIGHT NOTICE\\n\\nPlease be considerate and license your project under the GPL\\n\");\n\t\tfprintf(fp, \"%s WARNING: NO COPYRIGHT NOTICE\\n\\n%s Please be considerate and license this under the GPL\\n\", comment, comment);\n\t\treturn;\n\t}\n\n\tlglfp = open_in(info, *legal_fname);\n\tif (!lglfp) {\n\t\tgbl_msg.error(\"Cannot open copyright notice file, %s\\n\", legal_fname->c_str());\n\t\tfprintf(fp, \"%s WARNING: NO COPYRIGHT NOTICE\\n\\n\"\n\t\t\t\"%s Please be considerate and license this project under the GPL\\n\", comment, comment);\n\t\tperror(\"O/S Err:\");\n\t\treturn;\n\t}\n\n\twhile(fgets(line, sizeof(line), lglfp)) {\n\t\tstatic const char\tkyfname[] = \"// Filename:\",\n\t\t\t\t\tkyproject[] = \"// Project:\",\n\t\t\t\t\tkycmdline[] = \"// CmdLine:\",\n\t\t\t\t\tkycomment[] = \"//\",\n\t\t\t\t\tkycline[] = \"///////////////////////////////////////////////////////////////////////\";\n\t\tif (strncasecmp(line, kyfname, strlen(kyfname))==0) {\n\t\t\tfprintf(fp, \"%s %s\\t%s\\n\", comment, &kyfname[3],\n\t\t\t\tfname.c_str());\n\t\t} else if (strncasecmp(line, kyproject, strlen(kyproject))==0) {\n\t\t\tSTRINGP\tstrp;\n\t\t\tif (NULL != (strp = getstring(info, KYPROJECT)))\n\t\t\t\tfprintf(fp, \"%s %s\\t%s\\n\", comment,\n\t\t\t\t\t&kyproject[3], strp->c_str());\n\t\t\telse\n\t\t\t\tfputs(line, fp);\n\t\t} else if (strncasecmp(line, kycmdline, strlen(kycmdline))==0){\n\t\t\tSTRINGP\tstrp = getstring(info, KYCMDLINE);\n\t\t\tif (strp)\n\t\t\t\tfprintf(fp, \"%s %s\\t%s\\n\", comment,\n\t\t\t\t\t&kycmdline[3], strp->c_str());\n\t\t\telse {\n\t\t\t\tfprintf(fp, \"%s\\t(No command line data found)\\n\",\n\t\t\t\t\tkycmdline);\n\t\t\t}\n\t\t}else if((cline)&&(strncmp(line, kycline, strlen(kycline))==0)){\n\t\t\tfprintf(fp, \"%s\\n\", cline);\n\t\t} else if (strncmp(line, kycomment, strlen(kycomment))==0) {\n\t\t\tfprintf(fp, \"%s%s\", comment, &line[strlen(kycomment)]);\n\t\t} else\n\t\t\tfputs(line, fp);\n\t}\n}\n\n"
  },
  {
    "path": "sw/legalnotice.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/legalnotice.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\t\n//\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tLEGALNOTICE_H\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n\n#include \"mapdhash.h\"\n#include \"parser.h\"\n\n// Insert a given legal notice into the FILE stream\n//\n// 1. We'll adjust the projuct line for the current project\n// 2. We'll also add a notice that the file so created was computer generated,\n//\tand thus should not be edited\n// 3. This notice will include our command line as well\n//\nextern\tvoid\tlegal_notice(MAPDHASH &info, FILE *fp, STRING &fname,\n\t\t\tconst char *cline = NULL,\n\t\t\tconst char *comment = \"//\");\n#endif\n"
  },
  {
    "path": "sw/mapdhash.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/mapdhash.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tTo handle processing our key-value pair data structure.  This\n//\t\tis the fundamental data structure used to maintain AutoFPGA's\n//\tdata store, and so it is used throughout.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"parser.h\"\n#include \"keys.h\"\n#include \"ast.h\"\n#include \"kveval.h\"\n#include \"globals.h\"\n#include \"msgs.h\"\n\nMAPT\toperator+(MAPT a, MAPT b) {\n\tchar\t*sbuf;\n\n\tswitch(a.m_typ) {\n\tcase MAPT_STRING:\n\t\tswitch(b.m_typ) {\n\t\tcase MAPT_STRING:\n\t\t\tsbuf = new char[a.u.m_s->length()\n\t\t\t\t\t+b.u.m_s->length()+4];\n\t\t\tsprintf(sbuf, \"%s %s\", a.u.m_s->c_str(),\n\t\t\t\tb.u.m_s->c_str());\n\t\t\ta.u.m_s = new STRING(sbuf);\n\t\t\tdelete sbuf;\n\t\t\tbreak;\n\t\tcase\tMAPT_INT:\n\t\t\tsbuf = new char[a.u.m_s->length()+32];\n\t\t\tsprintf(sbuf, \"%s + %d\", a.u.m_s->c_str(), b.u.m_v);\n\t\t\ta.u.m_s = new STRING(sbuf);\n\t\t\tdelete sbuf;\n\t\t\tbreak;\n\t\tcase\tMAPT_AST:\n\t\t\tfprintf(stderr, \"WARNING: Dont know how to add STRING to AST\\n\");\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tfprintf(stderr, \"WARNING: Dont know how to add STRING to other than INT or STRING\\n\");\n\t\t} break;\n\tcase MAPT_INT:\n\t\tswitch(b.m_typ) {\n\t\tcase MAPT_STRING:\n\t\t\ta.m_typ = MAPT_AST;\n\t\t\ta.u.m_a = new AST_BRANCH(\n\t\t\t\t'+', new AST_NUMBER(a.u.m_v),\n\t\t\t\tparse_ast(*b.u.m_s));\n\t\t\tbreak;\n\t\tcase MAPT_INT:\n\t\t\t// a.m_typ = MAPT_INT;\n\t\t\ta.u.m_v += b.u.m_v;\n\t\t\tbreak;\n\t\tcase MAPT_AST:\n\t\t\ta.m_typ = MAPT_AST;\n\t\t\ta.u.m_a = new AST_BRANCH(\n\t\t\t\t'+', new AST_NUMBER(a.u.m_v),\n\t\t\t\tb.u.m_a);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tfprintf(stderr, \"WARNING: Dont know how to add INT to a MAP\\n\");\n\t\t} break;\n\tcase MAPT_AST:\n\t\tswitch(b.m_typ) {\n\t\tcase MAPT_STRING:\n\t\t\ta.u.m_a = new AST_BRANCH( '+', a.u.m_a,\n\t\t\t\tparse_ast(*b.u.m_s));\n\t\t\tbreak;\n\t\tcase MAPT_INT:\n\t\t\ta.m_typ = MAPT_AST;\n\t\t\ta.u.m_a = new AST_BRANCH('+', a.u.m_a,\n\t\t\t\tnew AST_NUMBER(b.u.m_v));\n\t\t\tbreak;\n\t\tcase MAPT_AST:\n\t\t\ta.u.m_a = new AST_BRANCH('+', a.u.m_a, b.u.m_a);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tfprintf(stderr, \"WARNING: Dont know how to add AST to a MAP\\n\");\n\t\t} break;\n\tdefault:\n\t\tfprintf(stderr, \"1. DONT KNOW HOW TO ADD TWO MAPS TOGETHER (%d and %d)\\n\",\n\t\t\ta.m_typ, b.m_typ);\n\t\tif (a.m_typ == MAPT_MAP)\n\t\t\tmapdump(*a.u.m_m);\n\t\tif (b.m_typ == MAPT_MAP)\n\t\t\tmapdump(*b.u.m_m);\n\t}\n\n\treturn a;\n}\n\nMAPT\toperator+(MAPT a, const STRING b) {\n\tchar\t*sbuf;\n\n\tswitch(a.m_typ) {\n\tcase MAPT_STRING:\n\t\tsbuf = new char[a.u.m_s->length() +b.length()+4];\n\t\tsprintf(sbuf, \"%s %s\", a.u.m_s->c_str(), b.c_str());\n\t\ta.u.m_s = new STRING(sbuf);\n\t\tdelete sbuf;\n\t\tbreak;\n\tcase MAPT_INT:\n\t\ta.m_typ = MAPT_AST;\n\t\ta.u.m_a = new AST_BRANCH( '+', new AST_NUMBER(a.u.m_v),\n\t\t\tparse_ast(b));\n\t\tbreak;\n\tcase MAPT_AST:\n\t\ta.u.m_a = new AST_BRANCH( '+', a.u.m_a, parse_ast(b));\n\t\tbreak;\n\tdefault:\n\t\tfprintf(stderr, \"2. DONT KNOW HOW TO ADD A MAP TO A STRING (%d)\\n\", a.m_typ);\n\t\tmapdump(*a.u.m_m);\n\t}\n\n\treturn a;\n}\nSTRING\t*trim(const STRING &s) {\n\tconst char\t*a, *b;\n\tSTRINGP\t\tstrp;\n\ta = s.c_str();\n\tb = s.c_str() + s.length()-1;\n\n\tfor(; (*a)&&(a<=b); a++)\n\t\tif (!isspace(*a))\n\t\t\tbreak;\n\tfor(; (b>a); b--)\n\t\tif (!isspace(*b))\n\t\t\tbreak;\n\tstrp = new STRING(s.substr(a-s.c_str(), b-a+1));\n\treturn strp;\n}\n\nbool\tsplitkey(const STRING &ky, STRING &mkey, STRING &subky) {\n\tsize_t\tpos;\n\n\tif (((pos=ky.find('.')) != STRING::npos)\n\t\t\t&&(pos != 0)\n\t\t\t&&(pos < ky.length()-1)) {\n\t\tmkey = ky.substr(0,pos);\n\t\tsubky = ky.substr(pos+1,ky.length()-pos+1);\n\t\tassert(subky.length() > 0);\n\t\treturn true;\n\t} return false;\n}\n\nvoid\taddtomap(MAPDHASH &fm, STRING ky, STRING vl) {\n\tSTRING\tmkey, subky;\n\tSTRINGP\ttrimmed;\n\tbool\tastnode = false, pluskey = false;\n\tMAPT\tsubfm;\n\tMAPDHASH::iterator\tsubloc = fm.end();\n\n\ttrimmed = trim(ky);\n\tif ((*trimmed)[0] == '@') {\n\t\tSTRINGP\ttmp = new STRING(trimmed->substr(1));\n\t\tdelete trimmed;\n\t\ttrimmed = tmp;\n\t} if ((*trimmed)[0] == '$') {\n\t\tastnode = true;\n\t\tSTRINGP\ttmp = new STRING(trimmed->substr(1));\n\t\tdelete trimmed;\n\t\ttrimmed = tmp;\n\t} if (((*trimmed)[0] == '+')&&((*trimmed)[1]!='.')) {\n\t\tpluskey = true;\n\t\tSTRINGP\ttmp = new STRING(trimmed->substr(1));\n\t\tdelete trimmed;\n\t\ttrimmed = tmp;\n\t}\n\n\tif (splitkey(*trimmed, mkey, subky)) {\n\n\t\tMAPDHASH::iterator\tsubloc = fm.find(mkey);\n\t\tdelete\ttrimmed;\n\n\t\tif ((subloc == fm.end())&&(pluskey))\n\t\t\tsubloc = fm.find(STRING(\"+\")+mkey);\n\t\telse if (subloc == fm.end()) {\n\t\t\tsubloc = fm.find(STRING(\"+\")+mkey);\n\t\t\tif (subloc != fm.end()) {\n\t\t\t\t// REMOVE anything on conlict\n\t\t\t\tfm.erase(subloc);\n\t\t\t\tsubloc = fm.end();\n\t\t\t}\n\t\t}\n\n\t\tif (subloc == fm.end()) {\n\t\t\tsubfm.m_typ = MAPT_MAP;\n\t\t\tsubfm.u.m_m = new MAPDHASH;\n\t\t\tfm.insert(KEYVALUE(mkey, subfm ) );\n\t\t} else {\n\t\t\tsubfm = (*subloc).second;\n\t\t}\n\n\t\tif ((!pluskey)&&(subfm.m_typ != MAPT_MAP)) {\n\t\t\treturn;\n\t\t} else if (subfm.m_typ == MAPT_MAP) {\n\t\t\tif (pluskey)\n\t\t\t\tsubky = STRING(\"+\") + subky;\n\t\t\tif (astnode)\n\t\t\t\tsubky = STRING(\"$\") + subky;\n\t\t\taddtomap(*subfm.u.m_m, subky, vl);\n\t\t\treturn;\n\t\t}\n\t} else {\n\t\tsubloc = fm.find(*trimmed);\n\t\tif ((subloc == fm.end())&&(pluskey))\n\t\t\tsubloc = fm.find(STRING(\"+\")+(*trimmed));\n\t\tif(subloc != fm.end()) {\n\t\t\tsubfm = subloc->second;\n\t\t}\n\t}\n\n\tif ((astnode)&&(*trimmed != KYEXPR)) {\n\t\tif (subloc  == fm.end()) {\n\t\t\tMAPDHASH\t*node;\n\t\t\tMAPT\t\telm;\n\n\t\t\telm.m_typ = MAPT_MAP;\n\t\t\telm.u.m_m = node = new MAPDHASH;\n\t\t\tfm.insert(KEYVALUE(*trimmed, elm));\n\t\t\taddtomap(*node, STRING(\"$\")+STRING((pluskey)?\"+\":\"\")+KYEXPR, vl);\n\t\t\treturn;\n\t\t} else if (subfm.m_typ == MAPT_MAP) {\n\t\t\taddtomap(*subfm.u.m_m, STRING(\"$\")+STRING((pluskey)?\"+\":\"\")+KYEXPR, vl);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tMAPT\telm;\n\tif (pluskey) {\n\t\tif (subloc == fm.end()) {\n\n\t\t\tMAPT\telm;\n\t\t\tif (astnode) {\n\t\t\t\telm.m_typ = MAPT_AST;\n\t\t\t\telm.u.m_a = parse_ast(vl);\n\t\t\t} else {\n\t\t\t\telm.m_typ = MAPT_STRING;\n\t\t\t\telm.u.m_s = new STRING(vl);\n\t\t\t}\n\t\t\tfm.insert(KEYVALUE(STRING(\"+\")+(*trimmed), elm));\n\t\t} else {\n\t\t\tsubloc->second = subfm + vl;\n\t\t}\n\t} else if (astnode) {\n\t\tif ((*trimmed)!=KYEXPR) {\n\t\t\tMAPDHASH\t*node;\n\t\t\telm.m_typ = MAPT_MAP;\n\t\t\telm.u.m_m = node = new MAPDHASH;\n\t\t\tfm.insert(KEYVALUE(*trimmed, elm));\n\t\t\taddtomap(*node, STRING(\"$\")+STRING((pluskey)?\"+\":\"\")+KYEXPR, vl);\n\t\t} else {\n\t\t\telm.m_typ = MAPT_AST;\n\t\t\telm.u.m_a = parse_ast(vl);\n\t\t\tif (NULL == elm.u.m_a)\n\t\t\t\tgbl_msg.fatal(\"Could not parse %s\\n\", vl.c_str());\n\t\t\tfm.insert(KEYVALUE(*trimmed, elm ) );\n\t\t\tif ((elm.u.m_a->isdefined())&&(*trimmed == KYEXPR)) {\n\t\t\t\tAST *ast = elm.u.m_a;\n\t\t\t\telm.m_typ = MAPT_INT;\n\t\t\t\telm.u.m_v = (int)ast->eval();\n\t\t\t\tfm.insert(KEYVALUE(KYVAL, elm));\n\t\t\t} delete trimmed;\n\t\t\treturn;\n\t\t}\n\t} else if (subloc == fm.end()) {\n\t\telm.m_typ = MAPT_STRING;\n\t\telm.u.m_s = new STRING(vl);\n\t\tfm.insert(KEYVALUE(*trimmed, elm ) );\n\t} else {\n\t\tsubfm.m_typ = MAPT_STRING;\n\t\tsubfm.u.m_s = new STRING(vl);\n\t}\n\tdelete\ttrimmed;\n}\n\nvoid\tmapdump_aux(FILE *fp, MAPDHASH &fm, int offset) {\n\tMAPDHASH::iterator\tkvpair;\n\n\tif (!fp)\n\t\treturn;\n\n\tfor(kvpair = fm.begin(); kvpair != fm.end(); kvpair++) {\n\t\tif (offset == 0)\n\t\t\tfprintf(fp, \"\\n\");\n\t\tfprintf(fp, \"%*s%s: \", offset, \"\", (*kvpair).first.c_str());\n\t\tif ((*kvpair).second.m_typ == MAPT_MAP) {\n\t\t\tfprintf(fp, \"\\n\");\n\t\t\tmapdump_aux(fp, *(*kvpair).second.u.m_m, offset+1);\n\t\t} else if ((*kvpair).second.m_typ == MAPT_INT) {\n\t\t\tfprintf(fp, \"%d\\n\", (*kvpair).second.u.m_v);\n\t\t} else if ((*kvpair).second.m_typ == MAPT_AST) {\n\t\t\tAST\t*ast = kvpair->second.u.m_a;\n\t\t\tfprintf(fp, \"<AST>\");\n\t\t\tif (ast->isdefined()) {\n\t\t\t\tfprintf(fp, \"\\tDEFINED and = %08lx\\n\", ast->eval());\n\t\t\t} else\n\t\t\t\tfprintf(fp, \"\\tNot defined\\n\");\n\t\t\tast->dump(fp, offset+4);\n\t\t} else { // if ((*kvpair).second.m_typ == MAPT_STRING)\n\t\t\tSTRINGP\ts = (*kvpair).second.u.m_s;\n\t\t\tsize_t\tpos;\n\t\t\tif ((pos=s->find(\"\\n\")) == STRING::npos) {\n\t\t\t\tfprintf(fp, \"%s\\n\", s->c_str());\n\t\t\t} else if (pos == s->length()-1) {\n\t\t\t\tfprintf(fp, \"%s\", s->c_str());\n\t\t\t} else\t{\n\t\t\t\tfprintf(fp, \"<Multi-line-String>\\n\");\n\t\t\t\tfprintf(fp, \"%s\\n----------------\\n\", s->c_str());\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\tmapdump(FILE *fp, MAPDHASH &fm) {\n\tif (!fp)\n\t\treturn;\n\tfprintf(fp, \"\\n================\\nFULL HASH DUMP!!\\n================\\n\");\n\tmapdump_aux(fp, fm, 0);\n}\n\nvoid\tmapdump(MAPDHASH &fm) {\n\tmapdump_aux(stdout, fm, 0);\n}\n\nvoid\tmapdump(FILE *fp, MAPT &elm) {\n\tif (!fp)\n\t\treturn;\n\tswitch(elm.m_typ) {\n\tcase MAPT_STRING:\n\t\tfprintf(fp, \"DUMP: %s\\n\", elm.u.m_s->c_str()); fflush(fp);\n\t\tbreak;\n\tcase MAPT_INT:\n\t\tfprintf(fp, \"DUMP: %d\\n\", elm.u.m_v); fflush(fp);\n\t\tbreak;\n\tcase MAPT_AST:\n\t\tfprintf(fp, \"(AST)\\n\"); fflush(fp);\n\t\tbreak;\n\tcase MAPT_MAP:\n\t\tmapdump_aux(fp, *elm.u.m_m, 0); fflush(fp);\n\t\tbreak;\n\t}\n}\n\n//\n// Merge two maps, a master and a sub\n//\nvoid\tmergemaps(MAPDHASH &master, MAPDHASH &sub) {\n\tMAPDHASH::iterator\tkvmaster, kvsub;\n\n\tfor(kvsub = sub.begin(); kvsub != sub.end(); kvsub++) {\n\t\tbool\tpluskey;\n\t\tpluskey = (kvsub->first.c_str()[0] == '+');\n\t\tif (kvsub->second.m_typ == MAPT_MAP) {\n\t\t\tkvmaster = master.find(kvsub->first);\n\t\t\tif (kvmaster == master.end()) {\n\t\t\t\t// Not found\n\t\t\t\tmaster.insert(KEYVALUE((*kvsub).first,\n\t\t\t\t\t(*kvsub).second ) );\n\t\t\t} else if (kvmaster->second.m_typ == MAPT_MAP) {\n\t\t\t\tmergemaps(*kvmaster->second.u.m_m,\n\t\t\t\t\t*kvsub->second.u.m_m);\n\t\t\t} else {\n\t\t\t\tfprintf(stderr,\n\t\t\t\t\t\"NAME CONFLICT!  Files not merged\\n\");\n\t\t\t}\n\t\t} else if (pluskey) {\n\t\t\t// Does the key already exist in the map?\n\t\t\tif(kvsub->first.length() > 1) {\n\t\t\t\tkvmaster = master.find(kvsub->first.substr(1));\n\t\t\t\tif (kvmaster == master.end())\n\t\t\t\t\tkvmaster = master.find(kvsub->first);\n\t\t\t} else\n\t\t\t\tkvmaster = master.find(kvsub->first);\n\n\n\t\t\tif (kvmaster == master.end())\n\t\t\t\t// No, this key doesn't exist.  Let's insert it\n\t\t\t\tmaster.insert(KEYVALUE(kvsub->first, kvsub->second));\n\t\t\telse\n\t\t\t\tkvmaster->second = kvmaster->second + kvsub->second;\n\t\t} else\n\t\t\tmaster.insert(KEYVALUE(kvsub->first, kvsub->second));\n\t}\n}\n\n/*\n * trimkey\n *\n * Given a key to a string within the current map level, trim all spaces from\n * that key.  Do NOT recurse if the key is not found.\n */\nvoid\ttrimkey(MAPDHASH &mp, const STRING &sky) {\n\tMAPDHASH::iterator\tkvpair, kvsecond;\n\tSTRING\tmkey, subky;\n\n\tif (splitkey(sky, mkey, subky)) {\n\t\tif (mp.end() != (kvpair=mp.find(mkey))) {\n\t\t\tif (kvpair->second.m_typ == MAPT_MAP) {\n\t\t\t\ttrimkey(*kvpair->second.u.m_m, subky);\n\t\t\t}\n\t\t}\n\t} else for(kvpair = mp.begin(); kvpair != mp.end(); kvpair++) {\n\t\tif ((*kvpair).second.m_typ == MAPT_STRING) {\n\t\t\tif ((*kvpair).first == sky) {\n\t\t\t\tSTRINGP\ttmps = (*kvpair).second.u.m_s;\n\t\t\t\t(*kvpair).second.u.m_s = trim(*tmps);\n\t\t\t\tdelete tmps;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*\n * trimall\n *\n * Find all keys of the given name, then find the strings they refer to, then\n * trim any white space from those strings.\n */\nvoid\ttrimall(MAPDHASH &mp, const STRING &sky) {\n\tMAPDHASH::iterator\tkvpair, kvsecond;\n\tSTRING\tmkey, subky;\n\n\tif (splitkey(sky, mkey, subky)) {\n\t\tif (mp.end() != (kvpair=mp.find(mkey))) {\n\t\t\tif (kvpair->second.m_typ == MAPT_MAP) {\n\t\t\t\t// Cannot recurse further, else the key M.S\n\t\t\t\t// would cause keys M.*.S to be trimmed as well.\n\t\t\t\t// Hence we now force this to be an absolute\n\t\t\t\t// reference\n\t\t\t\ttrimkey(*kvpair->second.u.m_m, subky);\n\t\t\t}\n\t\t}\n\t} for(kvpair = mp.begin(); kvpair != mp.end(); kvpair++) {\n\t\tif ((*kvpair).second.m_typ == MAPT_MAP) {\n\t\t\ttrimall(*(*kvpair).second.u.m_m, sky);\n\t\t} else if ((*kvpair).second.m_typ == MAPT_STRING) {\n\t\t\tif ((*kvpair).first == sky) {\n\t\t\t\tSTRINGP\ttmps = (*kvpair).second.u.m_s;\n\t\t\t\t(*kvpair).second.u.m_s = trim(*tmps);\n\t\t\t\tdelete tmps;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*\n * trimbykeylist\n *\n * Look for all map elements with the given keylist, and apply trimall to\n * all elements within their respective maps\n */\nvoid\ttrimbykeylist(MAPDHASH &mp, const STRING &kylist) {\n\tSTRINGP\tstrp;\n\n\tif (NULL != (strp = getstring(mp, kylist))) {\n\t\tstatic const char delimiters[] = \" \\t\\n,\";\n\t\tSTRING scpy = *strp;\n\t\tchar\t*tok = strtok((char *)scpy.c_str(), delimiters);\n\n\t\twhile(NULL != tok) {\n\t\t\ttrimall(mp, STRING(tok));\n\t\t\ttok = strtok(NULL, delimiters);\n\t\t}\n\t}\n}\n\nvoid\ttrimbykeylist(MAPT &elm, const STRING &kylist) {\n\tif (elm.m_typ == MAPT_MAP)\n\t\ttrimbykeylist(*elm.u.m_m, kylist);\n}\n\n/*\n * cvtintbykeylist\n *\n * Very similar to trimbykeylist, save that in this case we use the keylist\n * to determine what to convert to integers.\n */\nvoid\tcvtintbykeylist(MAPDHASH &mp, const STRING &kylist) {\n\tSTRINGP\tstrp;\n\n\tif (NULL != (strp = getstring(mp, kylist))) {\n\t\tstatic const char delimiters[] = \" \\t\\n,\";\n\t\tSTRING scpy = *strp;\n\t\tchar\t*tok = strtok((char *)scpy.c_str(), delimiters);\n\n\t\twhile(NULL != tok) {\n\t\t\tcvtint(mp, STRING(tok));\n\t\t\ttok = strtok(NULL, delimiters);\n\t\t}\n\t}\n/*\n\tMAPDHASH::iterator\tkvpair;\n\tfor(kvpair=mp.begin(); kvpair != mp.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tcvtintbykeylist(kvpair->second, kylist);\n\t}\n*/\n}\n\nvoid\tcvtintbykeylist(MAPT &elm, const STRING &kylist) {\n\tif (elm.m_typ == MAPT_MAP)\n\t\tcvtintbykeylist(*elm.u.m_m, kylist);\n}\n\n/*\n * cvtint\n *\n * Traverse the map looking for all keys named sky, and convert them to\n * integer values\n */\nvoid\tcvtint(MAPDHASH &mp, const STRING &sky) {\n\tMAPDHASH::iterator\tkvpair;\n\tSTRING\tmkey, subky;\n\n\tif (splitkey(sky, mkey, subky)) {\n\t\tif (mp.end() != (kvpair=mp.find(mkey))) {\n\t\t\tif (kvpair->second.m_typ == MAPT_MAP) {\n\t\t\t\tcvtint(*kvpair->second.u.m_m, subky);\n\t\t\t}\n\t\t} else for(kvpair = mp.begin(); kvpair != mp.end(); kvpair++) {\n\t\t\tif (kvpair->second.m_typ == MAPT_MAP) {\n\t\t\t\tcvtint(*kvpair->second.u.m_m, sky);\n\t\t\t}\n\t\t}\n\t} else for(kvpair = mp.begin(); kvpair != mp.end(); kvpair++) {\n\t\tif ((*kvpair).second.m_typ == MAPT_MAP) {\n\t\t\tcvtint(*(*kvpair).second.u.m_m, sky);\n\t\t} else if ((*kvpair).second.m_typ == MAPT_STRING) {\n\t\t\tif ((*kvpair).first == sky) {\n\t\t\t\tSTRINGP\ttmps = (*kvpair).second.u.m_s;\n\t\t\t\t(*kvpair).second.m_typ = MAPT_INT;\n\t\t\t\t(*kvpair).second.u.m_v=strtoul(tmps->c_str(), NULL, 0);\n\t\t\t\tdelete tmps;\n\t\t\t}\n\t\t}\n\t}\n}\n\nMAPDHASH::iterator findkey_aux(MAPDHASH &master, const STRING &ky, const STRING &pre) {\n\tSTRING\tmkey, subky;\n\tMAPDHASH::iterator\tresult;\n\n\tif (splitkey(ky, mkey, subky)) {\n\t\tMAPDHASH::iterator\tsubloc = master.find(mkey);\n\t\tif (subloc == master.end()) {\n\t\t\t// Check any super classes for a definition of this key\n\t\t\tif ((master.end() != (subloc = master.find(KYPLUSDOT)))\n\t\t\t\t\t&&(subloc->second.m_typ == MAPT_MAP)) {\n\t\t\t\tresult = findkey_aux(*subloc->second.u.m_m, ky, pre);\n\t\t\t\tif (result == subloc->second.u.m_m->end())\n\t\t\t\t\treturn master.end();\n\t\t\t\treturn result;\n\t\t\t} return subloc;\n\t\t} else {\n\t\t\tMAPT\tsubfm;\n\t\t\tsubfm = (*subloc).second;\n\n\t\t\tif (subfm.m_typ != MAPT_MAP) {\n\t\t\t\t/*\n\t\t\t\tfprintf(stderr, \"ERR: MAP[%s.%s] isnt a map\\n\",\n\t\t\t\t\tpre.c_str(), mkey.c_str());\n\t\t\t\t*/\n\t\t\t\t// assert(subfm->m_typ == MAPT_MAP)\n\t\t\t\treturn master.end();\n\t\t\t}\n\n\t\t\t// printf(\"Recursing on %s\\n\", mkey.c_str());\n\t\t\tSTRING\tnew_pre_key = pre+\".\"+mkey;\n\t\t\tresult = findkey_aux(*subfm.u.m_m, subky, new_pre_key);\n\t\t\tif (result == subfm.u.m_m->end()) {\n\t\t\t\t// printf(\"Subkey not found\\n\");\n\t\t\t\treturn master.end();\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tresult = master.find(ky);\n\treturn\tresult;\n}\n\nMAPDHASH::iterator findkey(MAPDHASH &master, const STRING &ky) {\n\tSTRING\tempty(\"\");\n\treturn findkey_aux(master, ky, empty);\n}\n\nMAPDHASH *getmap(MAPDHASH &master, const STRING &ky) {\n\tMAPDHASH::iterator\tr;\n\n\tr = findkey(master, ky);\n\tif (r == master.end())\n\t\treturn NULL;\n\telse if (r->second.m_typ != MAPT_MAP)\n\t\treturn NULL;\n\treturn r->second.u.m_m;\n}\n\nMAPDHASH *getmap(MAPDHASH *mp, const STRING &ky) {\n\tif (!mp)\n\t\treturn NULL;\n\treturn getmap(*mp, ky);\n}\n\nSTRINGP getstring(MAPDHASH &m) {\n\tMAPDHASH::iterator\tr;\n\n\tresolve_ast_expressions(m);\n\n\t// Can we build this string?\n\tr = m.find(KYSTR);\n\tif (r != m.end()) {\n\t\tif (r->second.m_typ == MAPT_STRING)\n\t\t\treturn r->second.u.m_s;\n\t} return NULL;\n}\n\nSTRINGP getstring(MAPDHASH &master, const STRING &ky) {\n\tMAPDHASH::iterator\tr;\n\tSTRINGP\tprefix;\n\n\tr = findkey(master, ky);\n\tif (r == master.end())\n\t\treturn NULL;\n\telse if (r->second.m_typ == MAPT_MAP) {\n\t\t// MAPDHASH\t*m = r->second.u.m_m;\n\t\tSTRINGP\t\tstrp;\n\n\t\t// Check for a .STR key within this node\n\t\tstrp = getstring(master);\n\t\tif (NULL == strp) {\n\t\t\tMAPDHASH::iterator kvprefix= findkey(master, KYPREFIX);\n\n\t\t\tif ((kvprefix != master.end())&&(kvprefix->second.m_typ == MAPT_STRING))\n\t\t\t\tprefix = kvprefix->second.u.m_s;\n\t\t\telse\n\t\t\t\tprefix = new STRING(\"(Unknown context)\");\n\n\t\t\tgbl_msg.error(\"STRING expression for KEY \\\"%s\\\"\"\n\t\t\t\t\" in %s isnt a string!!\\n\\t... it's a map,\"\n\t\t\t\t\" with sub-elements\\n\", ky.c_str(),\n\t\t\t\tprefix->c_str());\n\t\t}\n\t\treturn strp;\n\t} else if (r->second.m_typ != MAPT_STRING) {\n\t\tMAPDHASH::iterator kvprefix= findkey(master, KYPREFIX);\n\n\t\tif ((kvprefix != master.end())&&(kvprefix->second.m_typ == MAPT_STRING))\n\t\t\tprefix = kvprefix->second.u.m_s;\n\t\telse\n\t\t\tprefix = new STRING(\"(Unknown context)\");\n\n\t\tgbl_msg.error(\"STRING expression for KEY \\\"%s\\\" in %s isnt a string!!\\n\", ky.c_str(), prefix->c_str());\n\t\treturn NULL;\n\t}\n\treturn r->second.u.m_s;\n}\n\nSTRINGP getstring(MAPDHASH *m, const STRING &ky) {\n\tif (!m)\n\t\treturn NULL;\n\treturn getstring(*m, ky);\n}\n\nSTRINGP getstring(MAPT &m, const STRING &ky) {\n\tif (m.m_typ != MAPT_MAP)\n\t\treturn NULL;\n\treturn getstring(*m.u.m_m, ky);\n}\n\nvoid setstring(MAPDHASH &master, const STRING &ky, STRINGP strp) {\n\tMAPDHASH::iterator\tkvpair, kvsub;\n\n\tif (strp == NULL) {\n\t\tassert(0);\n\t\treturn;\n\t}\n\n\tkvpair = findkey(master, ky);\n\tif (kvpair == master.end()) {\n\t\t// The given key was not found in the hash\n\t\tSTRING\tmkey, subky;\n\n\t\tif (splitkey(ky, mkey, subky)) {\n\t\t\tMAPT\tsubfm;\n\t\t\tMAPDHASH::iterator\tsubloc = master.find(mkey);\n\n\t\t\tif (subloc == master.end()) {\n\t\t\t\t// Create a map to hold our value\n\t\t\t\tsubfm.m_typ = MAPT_MAP;\n\t\t\t\tsubfm.u.m_m = new MAPDHASH;\n\t\t\t\tmaster.insert(KEYVALUE(mkey, subfm ) );\n\t\t\t} else {\n\t\t\t\t// The map exists, let's reference it\n\t\t\t\tsubfm = (*subloc).second;\n\t\t\t\tif (subfm.m_typ != MAPT_MAP) {\n\t\t\t\t\tfprintf(stderr, \"ERR: MAP[%s] isnt a map\\n\", mkey.c_str());\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} setstring(*subfm.u.m_m, subky, strp);\n\t\t\treturn;\n\t\t}\n\n\t\tMAPT\telm;\n\t\telm.m_typ = MAPT_STRING;\n\t\telm.u.m_s = strp;\n\t\tmaster.insert(KEYVALUE(ky, elm ) );\n\t} else if (kvpair->second.m_typ == MAPT_MAP) {\n\t\tMAPDHASH *subhash = kvpair->second.u.m_m;\n\t\tkvsub = subhash->find(KYSTR);\n\t\tif (kvsub == subhash->end()) {\n\t\t\tMAPT\telm;\n\t\t\telm.m_typ = MAPT_STRING;\n\t\t\telm.u.m_s = strp;\n\t\t\tkvsub->second.u.m_m->insert(KEYVALUE(KYVAL, elm));\n\t\t} else {\n\t\t\tkvsub->second.m_typ = MAPT_STRING;\n\t\t\tkvsub->second.u.m_s = strp;\n\t\t}\n\t} else if (kvpair->second.m_typ == MAPT_STRING) {\n\t\tkvpair->second.u.m_s = strp;\n\t}\n}\n\nvoid setstring(MAPDHASH &master, const STRING &ky, const STRING &str) {\n\treturn setstring(master, ky, new STRING(str));\n}\n\nvoid setstring(MAPDHASH *mp, const STRING &ky, STRINGP strp) {\n\tassert(mp);\n\treturn setstring(*mp, ky, strp);\n}\n\nvoid setstring(MAPDHASH *mp, const STRING &ky, const STRING &str) {\n\tassert(mp);\n\treturn setstring(*mp, ky, new STRING(str));\n}\n\nvoid\tsetstring(MAPT &m, const STRING &ky, STRINGP strp) {\n\tsetstring(*m.u.m_m, ky, strp);\n}\n\nbool getvalue(MAPDHASH &map, int &value) {\n\tMAPDHASH::iterator\tkvpair;\n\n\tkvpair = map.find(KYVAL);\n\tif (kvpair != map.end()) {\n\t\tvalue = kvpair->second.u.m_v;\n\t\treturn (kvpair->second.m_typ == MAPT_INT);\n\t}\n\tkvpair = map.find(KYEXPR);\n\tif (kvpair == map.end())\n\t\treturn false;\n\n\tif (kvpair->second.m_typ == MAPT_AST) {\n\t\tAST\t*ast;\n\t\tast = kvpair->second.u.m_a;\n\t\tif (ast->isdefined()) {\n\t\t\tkvpair->second.m_typ = MAPT_INT;\n\t\t\tkvpair->second.u.m_v = ast->eval();\n\t\t\tdelete ast;\n\t\t} else\n\t\t\treturn false;\n\t}\n\n\tif (kvpair->second.m_typ == MAPT_INT) {\n\t\t/*\n\t\tMAPT\telm;\n\t\telm.m_typ = MAPT_INT;\n\t\telm.u.m_v = kvpair->second.u.m_v;\n\t\tmap.insert(KEYVALUE(KYVAL, elm));\n\t\tvalue = elm.u.m_v;\n\t\t*/\n\t\tvalue=kvpair->second.u.m_v;\n\t\treturn true;\n\t} return false;\n}\n\nbool getvalue(MAPDHASH &master, const STRING &ky, int &value) {\n\tMAPDHASH::iterator\tr;\n\n\tvalue = -1;\n\n\tr = findkey(master, ky);\n\tif (r == master.end()) {\n\t\treturn false;\n\t} else if (r->second.m_typ == MAPT_MAP) {\n\t\treturn getvalue(*r->second.u.m_m, value);\n\t} else if (r->second.m_typ == MAPT_AST) {\n\t\tAST\t*ast = r->second.u.m_a;\n\t\tif (ast->isdefined()) {\n\t\t\tr->second.m_typ = MAPT_INT;\n\t\t\tr->second.u.m_v = ast->eval();\n\t\t\tdelete ast;\n\t\t} else\n\t\t\treturn false;\n\t} else if (r->second.m_typ == MAPT_STRING) {\n\t\tvalue = strtoul(r->second.u.m_s->c_str(), NULL, 0);\n\t\treturn true;\n\t} else if (r->second.m_typ != MAPT_INT) {\n\t\treturn false;\n\t}\n\tvalue = r->second.u.m_v;\n\treturn true;\n}\n\nbool getvalue(MAPDHASH *mp, const STRING &ky, int &value) {\n\tif (!mp)\n\t\treturn false;\n\treturn getvalue(*mp, ky, value);\n}\n\nvoid\tsetvalue(MAPDHASH &master, const STRING &ky, int value) {\n\tMAPDHASH::iterator\tkvpair, kvsub;\n\n\tkvpair = findkey(master, ky);\n\tif (kvpair == master.end()) {\n\t\tSTRING\tmkey, subky;\n\t\tSTRINGP\ttrimmed;\n\n\t\ttrimmed = trim(ky);\n\t\tif ((*trimmed)[0] == '@') {\n\t\t\tSTRINGP\ttmp = new STRING(trimmed->substr(1,trimmed->size()));\n\t\t\tdelete trimmed;\n\t\t\ttrimmed = tmp;\n\t\t} if ((*trimmed)[0] == '$') {\n\t\t\tSTRINGP\ttmp = new STRING(trimmed->substr(1,trimmed->size()));\n\t\t\tdelete trimmed;\n\t\t\ttrimmed = tmp;\n\t\t}\n\n\t\tif (splitkey(*trimmed, mkey, subky)) {\n\t\t\tMAPT\tsubfm;\n\t\t\tMAPDHASH::iterator\tsubloc = master.find(mkey);\n\t\t\tdelete\ttrimmed;\n\t\t\tif (subloc == master.end()) {\n\t\t\t\t// Create a map to hold our value\n\t\t\t\tsubfm.m_typ = MAPT_MAP;\n\t\t\t\tsubfm.u.m_m = new MAPDHASH;\n\t\t\t\tmaster.insert(KEYVALUE(mkey, subfm ) );\n\t\t\t} else {\n\t\t\t\t// The map exists, let's reference it\n\t\t\t\tsubfm = (*subloc).second;\n\t\t\t\tif (subfm.m_typ != MAPT_MAP) {\n\t\t\t\t\tfprintf(stderr, \"MAP[%s] isnt a map\\n\", mkey.c_str());\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} setvalue(*subfm.u.m_m, subky, value);\n\t\t\treturn;\n\t\t}\n\n\t\tMAPT\telm;\n\t\telm.m_typ = MAPT_INT;\n\t\telm.u.m_v = value;\n\t\tmaster.insert(KEYVALUE(*trimmed, elm ) );\n\t\tdelete\ttrimmed;\n\t} else if (kvpair->second.m_typ == MAPT_MAP) {\n\t\tMAPDHASH *subhash = kvpair->second.u.m_m;\n\t\tkvsub = subhash->find(KYVAL);\n\t\tif (kvsub == subhash->end()) {\n\t\t\tMAPT\telm;\n\t\t\telm.m_typ = MAPT_INT;\n\t\t\telm.u.m_v = value;\n\t\t\tkvsub->second.u.m_m->insert(KEYVALUE(KYVAL, elm));\n\t\t} else {\n\t\t\tkvsub->second.m_typ = MAPT_INT;\n\t\t\tkvsub->second.u.m_v = value;\n\t\t}\n\t}\n}\n\nMAPDHASH *copy(MAPDHASH *top) {\n\tMAPDHASH\t*cp = new MAPDHASH();\n\tMAPDHASH::iterator\tkvpair;\n\n\tfor(kvpair = top->begin(); kvpair != top->end(); kvpair++) {\n\t\tMAPT\telm;\n\n\t\telm.m_typ = kvpair->second.m_typ;\n\t\tif (kvpair->second.m_typ == MAPT_INT)\n\t\t\telm.u.m_v = kvpair->second.u.m_v;\n\t\telse if (kvpair->second.m_typ == MAPT_STRING)\n\t\t\telm.u.m_s = new STRING(*kvpair->second.u.m_s);\n\t\telse if (kvpair->second.m_typ == MAPT_MAP)\n\t\t\telm.u.m_m = copy(kvpair->second.u.m_m);\n\t\telse if (kvpair->second.m_typ == MAPT_AST)\n\t\t\telm.u.m_a = copy(kvpair->second.u.m_a);\n\t\telse {\n\t\t\tgbl_msg.fatal(\"in COPY(MAP)::UNKNOWN TYPE, %d\\n\", kvpair->second.m_typ);\n\t\t}\n\t\tcp->insert(KEYVALUE(kvpair->first, elm));\n\t} return cp;\n}\n\nvoid\tflatten_maps(MAPDHASH &node, MAPDHASH &sub, STRING &here) {\n\tMAPDHASH::iterator\tkvpair, nodepair;\n\n\tgbl_msg.info(\"FLATT-MAP\\n\");\n\t//\n\t// Search for subnodes that are not maps within node\n\t//\n\tfor(kvpair = sub.begin(); kvpair!=sub.end(); kvpair++) {\n\t\tnodepair = node.find(kvpair->first);\n\t\tif (nodepair == node.end()) {\n\t\t\t//\n\t\t\t// The subnode key, from a plus map, does not exist\n\t\t\t// in the parent.  Copy it into the parent therefore.\n\t\t\t//\n\t\t\tgbl_msg.info(\"Key not found, %s + %s, \"\n\t\t\t\t\t\"inheriting key\\n\", here.c_str(),\n\t\t\t\t\tkvpair->first.c_str());\n\t\t\tMAPT\telm;\n\n\t\t\telm.m_typ = kvpair->second.m_typ;\n\t\t\tif (kvpair->second.m_typ == MAPT_INT) {\n\t\t\t\t// Copy an integer key\n\t\t\t\telm.u.m_v = kvpair->second.u.m_v;\n\t\t\t} else if (kvpair->second.m_typ == MAPT_STRING) {\n\t\t\t\t// Copy a string\n\t\t\t\telm.u.m_s = new STRING(*kvpair->second.u.m_s);\n\t\t\t} else if (kvpair->second.m_typ == MAPT_MAP) {\n\t\t\t\t// Copy a MAP\n\t\t\t\telm.u.m_m = copy(kvpair->second.u.m_m);\n\t\t\t} else if (kvpair->second.m_typ == MAPT_AST) {\n\t\t\t\t// Copy a AST/expression\n\t\t\t\telm.u.m_a = copy(kvpair->second.u.m_a);\n\t\t\t} else\n\t\t\t\t// Otherwise, I have no idea what kind of\n\t\t\t\t// element this was.  BOMB!\n\t\t\t\tgbl_msg.fatal(\"FLATTEN(MAP)::UNKNOWN TYPE, %d\\n\",\n\t\t\t\t\tkvpair->second.m_typ);\n\n\t\t\t//\n\t\t\t// Put this newly copied key into the parent map.\n\t\t\t//\n\t\t\tnode.insert(KEYVALUE(kvpair->first, elm));\n\t\t} else if ((nodepair->second.m_typ==MAPT_MAP)&&(kvpair->second.m_typ == MAPT_MAP)) {\n\t\t\t// It's not uncommon to have a +.name.KEY.SUBKEY..etc\n\t\t\t// tag.  In that case, we need to get copy the\n\t\t\t// maps while preserving their structure\n\t\t\tSTRING\tnxt = here + \".\" + nodepair->first;\n\t\t\tgbl_msg.info(\"RECURSING TO COPY %s\\n\", nxt.c_str());\n\t\t\t// Recurse on both the node, and the subnode\n\t\t\tflatten_maps(*nodepair->second.u.m_m, *kvpair->second.u.m_m, nxt);\n\t\t} else {\n\t\t\tSTRING\tnkey = here + \".\" + nodepair->first;\n\t\t\tgbl_msg.info(\"IGNORING %s (already exists)\\n\",\n\t\t\t\tnkey.c_str());\n\t\t}\n\t}\n}\n\nvoid\tflatten_aux(MAPDHASH &master, MAPDHASH &sub, STRING &here) {\n\tMAPDHASH::iterator\tkvpair, kvsub, kvnxt;\n\n\tfor(kvpair=sub.begin(); kvpair != sub.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ == MAPT_MAP) {\n\t\t\tSTRING\tnkey = here + \".\" + STRING(kvpair->first);\n\n\t\t\tflatten_aux(master, *kvpair->second.u.m_m, nkey);\n\n\t\t\tif (kvpair->first == KYPLUSDOT) {\n\t\t\t    // Only if the key of this element is +\n\t\t\t    // do we need to recurse and copy keys beneath\n\t\t\t    // the plus into this primary location\n\t\t\t    //\n\t\t\t    kvsub = kvpair->second.u.m_m->begin();\n\t\t\t    kvnxt = kvsub; kvnxt++;\n\n\t\t\t    // Every +. key should contain its own map,\n\t\t\t    // and a single map within it.  Skip the extra\n\t\t\t    // recursion, and reference the map within only.\n\t\t\t    // First, though, assert this is the case.\n\t\t\t    assert(kvnxt == kvpair->second.u.m_m->end());\n\t\t\t    if (kvsub->second.m_typ == MAPT_MAP)\n\t\t\t\tflatten_maps(sub, *kvsub->second.u.m_m, nkey);\n\t\t\t    else\n\t\t\t\tflatten_maps(sub, *kvpair->second.u.m_m, nkey);\n\t\t\t}\n\t\t}\n\n\n\t\tif (kvpair->first.compare(KYPLUSDOT)==0) {\n\t\t\t\tSTRING\tikey = kvpair->first.substr(1);\n\t\t\t\tMAPDHASH::iterator\tkvprior;\n\n\t\t\t\tkvprior = sub.find(ikey);\n\t\t\t\tif (kvprior == master.end()) {\n\t\t\t\t\tsub.insert(KEYVALUE(ikey,\n\t\t\t\t\t\tkvpair->second));\n\t\t\t\t} else if ((kvpair->second.m_typ == kvprior->second.m_typ)\n\t\t\t\t\t&&(kvprior->second.m_typ == MAPT_STRING)) {\n\n\t\t\t\t\tSTRINGP\tpstr = kvprior->second.u.m_s;\n\t\t\t\t\tif (isspace((*pstr)[(*pstr).size()-1]))\n\n\t\t\t\t\t\t(*kvprior->second.u.m_s) = (*kvprior->second.u.m_s) + (*kvpair->second.u.m_s);\n\t\t\t\t\telse\n\t\t\t\t\t\t(*kvprior->second.u.m_s) = (*kvprior->second.u.m_s) + STRING(\" \") + (*kvpair->second.u.m_s);\n\t\t\t\t}\n\n/*\n\t\t\t\t// Can't delete the + sub hash, since we might\n\t\t\t\t// wish to reference it\n\t\t\t\tsub.erase(kvpair);\n\t\t\t\tkvpair = sub.begin();\n\t\t\t\tif (kvpair == sub.end())\n\t\t\t\t\tbreak;\n*/\n\n\t\t//else if((kvpair->first[0] == '/')&&(kvpair->first[1]=='+'))\n\t\t} else if (kvpair->first[0] == '/') {\n\t\t\tSTRING\tnkey = kvpair->first.substr(1);\n\t\t\tif (master.find(nkey) == master.end()) {\n\t\t\t\tmaster.insert(KEYVALUE(nkey, kvpair->second));\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\tflatten(MAPDHASH &master) {\n\tSTRING\ttop= STRING(\"\");\n\tflatten_aux(master, master, top);\n}\n\n"
  },
  {
    "path": "sw/mapdhash.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/mapdhash.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tTo define the data structures used to represent a parsed input\n//\t\tfile.  Of particular note is the key-value pair unordered map\n//\tstructure, and the components of that structure.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tMAPDHASH_H\n#define\tMAPDHASH_H\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include <string>\n#include <unordered_map>\n\n#define\tMAPT_INT\t0\n#define\tMAPT_STRING\t1\n#define\tMAPT_MAP\t2\n#define\tMAPT_AST\t3\n// Contains a \"soft-link\" to a hash entry, in other words, this is the \"name\" of another hash entry--one which we will use instead\n// #define\tMAPT_SLINK\t3\n\ntypedef\tstd::string *STRINGP, STRING;\ntypedef std::unordered_map<STRING,struct MAPT_S> MAPDHASH;\n\ntypedef\tstruct MAPT_S {\n\tint\tm_typ;\n\tunion {\n\t\tint\t\tm_v;\n\t\tSTRINGP\t\tm_s;\n\t\tMAPDHASH\t*m_m;\n\t\tclass AST\t*m_a;\t// Abstract syntax tree (uneval expr)\n\t\t// MAPDHASH\t*m_l;\t// link to elsewhere in the table\n\t} u;\n} MAPT;\n\ntypedef\tstd::pair<STRING,MAPT>\tKEYVALUE;\n\nextern\tSTRING *trim(const STRING &s);\nextern\tbool\tsplitkey(const STRING &ky, STRING &mkey, STRING &subky);\nextern\tvoid\taddtomap(MAPDHASH &fm, const STRING ky, STRING vl);\nextern\tvoid\tmapdump(MAPDHASH &fm);\nextern\tvoid\tmapdump(FILE *fp, MAPDHASH &fm);\nextern\tvoid\tmapdump(FILE *fp, MAPT &elm);\nextern\tvoid\tmergemaps(MAPDHASH &master, MAPDHASH &sub);\nextern\tvoid\tflatten(MAPDHASH &master);\nextern\tvoid\ttrimall(MAPDHASH &mp, const STRING &sky);\nextern\tvoid\ttrimbykeylist(MAPDHASH &mp, const STRING &skylist);\nextern\tvoid\ttrimbykeylist(MAPT &m, const STRING &skylist);\nextern\tvoid\tcvtint(MAPDHASH &mp, const STRING &sky);\nextern\tvoid\tcvtintbykeylist(MAPDHASH &mp, const STRING &skylist);\nextern\tvoid\tcvtintbykeylist(MAPT &m, const STRING &skylist);\nextern\tMAPDHASH::iterator\tfindkey(MAPDHASH &mp, const STRING &sky);\nextern\tMAPDHASH *getmap(MAPDHASH &mp, const STRING &ky);\nextern\tMAPDHASH *getmap(MAPDHASH *mp, const STRING &ky);\nextern\tSTRINGP\tgetstring(MAPDHASH &mp);\nextern\tSTRINGP\tgetstring(MAPDHASH &mp, const STRING &sky);\nextern\tSTRINGP\tgetstring(MAPDHASH *mp, const STRING &sky);\nextern\tSTRINGP\tgetstring(MAPT &m, const STRING &sky);\nextern\tvoid\tsetstring(MAPDHASH &mp, const STRING &sky, STRINGP strp);\nextern\tvoid\tsetstring(MAPDHASH &mp, const STRING &sky, const STRING &strp);\nextern\tvoid\tsetstring(MAPDHASH *mp, const STRING &sky, STRINGP strp);\nextern\tvoid\tsetstring(MAPDHASH *mp, const STRING &sky, const STRING &strp);\nextern\tvoid\tsetstring(MAPT &m, const STRING &sky, STRINGP strp);\nextern\tbool\tgetvalue(MAPDHASH &mp, int &value);\nextern\tbool\tgetvalue(MAPDHASH &mp, const STRING &sky, int &value);\nextern\tbool\tgetvalue(MAPDHASH *mp, const STRING &sky, int &value);\nextern\tvoid\tsetvalue(MAPDHASH &mp, const STRING &sky, int value);\n\n#endif // MAPDHASH\n"
  },
  {
    "path": "sw/mlist.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/mlist.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tAn MLIST is a list (i.e. std::vector<>) of bus masters.  This\n//\t\tfile defines the methods associated with such a list.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include \"parser.h\"\n#include \"mlist.h\"\n#include \"mapdhash.h\"\n#include \"keys.h\"\n#include \"predicates.h\"\n\nSTRINGP\t\tBMASTER::name(void) {\n\treturn getstring(*m_hash, KYPREFIX);\n}\n\nSTRINGP\t\tBMASTER::bus_prefix(void) {\n\tSTRINGP\tpfx;\n\n\tpfx = getstring(*m_hash, KYMASTER_PREFIX);\n\tif (NULL == pfx) {\n\t\tSTRINGP\tbus = getstring(*m_hash, KYMASTER_BUS_NAME);\n\t\tif (NULL == bus)\n\t\t\treturn NULL;\n\t\tpfx = new STRING(*bus + STRING(\"_\") + *name());\n\t\tsetstring(*m_hash, KYMASTER_PREFIX, pfx);\n\t}\n\treturn pfx;\n}\n\nbool\tBMASTER::read_only(void) {\n\tSTRINGP\toptions;\n\n\toptions = getstring(*m_hash, KYMASTER_OPTIONS);\n\tif (NULL != options)\n\t\treturn read_only_option(options);\n\treturn false;\n}\n\nbool\tBMASTER::write_only(void) {\n\tSTRINGP\toptions;\n\n\toptions = getstring(*m_hash, KYMASTER_OPTIONS);\n\tif (NULL != options)\n\t\treturn write_only_option(options);\n\treturn false;\n}\n"
  },
  {
    "path": "sw/mlist.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/mlist.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tAn MLIST is a list of bus masters.  This file defines the\n//\t\tmethods associated with such a list.\n//\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tMLIST_H\n#define\tMLIST_H\n\n#include <vector>\n\n#include \"parser.h\"\n\nclass\tBUSINFO;\n\n//\n// The MLIST, made of B(us)MASTER(s)\n//\n// A structure to contain information about lists of bus masters\n//\nclass\tBMASTER {\npublic:\n\tMAPDHASH\t*m_hash;\n\tSTRINGP\t\tname(void);\n\tSTRINGP\t\tbus_prefix(void);\n\tbool\t\tread_only(void);\n\tbool\t\twrite_only(void);\n\n\tBMASTER(MAPDHASH *hash) : m_hash(hash) {};\n};\n\ntypedef\tBMASTER *BMASTERP;\n\ntypedef\tstd::vector<BMASTERP> MLIST;\n\n// A pointer to a set of peripherals\ntypedef\tMLIST *MLISTP;\n\n#endif\t// MLIST_H\n"
  },
  {
    "path": "sw/msgs.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/msgs.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tA class for handling messages to the user\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdarg.h>\n#include \"msgs.h\"\n\nMSGS\tgbl_msg;\n\nvoid\tMSGS::open(const char *fname) {\n\tclose();\n\tm_dump = fopen(fname, \"w\");\n\n\tif (NULL == m_dump) {\n\t\tfprintf(stderr, \"ERR: Could not open %s\\n\", fname);\n\t\texit(EXIT_FAILURE);\n\t}\n}\n\nvoid\tMSGS::info(const char *fmt, ...) {\n\tva_list\targs;\n\n\tif (m_dump) {\n\t\tva_start(args, fmt);\n\t\tvfprintf(m_dump, fmt, args);\n\t\tva_end(args);\n\t}\n}\n\nvoid\tMSGS::userinfo(const char *fmt, ...) {\n\tva_list\targs;\n\n\tif (m_dump) {\n\t\tva_start(args, fmt);\n\t\tvfprintf(m_dump, fmt, args);\n\t\tva_end(args);\n\t}\n\n\tva_start(args, fmt);\n\tvfprintf(stdout, fmt, args);\n\tva_end(args);\n}\n\nvoid\tMSGS::warning(const char *fmt, ...) {\n\tconst\tchar\t*prefix = \"WARNING: \";\n\tva_list\targs;\n\n\tif (m_dump) {\n\t\tva_start(args, fmt);\n\t\tfprintf(m_dump, \"%s\", prefix);\n\t\tvfprintf(m_dump, fmt, args);\n\t\tva_end(args);\n\t}\n\n\tva_start(args, fmt);\n\tfprintf(stderr, \"%s\", prefix);\n\tvfprintf(stderr, fmt, args);\n\tva_end(args);\n}\n\nvoid\tMSGS::error(const char *fmt, ...) {\n\tconst char\t*prefix = \"ERR: \";\n\tva_list\targs;\n\n\tif (m_dump) {\n\t\tva_start(args, fmt);\n\t\tfprintf(m_dump, \"%s\", prefix);\n\t\tvfprintf(m_dump, fmt, args);\n\t\tva_end(args);\n\t}\n\n\tva_start(args, fmt);\n\tfprintf(stderr, \"%s\", prefix);\n\tvfprintf(stderr, fmt, args);\n\tva_end(args);\n\n\tm_err++;\n}\n\nvoid\tMSGS::fatal(const char *fmt, ...) {\n\tconst char\t*prefix = \"FATAL ERR: \";\n\tva_list\targs;\n\n\tif (m_dump) {\n\t\tva_start(args, fmt);\n\t\tfprintf(m_dump, \"%s\", prefix);\n\t\tvfprintf(m_dump, fmt, args);\n\t\tva_end(args);\n\t}\n\n\tva_start(args, fmt);\n\tfprintf(stderr, \"%s\", prefix);\n\tvfprintf(stderr, fmt, args);\n\tva_end(args);\n\n\texit(EXIT_FAILURE);\n}\n\nvoid\tMSGS::dump(MAPDHASH &map, const char *msg) {\n\tif (!m_dump)\n\t\treturn;\n\n\tfprintf(m_dump, \"%s\\n\", msg);\n\tmapdump(m_dump, map);\n}\n"
  },
  {
    "path": "sw/msgs.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/msgs.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tA class for handling messages to the user\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tMSGS_H\n#define\tMSGS_H\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include <string>\n#include <unordered_map>\n#include \"mapdhash.h\"\n\nclass\tMSGS {\n\tFILE\t*m_dump;\n\tint\tm_err;\npublic:\n\tMSGS(void) { m_err = 0; }\n\tvoid\topen(const char *fname);\n\tvoid\tclose(void) { if (m_dump) ::fclose(m_dump);  m_dump = NULL; };\n\tvoid\tflush(void) { if (m_dump) fflush(m_dump); }\n\t//\n\tvoid\tinfo(const char *, ...);\n\tvoid\tuserinfo(const char *, ...);\n\tvoid\twarning(const char *, ...);\n\tvoid\terror(const char *, ...);\n\t// void\toserr(const char *, ...);\n\tvoid\tfatal(const char *, ...);\n\tvoid\tdump(MAPDHASH &map, const char *msg = NULL);\n\tint\tstatus(void) { return (m_err)?EXIT_FAILURE : EXIT_SUCCESS; }\n};\n\nextern\tMSGS\tgbl_msg;\n\n#endif // MSGS\n"
  },
  {
    "path": "sw/parser.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/parser.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tTo parse an input file, and create a data structure of key-value\n//\t\tpairs from it.  Values of this structure may include other\n//\tkey-value pair sub-structures.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <assert.h>\n\n#include \"mapdhash.h\"\n#include \"parser.h\"\n#include \"keys.h\"\n#include \"msgs.h\"\n\nSTRING\t*rawline(FILE *fp) {\n\tchar\t\tlinebuf[512];\n\tSTRING\t\t*r = new STRING;\n\tchar\t\t *rv, *nl;\n\n\tdo {\n\t\trv = fgets(linebuf, sizeof(linebuf), fp);\n\t\tnl = strchr(linebuf, '\\n');\n\t\tif (rv)\n\t\t\tr->append(linebuf);\n\t} while((rv)&&(!nl));\n\n\t// If we didn't get anything, such as on an end of file, return NULL\n\t// that way we can differentiate an EOF or error from an empty line.\n\tif ((!rv)&&(r->length()==0)) {\n\t\tdelete r;\n\t\treturn NULL;\n\t}\n\n\treturn r;\n}\n\nSTRING\t*getline(FILE *fp) {\n\tSTRING\t*r;\n\tbool\tcomment_line;\n\n\tdo {\n\t\tr = rawline(fp);\n\t\tcomment_line = false;\n\t\tif ((r)&&(r->c_str()[0] == '#')) {\n\t\t\tif (isspace(r->c_str()[1]))\n\t\t\t\tcomment_line = true;\n\t\t\telse if (r->c_str()[1] == '#')\n\t\t\t\tcomment_line = true;\n\t\t}\n\t} while(comment_line);\n\n\treturn r;\n}\n\nbool\tiskeyline(STRING &s) {\n\tif (s.compare(0,3,STRING(\"@$(\"))==0)\n\t\treturn false;\n\treturn ((s[0] == '@')&&(s[1] != '@'));\n}\n\nMAPDHASH\t*genhash(STRING &prefix) {\n\tMAPDHASH\t*devm;\n\tMAPT\telm;\n\n\tdevm = new MAPDHASH();\n\telm.m_typ = MAPT_STRING;\n\telm.u.m_s = trim(prefix);\n\tdevm->insert(KEYVALUE(KYPREFIX,elm));\n\n\treturn devm;\n}\n\nMAPDHASH\t*gensubhash(MAPDHASH *top, STRING &prefix) {\n\tMAPDHASH\t*devm = NULL;\n\tSTRINGP\ttmp = trim(prefix);\n\n\t// This isn't any old key, this is a\n\t// prefix key.  All keys following will\n\t// be placed in the hierarchy beneath\n\t// this key.\n\tMAPDHASH::iterator\tkvpair;\n\tkvpair = top->find(*tmp);\n\tif (tmp->length() <= 0) {\n\t\tgbl_msg.fatal(\"EMPTY KEY\\n\");\n\t} else if (kvpair == top->end()) {\n\t\tSTRING\tkyp = STRING(*tmp);\n\t\tMAPT\telm;\n\n\t\tdevm = genhash(kyp);\n\n\t\telm.m_typ = MAPT_MAP;\n\t\telm.u.m_m = devm;\n\n\t\ttop->insert(KEYVALUE(kyp,elm));\n\t} else if (kvpair->second.m_typ == MAPT_MAP) {\n\t\tdevm = kvpair->second.u.m_m;\n\t} else {\n\t\tgbl_msg.fatal(\"NAME-CONFLICT!! (witin the same file, too!)\\n\");\n\t} delete tmp;\n\treturn devm;\n}\n\nMAPDHASH\t*parsefile(FILE *fp, const STRING &search);\n\nvoid\tprocess_keyvalue_pair(MAPDHASH *parent, const STRING &search, STRING &key, STRING &value) {\n\n\tif (key == KYINCLUDEFILE) {\n\t\tMAPDHASH\t*submap,\n\t\t\t\t*plusmap;\n\t\tMAPDHASH::iterator subp;\n\n\t\t// Read and insert the given file here\n\t\tsubmap= parsefile(value.c_str(), search);\n\n\t\t// If the file was found, as with the data within it, then ...\n\t\tif (submap != NULL) {\n\n\t\t\t// Read this file, creating a hash\n\t\t\tsubp = parent->find(KYPLUSDOT);\n\n\t\t\t// Declare everything within the file to be of the\n\t\t\t// sub-key \"+\" (KYPLUSDOT)\n\t\t\t//\n\t\t\tif (subp == parent->end()) {\n\t\t\t\tMAPT\telm;\n\t\t\t\telm.m_typ = MAPT_MAP;\n\t\t\t\tplusmap = new MAPDHASH;\n\t\t\t\telm.u.m_m = plusmap;\n\t\t\t\tparent->insert(KEYVALUE(KYPLUSDOT, elm));\n\t\t\t} else if (subp->second.m_typ != MAPT_MAP) {\n\t\t\t\tgbl_msg.error(\"KEY(+) EXISTS, AND ISN\\'T A MAP\\n\");\n\t\t\t} else {\n\t\t\t\tplusmap = subp->second.u.m_m;\n\t\t\t} if (plusmap)\n\t\t\t\tmergemaps(*plusmap, *submap);\n\t\t} // Otherwise ... (*TRY*) to ignore the error\n\t} else // If its a normal key, just add it to the map\n\t\taddtomap(*parent, key, value);\n}\n\n\nMAPDHASH\t*parsefile(FILE *fp, const STRING &search) {\n\tSTRING\t\tkey, value, *ln, prefix;\n\tMAPDHASH\t*fm = new MAPDHASH, *devm = NULL;\n\tsize_t\t\tpos;\n\n\tkey = \"\"; value = \"\";\n\twhile(NULL != (ln = getline(fp))) {\n\t\tif (iskeyline(*ln)) {\n\n\t\t\t// We may have a completed key-value pair that needs\n\t\t\t// to be stored.\n\t\t\tif (key.length() > 0) {\n\n\t\t\t\t// A key exists.  Let's store it.\n\n\t\t\t\t// If it's a PREFIX key, create a sub hash of\n\t\t\t\t// the FILE's hash\n\t\t\t\tif (key == KYPREFIX) {\n\t\t\t\t\tMAPDHASH\t*sub;\n\t\t\t\t\tsub = gensubhash(fm, value);\n\t\t\t\t\tif (sub)\n\t\t\t\t\t\tdevm = sub;\n\t\t\t\t}\n\n\t\t\t\tMAPDHASH\t*parent;\n\t\t\t\tif (devm)\n\t\t\t\t\tparent = devm;\n\t\t\t\telse\n\t\t\t\t\tparent = fm;\n\n\n\t\t\t\t// Process the old key\n\t\t\t\tprocess_keyvalue_pair(parent, search, key, value);\n\t\t\t}\n\n\t\t\t\t//\n\t\t\tif ((pos = ln->find(\"=\"))\n\t\t\t\t\t&&(pos != STRING::npos)) {\n\n\t\t\t\t// Separate the key from its value\n\t\t\t\tkey   = ln->substr(1, pos-1);\n\n\t\t\t\t// If we have a @KEY += line, then place the\n\t\t\t\t// plus in front of the key.  @+KEY is an\n\t\t\t\t// invalid key, so ... this should work.\n\t\t\t\tif (key.c_str()[(key.size())-1] == '+') {\n\t\t\t\t\t// Our key takes the + off the right,\n\t\t\t\t\t// and adds it to the left\n\t\t\t\t\tkey = STRING(\"+\")+key.substr(0,key.size()-1);\n\t\t\t\t}\n\n\t\t\t\t// Trim any whitespace from the key\n\t\t\t\tSTRINGP\ttrimd;\n\t\t\t\ttrimd = trim(key);\n\t\t\t\tkey   = STRING(*trimd);\n\t\t\t\tdelete\ttrimd;\n\n\t\t\t\t// Trim any whitespace from the value on this\n\t\t\t\t// line\n\t\t\t\ttrimd = trim(ln->substr(pos+1));\n\t\t\t\tvalue = STRING(*trimd);\n\t\t\t\tdelete\ttrimd;\n\t\t\t} else {\n\t\t\t\t// If we have a key with no \"=\" sign,\n\t\t\t\t// assume the whole line is the key.\n\t\t\t\t// Trim it up.\n\t\t\t\tkey = ln->substr(1, ln->length()-1);\n\t\t\t\tSTRINGP\ttrimd;\n\t\t\t\ttrimd = trim(key);\n\t\t\t\tkey   = STRING(*trimd);\n\t\t\t\tdelete trimd;\n\n\t\t\t\tgbl_msg.warning(\"Key line with no =, key was %s\\n\", key.c_str());\n\t\t\t\tvalue = \"\";\n\t\t\t}\n\n\t\t} else if (ln->c_str()[0]) {\n\t\t\tvalue = value + (*ln);\n\t\t}\n\n\t\tdelete ln;\n\t} if (key.length()>0) {\n\t\tif (key == KYPREFIX) {\n\t\t\tMAPDHASH\t*sub;\n\t\t\tsub = gensubhash(fm, value);\n\t\t\tif (sub)\n\t\t\t\tdevm = sub;\n\t\t}\n\n\n\t\tMAPDHASH\t*parent;\n\n\t\tif (devm)\n\t\t\tparent = devm;\n\t\telse\n\t\t\tparent = fm;\n\n\t\tprocess_keyvalue_pair(parent, search, key, value);\n\t}\n\n\treturn fm;\n}\n\nFILE\t*open_data_file(const char *fname) {\n\tstruct\tstat\tsb;\n\tif ((access(fname, R_OK)!=0)||(stat(fname, &sb) != 0)) {\n\t\treturn NULL;\n\t} else {\n\t\tif (sb.st_mode & S_IFREG)\n\t\t\treturn fopen(fname, \"r\");\n\t} return NULL;\n}\n\nFILE\t*search_and_open(const char *fname, const STRING &search) {\n\tFILE\t*fp = open_data_file(fname);\n\n\tif ((fp == NULL)&&(fname[0] != '/')&&(fname[0] != '.')) {\n\t\tSTRING\tcopy = search;\n\t\tchar\t*sub = (char *)copy.c_str();\n\t\tchar\t*dir = strtok(sub, \", \\t\\n:\");\n\t\twhile(dir != NULL) {\n\t\t\tchar\t*full = new char[strlen(fname)+2+strlen(dir)];\n\t\t\tstrcpy(full, dir);\n\t\t\tstrcat(full, \"/\");\n\t\t\tstrcat(full, fname);\n\t\t\tif (NULL != (fp=open_data_file(full))) {\n\t\t\t\tgbl_msg.info(\"Opened: %s\\n\", full);\n\t\t\t\tdelete[] full;\n\t\t\t\treturn fp;\n\t\t\t} delete[] full;\n\t\t\tdir = strtok(NULL, \", \\t\\n:\");\n\t\t}\n\n\t\tgbl_msg.error(\"Could not open %s\\nSearched through %s\\n\",\n\t\t\tfname, search.c_str());\n\t\treturn NULL;\n\t}\n\n\tgbl_msg.info(\"Directly opened: %s\\n\", fname);\n\treturn fp;\n}\n\nMAPDHASH\t*parsefile(const char *fname, const STRING &search) {\n\tMAPDHASH\t*map;\n\tFILE\t\t*fp = search_and_open(fname, search);\n\n\tif (fp == NULL) {\n\t\tgbl_msg.error(\"PARSE-ERR: Could not open %s\\n\"\n\t\t\t\"\\t  Searched through: %s\\n\", fname, search.c_str());\n\t\treturn NULL;\n\t} else {\n\t\tmap = parsefile(fp, search);\n\t\tfclose(fp);\n\n\t\treturn map;\n\t}\n}\n\nMAPDHASH\t*parsefile(const STRING &fname, const STRING &search) {\n\treturn parsefile((const char *)fname.c_str(), search);\n}\n\n"
  },
  {
    "path": "sw/parser.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/parser.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tTo define the processes used to parse a raw input file.  This\n//\t\tdoes not include the code necessary to evaluate any strings\n//\twithin that input file, only the code to turn the input file into\n//\tKEY-VALUE pairs. used by a parsed input file.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tPARSER_H\n#define\tPARSER_H\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"mapdhash.h\"\n\nextern\tSTRING\t*rawline(FILE *fp);\nextern\tSTRING\t*getline(FILE *fp);\nextern\tMAPDHASH\t*parsefile(FILE *fp, const STRING &search=\"\");\nextern\tMAPDHASH\t*parsefile(const char *fname, const STRING &search=\"\");\nextern\tMAPDHASH\t*parsefile(const STRING &fname, const STRING &search=\"\");\n\n#endif\n"
  },
  {
    "path": "sw/plist.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/plist.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tA PLIST is a list of peripherals (i.e. bus slaves, or components\n//\t\twith a SLAVE.BUS tag).  This file defines the methods associated\n//\twith such a list.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <string.h>\n#include <unistd.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <limits.h>\n#include <ctype.h>\n\n#include \"parser.h\"\n#include \"keys.h\"\n#include \"kveval.h\"\n#include \"plist.h\"\n#include \"bitlib.h\"\n#include \"businfo.h\"\n#include \"predicates.h\"\n#include \"subbus.h\"\n#include \"globals.h\"\n#include \"msgs.h\"\n\n\nbool\tPERIPH::issingle(void) {\n\tSTRINGP\tstr;\n\n\tif (!p_phash)\n\t\treturn false;\n\tif (NULL == (str = getstring(*p_phash, KYSLAVE_TYPE)))\n\t\treturn false;\n\tif (str->compare(KYSINGLE)!=0)\n\t\treturn false;\n\treturn true;\n}\n\nbool\tPERIPH::isdouble(void) {\n\tSTRINGP\tstr;\n\n\tif (!p_phash)\n\t\treturn false;\n\tif (NULL == (str = getstring(*p_phash, KYSLAVE_TYPE)))\n\t\treturn false;\n\tif (str->compare(KYDOUBLE)!=0)\n\t\treturn false;\n\tif (NULL != (str = getstring(*p_phash, KYERROR_WIRE)))\n\t\treturn false;\n\treturn true;\n}\n\nbool\tPERIPH::isbus(void) {\n\tSTRINGP\tstr;\n\n\tif (!p_phash)\n\t\treturn false;\n\tif (NULL == (str = getstring(*p_phash, KYSLAVE_TYPE)))\n\t\treturn false;\n\tif (str->compare(KYBUS)!=0)\n\t\treturn false;\n\treturn true;\n}\n\nbool\tPERIPH::ismemory(void) {\n\tSTRINGP\tstr;\n\n\tif (!p_phash)\n\t\treturn false;\n\tif (NULL == (str = getstring(*p_phash, KYSLAVE_TYPE)))\n\t\treturn false;\n\tif (str->compare(KYMEMORY)!=0)\n\t\treturn false;\n\treturn true;\n}\n\nunsigned PERIPH::get_slave_address_width(void) {\n\tunsigned\tawid, lgdw = 0;\n\n\tawid = nextlg(naddr());\n\tif (p_slave_bus != NULL && !p_slave_bus->word_addressing())\n\t\tlgdw = nextlg(p_slave_bus->data_width()/8);\n\tawid += lgdw;\n\n\tif (p_awid != (unsigned)awid) {\n\t\tp_awid = awid;\n\t\tsetvalue(*p_phash, KYSLAVE_AWID, awid);\n\t}\n\treturn p_awid;\n}\n\nunsigned PERIPH::naddr(void) {\n\tint\tvalue;\n\n\tassert(p_phash);\n\n\tif (getvalue(*p_phash, KYNADDR, value)) {\n\t\tbool rebuild = false;\n\t\tint\tlgdw = 0;\n\n\t\tif (p_slave_bus != NULL && !p_slave_bus->word_addressing())\n\t\t\tlgdw = nextlg(p_slave_bus->data_width()/8);\n\n\t\tif ((int)p_naddr != value) {\n\t\t\tgbl_msg.warning(\"%s's number of addresses changed from %ld to %d\\n\",\n\t\t\t\tp_name->c_str(), p_naddr, value);\n\t\t\tp_naddr = 0;\n\t\t}\n\t\tif (0 == p_naddr) {\n\t\t\t// Set p_naddr from value\n\n\t\t\tint\tlgaddr = nextlg(value);\n\n\t\t\tp_naddr = value;\n\t\t\tlgaddr += lgaddr + lgdw;\n\t\t\trebuild = true;\n\t\t\tp_awid  = lgaddr;\n\t\t}\n\t\tif (rebuild) {\n\t\t\tsetstring(p_phash, KYSLAVE_PORTLIST,\n\t\t\t\t\tp_slave_bus->slave_portlist(this));\n\t\t\tsetstring(p_phash, KYSLAVE_ANSIPORTLIST,\n\t\t\t\t\tp_slave_bus->slave_ansi_portlist(this));\n\t\t}\n\t\tif (!getstring(p_phash, KYSLAVE_IANSI)) {\n\t\t\tsetstring(p_phash, KYSLAVE_IANSI,\n\t\t\t\t\tp_slave_bus->slave_iansi(this));\n\t\t\trebuild = true;\n\t\t}\n\t\tif (!getstring(p_phash, KYSLAVE_OANSI)) {\n\t\t\tsetstring(p_phash, KYSLAVE_OANSI,\n\t\t\t\t\tp_slave_bus->slave_oansi(this));\n\t\t\trebuild = true;\n\t\t}\n\t\tif (!getstring(p_phash, KYSLAVE_ANSPREFIX)) {\n\t\t\tsetstring(p_phash, KYSLAVE_ANSPREFIX,\n\t\t\t\t\tp_slave_bus->slave_ansprefix(this));\n\t\t\trebuild = true;\n\t\t}\n\n\t\tif (rebuild)\n\t\t\treeval(p_phash);\n\t}\n\treturn p_naddr;\n}\n\nvoid\tPERIPH::integrity_check(void) {\n\tassert(NULL != p_name);\n\tassert(NULL != p_phash);\n\tassert(NULL != p_slave_bus);\n}\n\nSTRINGP\tPERIPH::bus_prefix(void) {\n\tSTRINGP\tpfx;\n\tpfx = getstring(p_phash, KYSLAVE_PREFIX);\n\tif (NULL == pfx) {\n\t\tSTRINGP\tbus = p_slave_bus->name();\n\t\tif (NULL == bus)\n\t\t\treturn NULL;\n\t\t// Assume a prefix if it isnt given\n\t\tpfx = new STRING(STRING(*bus)+STRING(\"_\")+STRING(*p_name));\n\t\tsetstring(p_phash, KYSLAVE_PREFIX, pfx);\n\t}\n\n\treturn pfx;\n}\n\nbool\tPERIPH::read_only(void) {\n\tSTRINGP\toptions;\n\n\toptions = getstring(*p_phash, KYSLAVE_OPTIONS);\n\tif (NULL != options)\n\t\treturn read_only_option(options);\n\treturn false;\n}\n\nbool\tPERIPH::write_only(void) {\n\tSTRINGP\toptions;\n\n\toptions = getstring(*p_phash, KYSLAVE_OPTIONS);\n\tif (NULL != options)\n\t\treturn write_only_option(options);\n\treturn false;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// Logic on sets of peripherals\n//\n////////////////////////////////////////////////////////////////////////////////\nvoid\tPLIST::integrity_check(void) {\n\tassert(NULL != this);\n\tfor(unsigned k=0; k<size(); k++) {\n\t\tPERIPHP\tpp = (*this)[k];\n\t\tpp->integrity_check();\n\t}\n}\n\n//\n// compare_naddr\n//\n// This is part of the peripheral sorting mechanism, whereby peripherals are\n// sorted by the numbers of addresses they use.  Peripherals using fewer\n// addresses are placed first, with peripherals using more addresses placed\n// later.\n//\nbool\tcompare_naddr(PERIPHP a, PERIPHP b) {\n\tif (!a)\n\t\treturn (b)?false:true;\n\telse if (!b)\n\t\treturn true;\n\n\t// Unordered items come before ordered items.\n\n\tbool\t\thave_order = false;\n\tint\t\taorder, border;\n\n\tif (a->p_phash == NULL) {\n\t\tgbl_msg.fatal(\"Peripheral %s has a null hash!\\n\", a->p_name->c_str());\n\t} if (b->p_phash == NULL) {\n\t\tgbl_msg.fatal(\"ERR: Peripheral %s has a null hash!\\n\", b->p_name->c_str());\n\t}\n\n\thave_order = getvalue(*a->p_phash, KYSLAVE_ORDER, aorder);\n\tif (have_order) {\n\t\thave_order = getvalue(*b->p_phash, KYSLAVE_ORDER, border);\n\t\tif (have_order)\n\t\t\treturn (aorder < border);\n\t\treturn false;\n\t} else if (getvalue(*b->p_phash, KYSLAVE_ORDER, border))\n\t\treturn true;\n\n\tunsigned\tanaddr, bnaddr;\n\n\tanaddr = a->get_slave_address_width();\n\tbnaddr = b->get_slave_address_width();\n\n\tif (anaddr != bnaddr)\n\t\treturn (anaddr < bnaddr);\n\t// Otherwise ... the two address types are equal.\n\tif ((a->p_name)&&(b->p_name))\n\t\treturn (a->p_name->compare(*b->p_name) < 0) ? true:false;\n\telse if (!a->p_name)\n\t\treturn true;\n\telse\n\t\treturn true;\n}\n\nbool\tcompare_address(PERIPHP a, PERIPHP b) {\n\tif (!a)\n\t\treturn (b)?false:true;\n\telse if (!b)\n\t\treturn true;\n\treturn (a->p_base < b->p_base);\n}\n\nbool\tcompare_regaddr(PERIPHP a, PERIPHP b) {\n\treturn (a->p_regbase < b->p_regbase);\n}\n\nint\tPLIST::add(PERIPHP p) {\n\t// To get here, the component must already have a valid hash\n\tassert(p->p_phash);\n\tpush_back(p);\n\treturn size()-1;\n}\n\n\n//\n// Add a peripheral to a given list of peripherals\nint\tPLIST::add(MAPDHASH *phash) {\n\tPERIPHP p;\n\tSTRINGP\tpname;\n\tint\tnaddr;\n\n\tpname  = getstring(*phash, KYPREFIX);\n\tif (!pname) {\n\t\tgbl_msg.warning(\"Skipping unnamed peripheral\\n\");\n\t\treturn -1;\n\t}\n\tif (!getvalue(*phash, KYNADDR, naddr)) {\n\t\tnaddr = 0;\n\t}\n\tif (issubbus(*phash)) {\n\t\tBUSINFO\t\t*bi;\n\t\tMAPDHASH::iterator\tkvmbus;\n\n\t\tkvmbus = findkey(*phash, KYMASTER_BUS);\n\t\tif (kvmbus != phash->end()) {\n\t\t\tbi = NULL;\n\t\t\tif (kvmbus->second.m_typ == MAPT_STRING)\n\t\t\t\tbi = find_bus(kvmbus->second.u.m_s);\n\t\t\telse if (kvmbus->second.m_typ == MAPT_MAP)\n\t\t\t\tbi = find_bus(kvmbus->second.u.m_m);\n\t\t\tassert(bi);\n\t\t}\n\t\tp = new SUBBUS(phash, bi->name(), bi);\n\t} else {\n\t\tp = new PERIPH;\n\t\tp->p_master_bus = NULL;\n\t}\n\n\tp->p_base = 0;\n\tp->p_naddr = naddr;\n\tp->p_phash = phash;\n\tp->p_name  = pname;\n\t{\n\t\tBUSINFO\t\t*bi;\n\t\tMAPDHASH::iterator\tkvsbus;\n\n\t\tkvsbus = findkey(*phash, KYSLAVE_BUS);\n\t\tassert(kvsbus != phash->end());\n\t\tassert(kvsbus->second.m_typ == MAPT_MAP);\n\t\tbi = find_bus(kvsbus->second.u.m_m);\n\t\tassert(bi);\n\t\tp->p_slave_bus = bi;\n\t}\n\tif (0 != naddr) {\n\t\t// Calculate and set p->p_awid\n\t\tp->get_slave_address_width();\n\t} else\n\t\tp->p_awid = 0;\n\n\n\t(void)p->bus_prefix();\n\n\tpush_back(p);\n\treturn size()-1;\n}\n\nbool\tPLIST::get_base_address(MAPDHASH *phash, unsigned &base) {\n\tfor(iterator p=begin(); p!=end(); p++) {\n\t\tif ((*p)->p_phash == phash) {\n\t\t\tbase = (*p)->p_base;\n\t\t\treturn true;\n\t\t} else if ((*p)->p_master_bus) {\n\t\t\tif ((*p)->p_master_bus->get_base_address(phash, base)){\n\t\t\t\tbase += (*p)->p_base;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\nunsigned\tPLIST::min_addr_size_bytes(const unsigned np,\n\t\t\t\tconst unsigned mina_bytes,\n\t\t\t\tconst unsigned nullsz_bytes) {\n\tunsigned\tstart = nullsz_bytes, pa, base_bytes;\n\n\tfor(unsigned i=0; i<np; i++) {\n\t\tpa = (*this)[i]->get_slave_address_width();\n\t\tif (pa <= 0)\n\t\t\tcontinue;\n\t\tif (pa < mina_bytes)\n\t\t\tpa = mina_bytes;\n\t\tbase_bytes = (start + ((1<<pa)-1));\n\t\tbase_bytes &= (-1<<pa);\n\t\t// First valid next address is ...\n\t\tstart = base_bytes + (1<<pa);\n\t}\n\t// Next address\n\treturn nextlg(start);\n}\n\nunsigned\tPLIST::min_addr_size_octets(unsigned np,\n\t\t\t\tunsigned mina, unsigned nullsz,\n\t\t\t\tunsigned daddr) {\n\tunsigned\tmna = mina - daddr,\n\t\t\tnullszb;\n\n\tif (mna < 1)\n\t\tmna = 1;\n\tnullszb = nullsz >> daddr;\n\tmna = min_addr_size_bytes(np, mna, nullszb);\n\tmna += daddr;\n\treturn mna;\n}\n\nextern bool gbl_ready_for_address_assignment;\nvoid\tPLIST::assign_addresses(unsigned dwidth, unsigned nullsz,\n\t\tunsigned bus_min_address_width) {\n\tunsigned daddr_abits = nextlg(dwidth/8);\n\n\tassert(gbl_ready_for_address_assignment);\n\n\t// Use daddr_abits to convert our addresses between bus addresses and\n\t// byte addresses.  The address width involved is in bus words,\n\t// whereeas the base address needs to be in octets.  NullSz is also\n\t// in octets.\n\tif (size() < 1) {\n\t\tif (nullsz > 0)\n\t\t\tm_address_width = nextlg(nullsz);\n\t\telse\n\t\t\tm_address_width = 0;\n\t\treturn;\n\t} else if ((size() < 2)&&(nullsz == 0)) {\n\t\tPERIPHP\tp = (*this)[0];\n\t\tMAPDHASH\t*ph = p->p_phash;\n\t\tGENBUS\t\t*g = p->p_slave_bus->generator();\n\n\t\tp->p_base = 0;\n\t\tp->p_mask = 0;\n\t\tsetvalue(*p->p_phash, KYBASE, p->p_base);\n\t\tsetvalue(*p->p_phash, KYMASK, p->p_mask);\n\t\tm_address_width = p->get_slave_address_width();\n\t\tif (m_address_width <= 0) {\n\t\t\tgbl_msg.error(\"Slave %s has zero NADDR (now address assigned)\\n\",\n\t\t\t\tp->p_name->c_str());\n\t\t}\n\n\t\tif (g) {\n\t\t\tsetstring(*ph, KYSLAVE_PORTLIST,\n\t\t\t\tg->slave_portlist(p));\n\t\t\tsetstring(*ph, KYSLAVE_ANSIPORTLIST,\n\t\t\t\tg->slave_ansi_portlist(p));\n\t\t\tif (!getstring(*ph, KYSLAVE_IANSI))\n\t\t\t\tsetstring(*ph, KYSLAVE_IANSI, g->iansi(NULL));\n\t\t\tif (!getstring(*ph, KYSLAVE_OANSI))\n\t\t\t\tsetstring(*ph, KYSLAVE_OANSI, g->oansi(NULL));\n\t\t\tif (!getstring(*ph, KYSLAVE_ANSPREFIX))\n\t\t\t\tsetstring(*ph, KYSLAVE_ANSPREFIX,\n\t\t\t\t\t\t\tg->slave_ansprefix(p));\n\t\t\treeval(*ph);\n\t\t}\n\t} else {\n\t\tbool\tm_full_decode = false;\n\n\t\tassert((*this)[0]->p_slave_bus);\n\t\tif (!(*this)[0]->p_slave_bus->word_addressing())\n\t\t\tdaddr_abits = 0;\n\n\t\t// We'll need a minimum of nextlg(p->size()) bits to address\n\t\t// p->size() separate peripherals.  While we'd like to minimize\n\t\t// the number of bits we use to do this, adding one extra bit\n\t\t// in to the minimum number of bits required gives us a little\n\t\t// bit of flexibility while also attempting to keep our bus\n\t\t// width to a minimum.\n\t\tunsigned long start_address = nullsz;\n\t\tunsigned long min_awd, min_asz;\n\n\t\t// Sort our peripherals by the number of address lines they\n\t\t// will be using.  At the end of this, we'll know that we'll\n\t\t// need a minimum of (*p)[p->size()-1]->p_awid+1 address lines.\n\t\tsort(begin(), end(), compare_naddr);\n\n\t\t//\n\t\t// We've got two Goals:\n\t\t//\n\t\t// #1 Keep the bus address width to a minimum\n\t\t// #2 Keep the LUTs required to a minimum\n\t\t//\n\t\t// Hence, let's try adjusting the minimum address difference\n\t\t// between peripherals to find the minimum #2, subject to\n\t\t// having found the minimum of #1\n\n\t\t// Let's start by calculating the number of bits we will need\n\t\t// if we don't do anything smart\n\t\tmin_awd = (*this)[size()-1]->get_slave_address_width()\n\t\t\t\t+ daddr_abits;\n\t\tmin_asz = min_addr_size_octets(size(), min_awd,\n\t\t\t\tnullsz, daddr_abits);\n\t\tif (min_asz < bus_min_address_width)\n\t\t\tmin_asz = bus_min_address_width;\n\t\t// Our goal will be to do better than this\n\n\t\tfor(iterator p=begin(); p!=end(); p++) {\n\t\t\t// Make certain all of our slaves have at least\n\t\t\t// one address location assigned to them, generate\n\t\t\t// an error if not\n\t\t\tif ((*p)->naddr() <= 0) {\n\t\t\t\tgbl_msg.error(\"Slave %s has zero \"\n\t\t\t\t\t\"NADDR (now address assigned)\\n\",\n\t\t\t\t\t(*p)->p_name->c_str());\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t// Minimize the address width\n\t\t//\n\t\tunsigned\tmin_relevant = 32-daddr_abits;\n\t\tfor(unsigned mina = daddr_abits+1; mina < 32-daddr_abits;\n\t\t\t\t\t\tmina++) {\n\t\t\t//\n\t\t\tunsigned\ttotal_address_width,\n\t\t\t\t\trelevant_address_bits;\n\n\t\t\t//\n\t\t\ttotal_address_width = min_addr_size_octets(size(),\n\t\t\t\t\tmina, nullsz, daddr_abits);\n\t\t\trelevant_address_bits = total_address_width - mina;\n\n\t\t\tif (total_address_width > min_asz) {\n\t\t\t\t// Never increase our # of address lines\n\t\t\t} else if (relevant_address_bits < min_relevant) {\n\t\t\t\tmin_asz = total_address_width;\n\t\t\t\tmin_relevant = relevant_address_bits;\n\t\t\t\tmin_awd = mina;\n\t\t\t}\n\t\t}\n\n\t\t//\n\t\t// Now we're ready to do the actual address assignment\n\t\t//\n\t\t// We'll do the calculation in calculation in octets, where\n\t\t// the conversion from the one to the next is daddr_abits--the\n\t\t// number of address bits required to advance one bus word.\n\n\t\t// We'll start assigning addresses after skipping some number\n\t\t// of addresses assigned to the null address.  This is user\n\t\t// selectable, and may be zero.\n\t\tstart_address = nullsz;\n\t\tfor(unsigned i=0; i<size(); i++) {\n\t\t\tunsigned\tpa, pfull, pmsk;\n\n\t\t\t// pa is the width in the number of address bits\n\t\t\t// required to address one octet of this peripheral.\n\t\t\tpfull=(*this)[i]->get_slave_address_width()+daddr_abits;\n\t\t\tpa = pfull;\n\t\t\tif (pa <= 0) {\n\t\t\t\t// p_base is in octets\n\t\t\t\t(*this)[i]->p_base = start_address;\n\t\t\t\t(*this)[i]->p_mask = 0;\n\t\t\t} else {\n\t\t\t\t//\n\t\t\t\t// If our address increment is smaller than the\n\t\t\t\t// minimum increment we calculated above, then\n\t\t\t\t// bump it up to that minimum increment\n\t\t\t\tif (pa < min_awd)\n\t\t\t\t\tpa = min_awd;\n\n\t\t\t\t// p_base is the base address of this\n\t\t\t\t// peripheral, expressed in octets\n\t\t\t\t(*this)[i]->p_base =start_address+((1ul<<pa)-1);\n\t\t\t\t//\n\t\t\t\t// Trim p_base back down to just the addresses\n\t\t\t\t// we'd use--that way the upper address bits\n\t\t\t\t// don't change across this peripherals address\n\t\t\t\t// range\n\t\t\t\t(*this)[i]->p_base &= (-1l<<pa);\n\t\t\t\t//\n\t\t\t\t// Now, advance the start address to the next\n\t\t\t\t// open address after this peripheral\n\t\t\t\tstart_address = (*this)[i]->p_base + (1ul<<pa);\n\n\t\t\t\t//\n\t\t\t\t// p_mask are the bits that matter when decoding\n\t\t\t\t// this peripheral.  It's basically all ones\n\t\t\t\t// up-shifted by the number of bits this\n\t\t\t\t// peripheral uses--we'll trim it back down\n\t\t\t\t// to the minimum required bits in a mask in\n\t\t\t\t// a moment\n\t\t\t\tpmsk = (m_full_decode) ? pfull : pa;\n\t\t\t\t(*this)[i]->p_mask = (-1)<<(pmsk-daddr_abits);\n\t\t\t\tassert((*this)[i]->p_mask != 0);\n\t\t\t}\n\t\t}\n\t\tassert(start_address != 0);\n\n\t\tunsigned master_mask = nextlg(start_address);\n\t\tmaster_mask = (1u << (master_mask-daddr_abits))-1;\n\n\t\t// One more pass, now that we know the last address\n\t\tfor(unsigned i=0; i<size(); i++) {\n\n\t\t\t//\n\t\t\t// Trim the bits necessary to express the relevant\n\t\t\t// bits of this address\n\t\t\t(*this)[i]->p_mask &= master_mask;\n\n\t\t\tgbl_msg.info(\"  %20s -> %08lx & 0x%08lx\\n\",\n\t\t\t\t\t(*this)[i]->p_name->c_str(),\n\t\t\t\t\t(*this)[i]->p_base,\n\t\t\t\t\t(*this)[i]->p_mask << daddr_abits);\n\n\t\t\tif ((*this)[i]->p_phash) {\n\t\t\t\tPERIPHP\tp = (*this)[i];\n\t\t\t\tMAPDHASH\t*ph = p->p_phash;\n\t\t\t\tGENBUS\t\t*g = p->p_slave_bus->generator();\n\t\t\t\tsetvalue(*ph, KYBASE, p->p_base);\n\t\t\t\tsetvalue(*ph, KYMASK, p->p_mask << daddr_abits);\n\t\t\t\tif (g) {\n\t\t\t\t\tsetstring(*ph, KYSLAVE_PORTLIST,\n\t\t\t\t\t\tg->slave_portlist(p));\n\t\t\t\t\tsetstring(*ph, KYSLAVE_ANSIPORTLIST,\n\t\t\t\t\t\tg->slave_ansi_portlist(p));\n\t\t\t\t\tif (!getstring(*ph, KYSLAVE_IANSI))\n\t\t\t\t\t\tsetstring(*ph, KYSLAVE_IANSI,\n\t\t\t\t\t\t\tg->iansi(NULL));\n\t\t\t\t\tif (!getstring(*ph, KYSLAVE_OANSI))\n\t\t\t\t\t\tsetstring(*ph, KYSLAVE_OANSI,\n\t\t\t\t\t\t\tg->oansi(NULL));\n\t\t\t\t\tif (!getstring(*ph, KYSLAVE_ANSPREFIX))\n\t\t\t\t\t\tsetstring(*ph, KYSLAVE_ANSPREFIX,\n\t\t\t\t\t\t\tg->slave_ansprefix(p));\n\t\t\t\t\treeval(*ph);\n\t\t\t\t}\n\t\t\t}\n\t\t} m_address_width = nextlg(start_address)-daddr_abits;\n\t}\n\n\treeval(gbl_hash);\n}\n"
  },
  {
    "path": "sw/plist.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/plist.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tA PLIST is a list (C++ vector) of bus slaves, herein called\n//\t\tperipherals.  This file defines the methods associated with\n//\tsuch a list.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tPLIST_H\n#define\tPLIST_H\n\n#include <vector>\n\n#include \"parser.h\"\n\nclass\tBUSINFO;\n\n//\n// The PLIST, made of PERIPH(erals)\n//\n// A structure to contain information about lists of peripherals\n//\nclass\tPERIPH {\npublic:\n\tunsigned long\tp_base, p_regbase;\t// In octets\n\tunsigned long\tp_naddr;\t// In words, given in file\n\t//\n\t// p_awid = number of address lines for this slave\n\t//\tIn word addressing, this is log_2(p_naddr)\n\t//\tOtherwise, its defined as log_2(p_naddr * bus->data_width()/8)\n\t//   This is on the *slave* bus.  For subbus's, it may not be the same\n\t//\tas the width on the *master* bus.\n\tunsigned\tp_awid;\t\t//\n\tunsigned long\tp_mask;\t\t// Words.  Bit is true if relevant for address selection\n\t//\n\tunsigned\tp_sbaw;\n\tSTRINGP\t\tp_name;\n\tMAPDHASH\t*p_phash;\n\tBUSINFO\t\t*p_slave_bus;\t// We are a slave of this bus\n\tBUSINFO\t\t*p_master_bus;\t// We might master this bus beneath us\n\n\tSTRINGP\tname(void) { return p_name; };\n\tvirtual\tbool\tissingle(void);\n\tvirtual\tbool\tisdouble(void);\n\tvirtual\tbool\tisbus(void);\n\tvirtual\tbool\tismemory(void);\n\tvirtual\tbool\tread_only(void);\n\tvirtual\tbool\twrite_only(void);\n\tvirtual unsigned get_slave_address_width(void);\n\t\tunsigned awid(void) { return get_slave_address_width(); }\n\t\tunsigned naddr(void);\n\tvirtual\tvoid\tintegrity_check(void);\n\tSTRINGP\tbus_prefix(void);\n};\n\ntypedef\tPERIPH *PERIPHP;\n\nclass\tPLIST : public std::vector<PERIPHP> {\n\tunsigned\tm_address_width;\npublic:\n\tPLIST(void) {}\n\tSTRINGP\t\tm_stype;\n\n\tvoid\tset_stype(STRING &stype);\n\t//\n\t// Add a peripheral to a given list of peripherals\n\tint\tadd(MAPDHASH *phash);\n\tint\tadd(PERIPHP p);\n\tvoid\tassign_addresses(unsigned dwidth, unsigned nullsz = 0,\n\t\t\t\tunsigned bus_min_address_width = 0);\n\tbool\tget_base_address(MAPDHASH *phash, unsigned &base);\n\tunsigned\tmin_addr_size_bytes(unsigned, unsigned,\n\t\t\t\tunsigned nullsz=0);\n\tunsigned\tmin_addr_size_octets(unsigned, unsigned,\n\t\t\t\tunsigned nullsz=0,\n\t\t\t\tunsigned daddr=2);\n\tunsigned get_address_width(void) {\n\t\treturn m_address_width;\n\t}\n\tvoid\tintegrity_check(void);\n\t/*\n\tvoid\tremove(std::vector<PERIPHP>::iterator ptr) {\n\t\tstd::vector<PERIPHP>::remove(ptr);\n\t}\n\t*/\n};\n\n// A pointer to a set of peripherals\ntypedef\tPLIST *PLISTP;\n\n//\n// Count the number of peripherals that are children of this top level hash,\n// and count them by type as well.\n//\nextern\tint count_peripherals(MAPDHASH &info);\n\n//\n// compare_naddr\n//\n// This is part of the peripheral sorting mechanism, whereby peripherals are\n// sorted by the numbers of addresses they use.  Peripherals using fewer\n// addresses are placed first, with peripherals using more addresses placed\n// later.\n//\nextern\tbool\tcompare_naddr(PERIPHP a, PERIPHP b);\n\n//\n// compare_address\n//\n// This is another means of sorting peripherals, this time by their address\n// within their bus.\n//\nextern\tbool\tcompare_address(PERIPHP a, PERIPHP b);\n\n//\n// compare_regaddr\n//\n// When examining registers that are accessed across busses, it becomes\n// important to be able to sort peripherals from the point of view of a master\n// that might be able to reach them.  This is the purpose of the REGBASE\n// address.  This compare sorts with respect to that address\n//\nextern\tbool\tcompare_regaddr(PERIPHP a, PERIPHP b);\n\n/*\n * build_plist\n *\n * Collect our peripherals into one of four lists.  This allows us to have\n * ordered access through the peripherals later.\n */\nextern\tvoid\tbuild_plist(MAPDHASH &info);\n\n#endif\t// PLIST_H\n"
  },
  {
    "path": "sw/predicates.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/predicates.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tA predicate is a function that returns true or false.  This\n//\t\tfile describes the implementation of a series of functions that\n//\tcan be used to determine of what type a given design component is.\n//\tIs it a bus master?  A bus slave?  A programmable interrupt controller?\n//\tetc.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <string.h>\n#include <unistd.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <limits.h>\n#include <ctype.h>\n\n#include \"parser.h\"\n#include \"keys.h\"\n#include \"kveval.h\"\n#include \"legalnotice.h\"\n#include \"bldtestb.h\"\n#include \"bitlib.h\"\n#include \"plist.h\"\n#include \"bldregdefs.h\"\n#include \"ifdefs.h\"\n#include \"bldsim.h\"\n#include \"predicates.h\"\n\n//\n// Is the given location within our hash a master?  Look it up.\n//\n// To be a bus master, it must have a @MTYPE field.\n//\nbool\tisbusmaster(MAPDHASH &phash) {\n\tSTRINGP styp;\n\n\tstyp = getstring(phash, KYMASTER_TYPE);\n\tif (NULL == styp)\n\t\treturn false;\n\tif (KYSCRIPT.compare(*styp) == 0)\n\t\treturn false;\n\treturn true;\n}\n//\n// Does the given location describe access to a bus lying beneath it?\n//\n// To be true, isbusmaster() must be true, and the MASTER.BUS.TYPE field\n// must be one of: SUBBUS, XCLOCK, ARBITER, etc.\n//\nbool\tissubbus(MAPDHASH &phash) {\n\tif (!isperipheral(phash))\n\t\treturn false;\n\tif (!isbusmaster(phash))\n\t\treturn false;\n\tSTRINGP\tmtype = getstring(phash, KYMASTER_TYPE);\n\tif (!mtype)\n\t\treturn false;\n\tif (mtype->compare(KYBUS)==0)\n\t\treturn true;\n\tif (mtype->compare(KYSUBBUS)==0)\n\t\treturn true;\n\tif (mtype->compare(KYXCLOCK)==0)\n\t\treturn true;\n\tif (mtype->compare(KYARBITER)==0)\n\t\treturn true;\n\treturn false;\n}\n\nbool\tisarbiter(MAPDHASH &phash) { return issubbus(phash); }\n\n//\n// Same thing, but when given a location within the tree, rather than a hash\n// value.\nbool\tisbusmaster(MAPT &pmap) {\n\tif (pmap.m_typ != MAPT_MAP)\n\t\treturn false;\n\treturn isbusmaster(*pmap.u.m_m);\n}\n\n//\n// Is the given hash a definition of a peripheral\n//\n// To be a peripheral, it must have a @PTYPE field.\n//\nbool\tisperipheral(MAPDHASH &phash) {\n\treturn (NULL != getstring(phash, KYSLAVE_TYPE));\n\t// return (phash.end() != phash.find(KYSLAVE_TYPE));\n}\n\nbool\tisperipheral(MAPT &pmap) {\n\tif (pmap.m_typ != MAPT_MAP)\n\t\treturn false;\n\treturn isperipheral(*pmap.u.m_m);\n}\n\n//\n// Does the given hash define a programmable interrupt controller?\n//\n// If so, it must have a @PIC.MAX field identifying the maximum number of\n// interrupts that can be assigned to it.\nbool\tispic(MAPDHASH &phash) {\n\treturn (phash.end() != findkey(phash, KYPIC_MAX));\n}\n\nbool\tispic(MAPT &pmap) {\n\tif (pmap.m_typ != MAPT_MAP)\n\t\treturn false;\n\treturn ispic(*pmap.u.m_m);\n}\n\n// Does this reference a memory peripheral?\nbool\tismemory(MAPDHASH &phash) {\n\tSTRINGP\tstrp;\n\n\tstrp = getstring(phash, KYSLAVE_TYPE);\n\tif (!strp)\n\t\treturn false;\n\tif (KYMEMORY.compare(*strp) != 0)\n\t\treturn false;\n\treturn true;\n}\n\nbool\tismemory(MAPT &pmap) {\n\tif (pmap.m_typ != MAPT_MAP)\n\t\treturn false;\n\treturn ismemory(*pmap.u.m_m);\n}\n\n//\n// Does this component have a bus definition within it, or does it reference\n// a bus?\nbool\trefbus(MAPDHASH &phash) {\n\n\tif (NULL != getstring(phash, KYBUS))\n\t\treturn true;\n\t// else if (NULL != getmap(phash, KYBUS)) return true;\n\treturn false;\n}\n\nbool\trefbus(MAPT &pmap) {\n\tif (pmap.m_typ != MAPT_MAP)\n\t\treturn false;\n\treturn refbus(*pmap.u.m_m);\n}\n\n//\n// Does this component have a clock definition within it, or does it reference\n// a clock?\n//\nbool\trefclock(MAPDHASH &phash) {\n\tSTRINGP\tstrp;\n\n\tstrp = getstring(phash, KYCLOCK);\n\tif (!strp)\n\t\treturn false;\n\treturn true;\n}\n\nbool\trefclock(MAPT &pmap) {\n\tif (pmap.m_typ != MAPT_MAP)\n\t\treturn false;\n\treturn refbus(*pmap.u.m_m);\n}\n\n// Does the top level map contain a CPU as one of the peripherals?\nbool\thas_cpu(MAPDHASH &phash) {\n\tMAPDHASH::iterator\tkvpair;\n\tSTRINGP\tstrp;\n\n\tfor(kvpair=phash.begin(); kvpair != phash.end(); kvpair++) {\n\t\tif (kvpair->second.m_typ != MAPT_MAP)\n\t\t\tcontinue;\n\t\tif (!isbusmaster(kvpair->second))\n\t\t\tcontinue;\n\t\tstrp = getstring(kvpair->second.u.m_m, KYMASTER_TYPE);\n\t\tif (NULL == strp)\n\t\t\tcontinue;\n\t\tif (strp->compare(KYCPU)==0)\n\t\t\treturn true;\n\t} return false;\n}\n\nbool\tread_only_option(STRINGP op) {\n\tchar \t*cstr, *tok;\n\tconst char\tDELIMITERS[] = \", \\t\\r\\n\";\n\tbool\tread_only = false;\n\n\tcstr = strdup(op->c_str());\n\ttok = strtok(cstr, DELIMITERS);\n\twhile(NULL != tok) {\n\t\tif (strcasecmp(tok, \"RO\")==0) {\n\t\t\tread_only = true;\n\t\t\tbreak;\n\t\t}\n\t\ttok = strtok(NULL, DELIMITERS);\n\t}\n\n\tfree(cstr);\n\treturn read_only;\n}\n\nbool\twrite_only_option(STRINGP op) {\n\tchar \t*cstr, *tok;\n\tconst char\tDELIMITERS[] = \", \\t\\r\\n\";\n\tbool\twrite_only = false;\n\n\tcstr = strdup(op->c_str());\n\ttok = strtok(cstr, DELIMITERS);\n\twhile(NULL != tok) {\n\t\tif (strcasecmp(tok, \"WO\")==0)\n\t\t\twrite_only = true;\n\t\ttok = strtok(NULL, DELIMITERS);\n\t}\n\n\tfree(cstr);\n\treturn write_only;\n}\n"
  },
  {
    "path": "sw/predicates.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/predicates.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tPREDICATES_H\n#define\tPREDICATES_H\n\n#include <stdio.h>\n#include <string>\n#include <vector>\n#include <algorithm>\n\n#include \"parser.h\"\n\n//\n// Is the given location within our hash a master?  Look it up.\n//\n// To be a bus master, it must have a @MASTER.TYPE field.\n//\nbool\tisbusmaster(MAPDHASH &phash);\n//\n// Does the given location describe access to a bus lying beneath it?\n//\n// To be true, isbusmaster() must be true, and the MASTER.BUS.TYPE field\n// must be one of: SUBBUS, XCLOCK, ARBITER, etc.\n//\nbool\tissubbus(MAPDHASH &phash);\nbool\tisarbiter(MAPDHASH &phash);\n//\n// Same thing, but when given a location within the tree, rather than a hash\n// value.\nbool\tisbusmaster(MAPT &pmap);\n\n//\n// Is the given hash a definition of a peripheral\n//\n// To be a peripheral, it must have a @SLAVE.TYPE field.\n//\nbool\tisperipheral(MAPDHASH &phash);\nbool\tisperipheral(MAPT &pmap);\n\n//\n// Does the given hash define a programmable interrupt controller?\n//\n// If so, it must have a @PIC.MAX field identifying the maximum number of\n// interrupts that can be assigned to it.\nbool\tispic(MAPDHASH &phash);\nbool\tispic(MAPT &pmap);\n\n// Does this reference a memory peripheral?\nbool\tismemory(MAPDHASH &phash);\nbool\tismemory(MAPT &pmap);\n\n// Does component reference a bus?\nbool\trefbus(MAPDHASH &phash);\nbool\trefbus(MAPT &pmap);\n\n// Does component reference a clock?\nbool\trefclock(MAPDHASH &phash);\nbool\trefclock(MAPT &pmap);\n\n// Does the toplevel map contain a CPU?\nbool\thas_cpu(MAPDHASH &phash);\n\n// Does the option set describe a read-only peripheral\nbool\tread_only_option(STRINGP op);\n// bool\tread_only_option(MAPDHASH &phash);\n// Does the option set describe a write-only peripheral\nbool\twrite_only_option(STRINGP op);\n// bool\twrite_only_option(MAPDHASH &phash);\n\n#endif\t// PREDICATES_H\n"
  },
  {
    "path": "sw/subbus.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/subbus.cpp\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\tA subbus component is a special type of bus slave that is also\n//\t\ta bus master on another bus at the same time.  The sub bus\n//\tthat the peripheral is a master of then determines the address range of\n//\tthe peripheral on the bus that it is a slave of.\n//\n//\tClassic examples of subbus's would be bridges.  DMA components are not\n//\tsubbus's, but rather masters and slaves in their own right.\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n\n#include \"plist.h\"\n#include \"businfo.h\"\n#include \"subbus.h\"\n#include \"bitlib.h\"\n#include \"globals.h\"\n#include \"msgs.h\"\n\nSUBBUS::SUBBUS(MAPDHASH *info, STRINGP subname, BUSINFO *subbus) {\n\tp_base = 0;\n\tp_naddr= 0;\n\tp_awid = 0;\n\tp_mask = 0;\n\n\tp_sbaw  = 0;\n\tp_name  = subname;\n\tp_phash = info;\n\tp_master_bus = subbus;\n}\n\nbool\tSUBBUS::isbus(void) { return true; }\nunsigned\tSUBBUS::get_slave_address_width(void) {\n\tunsigned\tawid;\n\n\tassert(p_master_bus);\n\tif (p_master_bus == p_slave_bus)\n\t\tgbl_msg.fatal(\"ERR: Component %s cannot be both slave to bus %s and master of it as a subbus\\n\",\n\t\t\t(p_name->c_str()) ? p_name->c_str() : \"(Unknown?!?!)\",\n\t\t\t(p_master_bus->name()->c_str()) ?\n\t\t\t\t p_master_bus->name()->c_str() : \"(Un-named)\",\n\t\t\t(p_slave_bus->name()->c_str())\n\t\t\t\t? p_slave_bus->name()->c_str() : \"(Un-named)\");\n\tassert(p_master_bus != p_slave_bus);\n\n\t// Calculate the address width for bytes\n\tawid = p_master_bus->address_width();\n\tif (p_master_bus->word_addressing())\n\t\tawid += nextlg(p_master_bus->data_width()/8);\n\n\tp_naddr = (1u<<(awid-nextlg(p_slave_bus->data_width()/8)));\n\n\t// Adjust this to be address width for words --- if required\n\tif (p_slave_bus->word_addressing())\n\t\tawid -= nextlg(p_slave_bus->data_width()/8);\n\n\tif (p_awid != awid) {\n\t\tp_awid = awid;\n\t\tsetvalue(*p_phash, KYSLAVE_AWID, awid);\n\t}\n\n\treturn p_awid;\n}\n\n/*\nbool SUBBUS::get_base_address(MAPDHASH *phash, unsigned &base) {\n\tassert(p_master_bus);\n\tassert(p_master_bus != p_slave_bus);\n\n\tif (p_slave_bus->get_base_address(phash, base)) {\n\t\t// If the bus we are mastering has an offset, add that to our\n\t\t// base address\n\t\tbase += p_base;\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n*/\n\nvoid\tSUBBUS::assign_addresses(void) {\n\tassert(p_master_bus);\n\tassert(p_master_bus != p_slave_bus);\n\n\t// Assign addresses to the bus that we master from here\n\tp_master_bus->assign_addresses();\n}\n\nbool\tSUBBUS::need_translator(void) {\n\tassert(p_slave_bus);\n\tassert(p_master_bus);\n\treturn p_slave_bus->need_translator(p_master_bus);\n}\n"
  },
  {
    "path": "sw/subbus.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//\n// Filename:\tsw/subbus.h\n//\n// Project:\tAutoFPGA, a utility for composing FPGA designs from peripherals\n// {{{\n// Purpose:\t\n//\n// Creator:\tDan Gisselquist, Ph.D.\n//\t\tGisselquist Technology, LLC\n//\n////////////////////////////////////////////////////////////////////////////////\n// }}}\n// Copyright (C) 2017-2024, Gisselquist Technology, LLC\n// {{{\n// This program is free software (firmware): you can redistribute it and/or\n// modify it under the terms of the GNU General Public License as published\n// by the Free Software Foundation, either version 3 of the License, or (at\n// your option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT\n// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or\n// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n// for more details.\n//\n// You should have received a copy of the GNU General Public License along\n// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no\n// target there if the PDF file isn't present.)  If not, see\n// <http://www.gnu.org/licenses/> for a copy.\n// }}}\n// License:\tGPL, v3, as defined and found on www.gnu.org,\n// {{{\n//\t\thttp://www.gnu.org/licenses/gpl.html\n//\n//\n////////////////////////////////////////////////////////////////////////////////\n//\n// }}}\n#ifndef\tSUBBUS_H\n#define\tSUBBUS_H\n\n#include \"plist.h\"\n#include \"businfo.h\"\n\nclass\tSUBBUS : public PERIPH {\npublic:\n\tSUBBUS(MAPDHASH *info, STRINGP subname, BUSINFO *subbus);\n\tvirtual\tbool\tisbus(void);\n\tvirtual\tunsigned\tget_slave_address_width(void);\n\tvoid\tadd(PERIPHP p) {\n\t\tp_master_bus->add(p);\n\t}\n\tvoid\tadd(MAPDHASH *phash) {\n\t\tp_master_bus->add(phash);\n\t}\n\n\tbool get_base_address(MAPDHASH *phash, unsigned &base);\n\n\tvoid\tassign_addresses(void);\n\tbool\tneed_translator(void);\n};\n\n#endif\n"
  }
]